Skip to content

Commit

Permalink
[runtime] Handle fatal managed exceptions a bit better in the runtime. (
Browse files Browse the repository at this point in the history
#15029)

Handle managed exceptions a bit better when we know there won't be any other
managed frames further up the stack (such as in the main method). In this
case, there's no use in trying to convert the managed exception into an
Objective-C exception, because we already know the process will be terminated.

Instead just print the exception to stderr, and abort immediately.

This means we'll actually get some useful information printed to stderr.
  • Loading branch information
rolfbjarne authored May 16, 2022
1 parent 61ef886 commit 27d1d02
Show file tree
Hide file tree
Showing 3 changed files with 18 additions and 16 deletions.
10 changes: 3 additions & 7 deletions runtime/monotouch-main.m
Original file line number Diff line number Diff line change
Expand Up @@ -443,26 +443,22 @@ - (void) memoryWarning: (NSNotification *) sender

if (xamarin_executable_name) {
assembly = xamarin_open_and_register (xamarin_executable_name, &exception_gchandle);
if (exception_gchandle != NULL)
xamarin_process_managed_exception_gchandle (exception_gchandle);
xamarin_process_fatal_exception_gchandle (exception_gchandle, "An exception occurred while opening the main executable");
} else {
const char *last_slash = strrchr (argv [0], '/');
const char *basename = last_slash ? last_slash + 1 : argv [0];
char *aname = xamarin_strdup_printf ("%s.exe", basename);

assembly = xamarin_open_and_register (aname, &exception_gchandle);
xamarin_free (aname);

if (exception_gchandle != NULL)
xamarin_process_managed_exception_gchandle (exception_gchandle);
xamarin_process_fatal_exception_gchandle (exception_gchandle, "An exception occurred while opening an assembly");
}

if (xamarin_supports_dynamic_registration) {
MonoReflectionAssembly *rassembly = mono_assembly_get_object (mono_domain_get (), assembly);
xamarin_register_entry_assembly (rassembly, &exception_gchandle);
xamarin_mono_object_release (&rassembly);
if (exception_gchandle != NULL)
xamarin_process_managed_exception_gchandle (exception_gchandle);
xamarin_process_fatal_exception_gchandle (exception_gchandle, "An exception occurred while opening the entry assembly");
}

DEBUG_LAUNCH_TIME_PRINT ("\tAssembly register time");
Expand Down
23 changes: 14 additions & 9 deletions runtime/runtime.m
Original file line number Diff line number Diff line change
Expand Up @@ -1087,6 +1087,17 @@ -(void) xamarinSetFlags: (enum XamarinGCHandleFlags) flags;
xamarin_process_managed_exception_gchandle (gchandle);
}

void
xamarin_process_fatal_exception_gchandle (GCHandle gchandle, const char *message)
{
if (gchandle == INVALID_GCHANDLE)
return;

NSString *fatal_message = [NSString stringWithFormat:@"%s\n%@", message, xamarin_print_all_exceptions (gchandle)];
NSLog (@PRODUCT ": %@", fatal_message);
xamarin_assertion_message ([fatal_message UTF8String]);
}

