diff --git a/mcs/class/referencesource/mscorlib/system/exception.cs b/mcs/class/referencesource/mscorlib/system/exception.cs index 89c57758e963..19a9e6c6c95a 100644 --- a/mcs/class/referencesource/mscorlib/system/exception.cs +++ b/mcs/class/referencesource/mscorlib/system/exception.cs @@ -1138,6 +1138,9 @@ internal Exception FixRemotingException () return this; } + + [MethodImplAttribute(MethodImplOptions.InternalCall)] + internal static extern void ReportUnhandledException(Exception exception); #endif } diff --git a/mcs/class/referencesource/mscorlib/system/threading/synchronizationcontext.cs b/mcs/class/referencesource/mscorlib/system/threading/synchronizationcontext.cs index 3e092bb3e31b..2df1364d2aa9 100644 --- a/mcs/class/referencesource/mscorlib/system/threading/synchronizationcontext.cs +++ b/mcs/class/referencesource/mscorlib/system/threading/synchronizationcontext.cs @@ -297,6 +297,11 @@ private static SynchronizationContext GetThreadLocalContext() context = AndroidPlatform.GetDefaultSyncContext (); #endif +#if UNITY_AOT + if (context == null) + context = OSSpecificSynchronizationContext.Get(); +#endif + return context; } @@ -375,4 +380,93 @@ private static int InvokeWaitMethodHelper(SynchronizationContext syncContext, In } #endif } + +#if UNITY_AOT + class OSSpecificSynchronizationContext : SynchronizationContext + { + object m_OSSynchronizationContext; + private static readonly ConditionalWeakTable s_ContextCache = new ConditionalWeakTable(); + + private OSSpecificSynchronizationContext(object osContext) + { + m_OSSynchronizationContext = osContext; + } + + public static OSSpecificSynchronizationContext Get() + { + var osContext = GetOSContext(); + if (osContext == null) + return null; + + return s_ContextCache.GetValue(osContext, _osContext => new OSSpecificSynchronizationContext(_osContext)); + } + + public override SynchronizationContext CreateCopy() + { + return new OSSpecificSynchronizationContext(m_OSSynchronizationContext); + } + + public override void Send(SendOrPostCallback d, object state) + { + throw new NotSupportedException(); + } + + public override void Post(SendOrPostCallback d, object state) + { + var callback = Marshal.GetFunctionPointerForDelegate((InvocationEntryDelegate)InvocationEntry); + var invocationContext = new InvocationContext(d, state); + var invocationContextHandle = GCHandle.Alloc(invocationContext); + PostInternal(m_OSSynchronizationContext, callback, GCHandle.ToIntPtr(invocationContextHandle)); + } + + private delegate void InvocationEntryDelegate(IntPtr arg); + + [MonoPInvokeCallback(typeof(InvocationEntryDelegate))] + private static void InvocationEntry(IntPtr arg) + { + try + { + var invocationContextHandle = GCHandle.FromIntPtr(arg); + var invocationContext = (InvocationContext)invocationContextHandle.Target; + invocationContextHandle.Free(); + invocationContext.Invoke(); + } + catch (Exception e) + { + Exception.ReportUnhandledException(e); + } + } + + [AttributeUsage (AttributeTargets.Method)] + sealed class MonoPInvokeCallbackAttribute : Attribute + { + public MonoPInvokeCallbackAttribute(Type t) + { + } + } + + class InvocationContext + { + private SendOrPostCallback m_Delegate; + private object m_State; + + public InvocationContext(SendOrPostCallback d, object state) + { + m_Delegate = d; + m_State = state; + } + + public void Invoke() + { + m_Delegate(m_State); + } + } + + [MethodImplAttribute(MethodImplOptions.InternalCall)] + private extern static object GetOSContext(); + + [MethodImplAttribute(MethodImplOptions.InternalCall)] + private extern static void PostInternal(object osSynchronizationContext, IntPtr callback, IntPtr arg); + } +#endif } diff --git a/mono/metadata/exception.c b/mono/metadata/exception.c index db668d23f658..b514e7ac3102 100644 --- a/mono/metadata/exception.c +++ b/mono/metadata/exception.c @@ -1533,3 +1533,10 @@ mono_error_convert_to_exception_handle (MonoError *error) return is_ok (error) ? MONO_HANDLE_CAST (MonoException, NULL_HANDLE) : MONO_HANDLE_NEW (MonoException, mono_error_convert_to_exception (error)); } + +void +ves_icall_System_Exception_ReportUnhandledException(MonoObject *exc) +{ + mono_unhandled_exception_internal (exc); + mono_invoke_unhandled_exception_hook (exc); +} \ No newline at end of file diff --git a/mono/metadata/exception.h b/mono/metadata/exception.h index 155c23c7e774..bd012adeb6e7 100644 --- a/mono/metadata/exception.h +++ b/mono/metadata/exception.h @@ -172,6 +172,9 @@ typedef void (*MonoUnhandledExceptionFunc) (MonoObject *exc, void *user MONO_API void mono_install_unhandled_exception_hook (MonoUnhandledExceptionFunc func, void *user_data); void mono_invoke_unhandled_exception_hook (MonoObject *exc); +void +ves_icall_System_Exception_ReportUnhandledException (MonoObject *exc); + MONO_END_DECLS #endif /* _MONO_METADATA_EXCEPTION_H_ */ diff --git a/mono/metadata/icall-def.h b/mono/metadata/icall-def.h index c07299a85d12..db60b2e16274 100644 --- a/mono/metadata/icall-def.h +++ b/mono/metadata/icall-def.h @@ -343,6 +343,10 @@ HANDLES(ENV_17, "internalGetEnvironmentVariable_native", ves_icall_System_Enviro HANDLES(ENV_18, "internalGetGacPath", ves_icall_System_Environment_GetGacPath, MonoString, 0, ()) HANDLES(ENV_19, "internalGetHome", ves_icall_System_Environment_InternalGetHome, MonoString, 0, ()) NOHANDLES(ICALL(ENV_20, "set_ExitCode", mono_environment_exitcode_set)) + +ICALL_TYPE(EXCEPTION, "System.Exception", EXCEPTION_1) +NOHANDLES(ICALL(EXCEPTION_1, "ReportUnhandledException", ves_icall_System_Exception_ReportUnhandledException)) + ICALL_TYPE(GC, "System.GC", GC_10) NOHANDLES(ICALL(GC_10, "GetAllocatedBytesForCurrentThread", ves_icall_System_GC_GetAllocatedBytesForCurrentThread)) NOHANDLES(ICALL(GC_0, "GetCollectionCount", ves_icall_System_GC_GetCollectionCount)) @@ -1031,6 +1035,10 @@ HANDLES(NATIVEC_3, "OpenEvent_icall", ves_icall_System_Threading_Events_OpenEven NOHANDLES(ICALL(NATIVEC_4, "ResetEvent_internal", ves_icall_System_Threading_Events_ResetEvent_internal)) NOHANDLES(ICALL(NATIVEC_5, "SetEvent_internal", ves_icall_System_Threading_Events_SetEvent_internal)) +ICALL_TYPE(OSSYNCCONTEXT, "System.Threading.OSSpecificSynchronizationContext", OSSYNCCONTEXT_1) +NOHANDLES(ICALL(OSSYNCCONTEXT_1, "GetOSContext", ves_icall_System_Threading_OSSpecificSynchronizationContext_GetOSContext)) +NOHANDLES(ICALL(OSSYNCCONTEXT_2, "PostInternal", ves_icall_System_Threading_OSSpecificSynchronizationContext_PostInternal)) + ICALL_TYPE(SEMA, "System.Threading.Semaphore", SEMA_1) NOHANDLES(ICALL(SEMA_1, "CreateSemaphore_icall", ves_icall_System_Threading_Semaphore_CreateSemaphore_icall)) NOHANDLES(ICALL(SEMA_2, "OpenSemaphore_icall", ves_icall_System_Threading_Semaphore_OpenSemaphore_icall)) diff --git a/mono/metadata/icall.c b/mono/metadata/icall.c index b87d9dd4d524..1a647c9520db 100644 --- a/mono/metadata/icall.c +++ b/mono/metadata/icall.c @@ -9850,3 +9850,16 @@ ves_icall_System_Net_NetworkInformation_LinuxNetworkChange_CloseNLSocket (gpoint #undef ICALL #undef NOHANDLES #undef MONO_HANDLE_REGISTER_ICALL + +MonoObjectHandle +ves_icall_System_Threading_OSSpecificSynchronizationContext_GetOSContext () +{ + return NULL_HANDLE; +} + +void +ves_icall_System_Threading_OSSpecificSynchronizationContext_PostInternal (gpointer callback, gpointer arg) +{ + /* This isn't actually reachable since ves_icall_System_Threading_OSSpecificSynchronizationContext_GetOSContext always returns NULL */ + mono_set_pending_exception (mono_exception_from_name_msg (mono_get_corlib (), "System", "NotImplementedException", "System.Threading.InteropServices.OSSpecificSynchronizationContext.PostInternal internal call is not implemented.")); +} diff --git a/mono/metadata/threads-types.h b/mono/metadata/threads-types.h index 4ad22c04e394..4939f9a82aae 100644 --- a/mono/metadata/threads-types.h +++ b/mono/metadata/threads-types.h @@ -597,4 +597,10 @@ mono_interlocked_unlock(void) { } #endif +MonoObjectHandle +ves_icall_System_Threading_OSSpecificSynchronizationContext_GetOSContext (); + +void +ves_icall_System_Threading_OSSpecificSynchronizationContext_PostInternal (gpointer callback, gpointer arg); + #endif /* _MONO_METADATA_THREADS_TYPES_H_ */