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
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 committed May 13, 2022
1 parent 4b55815 commit feb4aaf
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

0 comments on commit feb4aaf

Please sign in to comment.