[runtime] Make thread abort synchronous
authorAlexander Kyte <alexander.kyte@xamarin.com>
Fri, 8 May 2015 16:07:42 +0000 (12:07 -0400)
committerAlexander Kyte <alexander.kyte@xamarin.com>
Fri, 8 May 2015 17:24:53 +0000 (13:24 -0400)
Due to asynchronous abortion a crash is being seen on
posix systems where the abort signal handler is having a
data race and not exiting the suspend signal handler early.

When it tries to make a state transition because of this, it
cannot and it crashes.

This fixes it by making it synchronous.

mono/utils/mono-threads-posix.c
mono/utils/mono-threads.c
mono/utils/mono-threads.h

index 19fd8b7c12e75f7836cf00dba1251002b96dd3c5..b74bf6448705c17ba613ecc7cd151ffe9c8ea52c 100644 (file)
@@ -452,6 +452,7 @@ suspend_signal_handler (int _dummy, siginfo_t *info, void *context)
        if (current->syscall_break_signal) {
                current->syscall_break_signal = FALSE;
                THREADS_SUSPEND_DEBUG ("\tsyscall break for %p\n", current);
+               mono_threads_notify_initiator_of_abort (current);
                goto done;
        }
 
@@ -582,7 +583,8 @@ mono_threads_core_abort_syscall (MonoThreadInfo *info)
        This signal should not be interpreted as a suspend request.
        */
        info->syscall_break_signal = TRUE;
-       mono_threads_pthread_kill (info, abort_signal_num);
+       if (!mono_threads_pthread_kill (info, abort_signal_num))
+               mono_threads_add_to_pending_operation_set (info);
 }
 
 gboolean
index b720063ad63eb100e333b4ca6ec722a7c4c4adb7..f1b26bc1d40b41a318a3dbb679f353550f711244 100644 (file)
@@ -64,7 +64,15 @@ static gboolean unified_suspend_enabled;
 /*abort at 1 sec*/
 #define SLEEP_DURATION_BEFORE_ABORT 200
 
-static int suspend_posts, resume_posts, waits_done, pending_ops;
+static int suspend_posts, resume_posts, abort_posts, waits_done, pending_ops;
+
+void
+mono_threads_notify_initiator_of_abort (MonoThreadInfo* info)
+{
+       THREADS_SUSPEND_DEBUG ("[INITIATOR-NOTIFY-ABORT] %p\n", mono_thread_info_get_tid (info));
+       MONO_SEM_POST (&suspend_semaphore);
+       InterlockedIncrement (&abort_posts);
+}
 
 void
 mono_threads_notify_initiator_of_suspend (MonoThreadInfo* info)
@@ -121,7 +129,8 @@ void
 mono_threads_begin_global_suspend (void)
 {
        g_assert (pending_suspends == 0);
-       THREADS_SUSPEND_DEBUG ("------ BEGIN GLOBAL OP sp %d rp %d wd %d po %d\n", suspend_posts, resume_posts, waits_done, pending_ops);
+       THREADS_SUSPEND_DEBUG ("------ BEGIN GLOBAL OP sp %d rp %d ap %d wd %d po %d\n", suspend_posts, resume_posts,
+               abort_posts, waits_done, pending_ops);
        mono_threads_core_begin_global_suspend ();
 }
 
@@ -129,7 +138,8 @@ void
 mono_threads_end_global_suspend (void) 
 {
        g_assert (pending_suspends == 0);
-       THREADS_SUSPEND_DEBUG ("------ END GLOBAL OP sp %d rp %d wd %d po %d\n", suspend_posts, resume_posts, waits_done, pending_ops);
+       THREADS_SUSPEND_DEBUG ("------ END GLOBAL OP sp %d rp %d ap %d wd %d po %d\n", suspend_posts, resume_posts,
+               abort_posts, waits_done, pending_ops);
        mono_threads_core_end_global_suspend ();
 }
 
@@ -997,10 +1007,14 @@ mono_thread_info_abort_socket_syscall_for_close (MonoNativeThreadId tid)
        }
 
        mono_thread_info_suspend_lock ();
+       mono_threads_begin_global_suspend ();
 
        mono_threads_core_abort_syscall (info);
+       mono_threads_wait_pending_operations ();
 
        mono_hazard_pointer_clear (hp, 1);
+
+       mono_threads_end_global_suspend ();
        mono_thread_info_suspend_unlock ();
 }
 
index eaefe4dec701a5809b16c0a99e49a1b5c42e778b..54f3e8b63d458c80d39374e85c4a59ab54397062 100644 (file)
@@ -556,6 +556,11 @@ This tells the resume initiator that we completed resume duties and will return
 */
 void mono_threads_notify_initiator_of_resume (THREAD_INFO_TYPE* info);
 
+/*
+This tells the resume initiator that we completed abort duties and will return to previous state.
+*/
+void mono_threads_notify_initiator_of_abort (THREAD_INFO_TYPE* info);
+
 /* Thread state machine functions */
 
 typedef enum {