[runtime] Add a workaround for #50529 by locking around pthread_create()/pthread_join...
authorZoltan Varga <vargaz@gmail.com>
Tue, 7 Feb 2017 19:35:50 +0000 (14:35 -0500)
committerGitHub <noreply@github.com>
Tue, 7 Feb 2017 19:35:50 +0000 (14:35 -0500)
mono/metadata/sgen-mono.c
mono/metadata/threads.c
mono/utils/mono-threads.c
mono/utils/mono-threads.h

index f759901a5a0f3202693632de4b61f727490ea4c0..fc82365a9336dee1c36930c1b2305d2e7e335b49 100644 (file)
@@ -2521,7 +2521,13 @@ mono_gc_deregister_root (char* addr)
 int
 mono_gc_pthread_create (pthread_t *new_thread, const pthread_attr_t *attr, void *(*start_routine)(void *), void *arg)
 {
-       return pthread_create (new_thread, attr, start_routine, arg);
+       int res;
+
+       mono_threads_join_lock ();
+       res = pthread_create (new_thread, attr, start_routine, arg);
+       mono_threads_join_unlock ();
+
+       return res;
 }
 #endif
 
index 28b66c8eb3da13ed2d013971115376e0bbaf0628..b94a4ff7ff3a96bc0425f137514931e03b118acc 100644 (file)
@@ -5085,7 +5085,9 @@ mono_threads_join_threads (void)
                        if (thread != pthread_self ()) {
                                MONO_ENTER_GC_SAFE;
                                /* This shouldn't block */
+                               mono_threads_join_lock ();
                                mono_native_thread_join (thread);
+                               mono_threads_join_unlock ();
                                MONO_EXIT_GC_SAFE;
                        }
                } else {
index 401d3b7e3b1e806a3889d7457c66db1ca46eded3..5f719c161e365190573a59626e55b78f513b600f 100644 (file)
@@ -75,6 +75,8 @@ static gboolean mono_threads_inited = FALSE;
 static MonoSemType suspend_semaphore;
 static size_t pending_suspends;
 
+static mono_mutex_t join_mutex;
+
 #define mono_thread_info_run_state(info) (((MonoThreadInfo*)info)->thread_state & THREAD_STATE_MASK)
 
 /*warn at 50 ms*/
@@ -706,6 +708,7 @@ mono_threads_init (MonoThreadInfoCallbacks *callbacks, size_t info_size)
 
        mono_os_sem_init (&global_suspend_semaphore, 1);
        mono_os_sem_init (&suspend_semaphore, 0);
+       mono_os_mutex_init (&join_mutex);
 
        mono_lls_init (&thread_list, NULL);
        mono_thread_smr_init ();
@@ -1231,6 +1234,7 @@ mono_thread_info_yield (void)
 {
        return mono_threads_platform_yield ();
 }
+
 static mono_lazy_init_t sleep_init = MONO_LAZY_INIT_STATUS_NOT_INITIALIZED;
 static MonoCoopMutex sleep_mutex;
 static MonoCoopCond sleep_cond;
@@ -1689,3 +1693,26 @@ mono_thread_info_wait_multiple_handle (MonoThreadHandle **thread_handles, gsize
        else
                g_error ("%s: unknown res value %d", __func__, res);
 }
+
+/*
+ * mono_threads_join_mutex:
+ *
+ *   This mutex is used to avoid races between pthread_create () and pthread_join () on osx, see
+ * https://bugzilla.xamarin.com/show_bug.cgi?id=50529
+ * The code inside the lock should not block.
+ */
+void
+mono_threads_join_lock (void)
+{
+#ifdef TARGET_OSX
+       mono_os_mutex_lock (&join_mutex);
+#endif
+}
+
+void
+mono_threads_join_unlock (void)
+{
+#ifdef TARGET_OSX
+       mono_os_mutex_unlock (&join_mutex);
+#endif
+}
index a5db1c0c4e58bb8ab84904661400b97f758cf4e3..0e77e3956630a51a293468778eaae83ce4bb900e 100644 (file)
@@ -613,4 +613,7 @@ mono_thread_info_wait_one_handle (MonoThreadHandle *handle, guint32 timeout, gbo
 MonoThreadInfoWaitRet
 mono_thread_info_wait_multiple_handle (MonoThreadHandle **thread_handles, gsize nhandles, MonoOSEvent *background_change_event, gboolean waitall, guint32 timeout, gboolean alertable);
 
+void mono_threads_join_lock (void);
+void mono_threads_join_unlock (void);
+
 #endif /* __MONO_THREADS_H__ */