// Because this function won't always return, it will take ownership of the GCHandle and free it.
void
xamarin_process_managed_exception_gchandle (GCHandle gchandle)
Expand Down Expand Up @@ -1136,7 +1147,7 @@ -(void) xamarinSetFlags: (enum XamarinGCHandleFlags) flags;
while (xamarin_gc_pump) {
GCHandle exception_gchandle = INVALID_GCHANDLE;
xamarin_gc_collect (&exception_gchandle);
xamarin_process_managed_exception_gchandle (exception_gchandle);
xamarin_process_fatal_exception_gchandle (exception_gchandle, "An exception occurred while running the GC in a loop");
MONO_ENTER_GC_SAFE;
usleep (1000000);
MONO_EXIT_GC_SAFE;
Expand Down Expand Up @@ -1300,16 +1311,10 @@ -(void) xamarinSetFlags: (enum XamarinGCHandleFlags) flags;
#endif // defined(CORECLR_RUNTIME)

xamarin_bridge_call_runtime_initialize (&options, &exception_gchandle);
if (exception_gchandle != INVALID_GCHANDLE) {
NSLog (@PRODUCT ": An exception occurred when calling Runtime.Initialize:\n%@", xamarin_print_all_exceptions (exception_gchandle));
xamarin_assertion_message ("Can't continue if Runtime.Initialize fails.");
}
xamarin_process_fatal_exception_gchandle (exception_gchandle, "An exception occurred while calling Runtime.Initialize");

xamarin_bridge_register_product_assembly (&exception_gchandle);
if (exception_gchandle != INVALID_GCHANDLE) {
NSLog (@PRODUCT ": An exception occurred when registering the product assembly:\n%@", xamarin_print_all_exceptions (exception_gchandle));
xamarin_assertion_message ("Can't continue if registering the product assembly fails.");
}
xamarin_process_fatal_exception_gchandle (exception_gchandle, "An exception occurred while registering the product assembly");

#if !defined (CORECLR_RUNTIME)
xamarin_install_mono_profiler (); // must be called before xamarin_install_nsautoreleasepool_hooks or xamarin_enable_new_refcount
Expand Down
1 change: 1 addition & 0 deletions runtime/xamarin/runtime.h
Original file line number Diff line number Diff line change
Expand Up @@ -253,6 +253,7 @@ void xamarin_process_nsexception (NSException *exc);
void xamarin_process_nsexception_using_mode (NSException *ns_exception, bool throwManagedAsDefault, GCHandle *output_exception);
void xamarin_process_managed_exception (MonoObject *exc);
void xamarin_process_managed_exception_gchandle (GCHandle gchandle);
void xamarin_process_fatal_exception_gchandle (GCHandle gchandle, const char *message);
void xamarin_throw_product_exception (int code, const char *message);
GCHandle xamarin_create_product_exception (int code, const char *message);
GCHandle xamarin_create_product_exception_with_inner_exception (int code, GCHandle inner_exception_gchandle /* will be freed */, const char *message);
Expand Down

5 comments on commit 27d1d02

@vs-mobiletools-engineering-service2
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💻 [CI Build] Tests on macOS Mac Catalina (10.15) passed 💻

All tests on macOS Mac Catalina (10.15) passed.

Pipeline on Agent
Hash: 27d1d0292b7dba0fc8bd7387b2733fedd18ace5a

@vs-mobiletools-engineering-service2
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💻 [CI Build] Tests on macOS M1 - Mac Big Sur (11.5) passed 💻

All tests on macOS M1 - Mac Big Sur (11.5) passed.

Pipeline on Agent
Hash: 27d1d0292b7dba0fc8bd7387b2733fedd18ace5a

@vs-mobiletools-engineering-service2
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📋 [CI Build] API Diff 📋

API Current PR diff

ℹ️ API Diff (from PR only) (please review changes)

View API diff
View dotnet API diff
View dotnet legacy API diff
View dotnet iOS-MacCatalayst API diff

API diff

✅ API Diff from stable

View API diff
View dotnet API diff
View dotnet legacy API diff
View dotnet iOS-MacCatalayst API diff

Generator diff

Generator Diff (no change)

Pipeline on Agent XAMMINI-058.Monterey'
Hash: 27d1d0292b7dba0fc8bd7387b2733fedd18ace5a

@vs-mobiletools-engineering-service2
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📚 [CI Build] Artifacts 📚

Packages generated

View packages

Pipeline on Agent XAMMINI-061.Monterey
Hash: 27d1d0292b7dba0fc8bd7387b2733fedd18ace5a

@vs-mobiletools-engineering-service2
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ [CI Build] Tests passed on VSTS: simulator tests iOS. ✅

Tests passed on VSTS: simulator tests iOS.

🎉 All 234 tests passed 🎉

Pipeline on Agent XAMBOT-1023.Monterey'
[runtime] Handle fatal managed exceptions a bit better in the runtime. (#15029)

Please sign in to comment.