diff --git a/src/mono/System.Private.CoreLib/src/ILLink/ILLink.Descriptors.xml b/src/mono/System.Private.CoreLib/src/ILLink/ILLink.Descriptors.xml
index 7ddd23d78de8ed..2e8bace4a47d8b 100644
--- a/src/mono/System.Private.CoreLib/src/ILLink/ILLink.Descriptors.xml
+++ b/src/mono/System.Private.CoreLib/src/ILLink/ILLink.Descriptors.xml
@@ -278,6 +278,12 @@
+
+
+
+
+
+
diff --git a/src/mono/System.Private.CoreLib/src/System/GC.Mono.cs b/src/mono/System.Private.CoreLib/src/System/GC.Mono.cs
index 21eba8223fd0f9..77a4ac8b75d107 100644
--- a/src/mono/System.Private.CoreLib/src/System/GC.Mono.cs
+++ b/src/mono/System.Private.CoreLib/src/System/GC.Mono.cs
@@ -4,6 +4,7 @@
using System.Diagnostics.Tracing;
using System.Runtime;
using System.Runtime.CompilerServices;
+using System.Runtime.ExceptionServices;
namespace System
{
@@ -149,6 +150,20 @@ public static void ReRegisterForFinalize(object obj)
_ReRegisterForFinalize(obj);
}
+ [UnsafeAccessor(UnsafeAccessorKind.Method, Name = nameof(Finalize))]
+ private static extern void CallFinalize(object o);
+ private static void GuardedFinalize(object o)
+ {
+ try
+ {
+ CallFinalize(o);
+ }
+ catch (Exception ex) when (ExceptionHandling.IsHandledByGlobalHandler(ex))
+ {
+ // the handler returned "true" means the exception is now "handled" and we should continue.
+ }
+ }
+
[MethodImplAttribute(MethodImplOptions.InternalCall)]
public static extern long GetTotalMemory(bool forceFullCollection);
diff --git a/src/mono/mono/metadata/class-internals.h b/src/mono/mono/metadata/class-internals.h
index 5fa79bcca9c6e7..ba56a62ad6b818 100644
--- a/src/mono/mono/metadata/class-internals.h
+++ b/src/mono/mono/metadata/class-internals.h
@@ -889,6 +889,7 @@ typedef struct {
MonoClass *threadabortexception_class;
MonoClass *thread_class;
MonoClass *internal_thread_class;
+ MonoClass *gc_class;
MonoClass *autoreleasepool_class;
MonoClass *mono_method_message_class;
MonoClass *field_info_class;
diff --git a/src/mono/mono/metadata/domain.c b/src/mono/mono/metadata/domain.c
index 967e33f28df61c..13bb7a408564f7 100644
--- a/src/mono/mono/metadata/domain.c
+++ b/src/mono/mono/metadata/domain.c
@@ -238,6 +238,9 @@ mono_init_internal (const char *root_domain_name)
/* There is only one thread class */
mono_defaults.internal_thread_class = mono_defaults.thread_class;
+ mono_defaults.gc_class = mono_class_load_from_name (
+ mono_defaults.corlib, "System", "GC");
+
#if defined(HOST_DARWIN)
mono_defaults.autoreleasepool_class = mono_class_try_load_from_name (
mono_defaults.corlib, "System.Threading", "AutoreleasePool");
diff --git a/src/mono/mono/metadata/gc.c b/src/mono/mono/metadata/gc.c
index 9c49d2803cd95a..7065b6fe85fabd 100644
--- a/src/mono/mono/metadata/gc.c
+++ b/src/mono/mono/metadata/gc.c
@@ -81,9 +81,8 @@ static gboolean finalizer_thread_exited;
static MonoCoopCond exited_cond;
static MonoInternalThread *gc_thread;
-#ifndef HOST_WASM
-static RuntimeInvokeFunction finalize_runtime_invoke;
-#endif
+
+static MonoMethod *finalize_helper;
/*
* This must be a GHashTable, since these objects can't be finalized
@@ -280,31 +279,14 @@ mono_gc_run_finalize (void *obj, void *data)
return;
}
-
- /*
- * To avoid the locking plus the other overhead of mono_runtime_invoke_checked (),
- * create and precompile a wrapper which calls the finalize method using
- * a CALLVIRT.
- */
if (mono_log_finalizers)
g_log ("mono-gc-finalizers", G_LOG_LEVEL_MESSAGE, "<%s at %p> Compiling finalizer.", o_name, o);
-#ifndef HOST_WASM
- if (!finalize_runtime_invoke) {
- MonoMethod *finalize_method = mono_class_get_method_from_name_checked (mono_defaults.object_class, "Finalize", 0, 0, error);
+ if (!finalize_helper) {
+ finalize_helper = mono_class_get_method_from_name_checked (mono_defaults.gc_class, "GuardedFinalize", 1, 0, error);
mono_error_assert_ok (error);
- MonoMethod *invoke = mono_marshal_get_runtime_invoke (finalize_method, TRUE);
-
- finalize_runtime_invoke = (RuntimeInvokeFunction)mono_compile_method_checked (invoke, error);
- mono_error_assert_ok (error); /* expect this not to fail */
}
- RuntimeInvokeFunction runtime_invoke = finalize_runtime_invoke;
-#endif
-
- mono_runtime_class_init_full (o->vtable, error);
- goto_if_nok (error, unhandled_error);
-
if (G_UNLIKELY (MONO_GC_FINALIZE_INVOKE_ENABLED ())) {
MONO_GC_FINALIZE_INVOKE ((unsigned long)o, mono_object_get_size_internal (o),
o_ns, o_name);
@@ -315,23 +297,15 @@ mono_gc_run_finalize (void *obj, void *data)
MONO_PROFILER_RAISE (gc_finalizing_object, (o));
-#ifdef HOST_WASM
- MonoMethod* finalizer = mono_class_get_finalizer (o->vtable->klass);
- if (finalizer) { // null finalizers work fine when using the vcall invoke as Object has an empty one
- gpointer params [1];
- params [0] = NULL;
- mono_runtime_try_invoke (finalizer, o, params, &exc, error);
- }
-#else
- runtime_invoke (o, NULL, &exc, NULL);
-#endif
+ gpointer params [1];
+ params [0] = o;
+ mono_runtime_try_invoke (finalize_helper, NULL, params, &exc, error);
MONO_PROFILER_RAISE (gc_finalized_object, (o));
if (mono_log_finalizers)
g_log ("mono-gc-finalizers", G_LOG_LEVEL_MESSAGE, "<%s at %p> Returned from finalizer.", o_name, o);
-unhandled_error:
if (!is_ok (error))
exc = (MonoObject*)mono_error_convert_to_exception (error);
if (exc)
diff --git a/src/mono/mono/mini/aot-compiler.c b/src/mono/mono/mini/aot-compiler.c
index 033ef0d96b94b3..67c4daaa835ca9 100644
--- a/src/mono/mono/mini/aot-compiler.c
+++ b/src/mono/mono/mini/aot-compiler.c
@@ -4977,7 +4977,7 @@ add_full_aot_wrappers (MonoAotCompile *acfg)
add_method (acfg, get_runtime_invoke_sig (csig));
/* runtime-invoke used by finalizers */
- add_method (acfg, get_runtime_invoke (acfg, get_method_nofail (mono_defaults.object_class, "Finalize", 0, 0), TRUE));
+ add_method (acfg, get_runtime_invoke (acfg, get_method_nofail (mono_defaults.gc_class, "GuardedFinalize", 1, 0), FALSE));
/* This is used by mono_runtime_capture_context () */
method = mono_get_context_capture_method ();
diff --git a/src/mono/mono/mini/mini-runtime.c b/src/mono/mono/mini/mini-runtime.c
index ddb1bfb6201bc2..468534bc16ba41 100644
--- a/src/mono/mono/mini/mini-runtime.c
+++ b/src/mono/mono/mini/mini-runtime.c
@@ -5363,7 +5363,7 @@ mono_precompile_assembly (MonoAssembly *ass, void *user_data)
mono_error_cleanup (error); /* FIXME don't swallow the error */
continue;
}
- if (strcmp (method->name, "Finalize") == 0) {
+ if (strcmp (method->name, "GuardedFinalize") == 0) {
invoke = mono_marshal_get_runtime_invoke (method, FALSE);
mono_compile_method_checked (invoke, error);
mono_error_assert_ok (error);
diff --git a/src/tests/issues.targets b/src/tests/issues.targets
index 591eb79f0fd68e..53cdc97de4306e 100644
--- a/src/tests/issues.targets
+++ b/src/tests/issues.targets
@@ -1732,8 +1732,11 @@
https://github.com/dotnet/runtime/issues/98628
-
- NYI on Mono
+
+ https://github.com/dotnet/runtime/issues/47624
+
+
+ Test issue. The test relies on overriding the process return code.