Merge pull request #5504 from ntherning/wait-for-native-thread-to-die-in-Thread-Join
authorNiklas Therning <niklas@therning.org>
Mon, 11 Sep 2017 09:07:53 +0000 (11:07 +0200)
committerGitHub <noreply@github.com>
Mon, 11 Sep 2017 09:07:53 +0000 (11:07 +0200)
Wait for the native thread to die in Thread.Join() on Windows

1  2 
mono/metadata/threads.c

diff --combined mono/metadata/threads.c
index c97f7f3f53cca5e0fc080224d1073b2053d32045,4e29232b78557608570ce0052c1464e348ddda2f..3eb6b3b623c8994cf3b2442b79a4270c2eebcc0b
@@@ -1802,7 -1802,7 +1802,7 @@@ mono_join_uninterrupted (MonoThreadHand
  }
  
  gboolean
- ves_icall_System_Threading_Thread_Join_internal(MonoThread *this_obj, int ms)
+ ves_icall_System_Threading_Thread_Join_internal (MonoThread *this_obj, int ms)
  {
        MonoInternalThread *thread = this_obj->internal_thread;
        MonoThreadHandle *handle = thread->handle;
                return FALSE;
        }
  
+       MonoNativeThreadId tid = thread_get_tid (thread);
        UNLOCK_THREAD (thread);
  
-       if(ms== -1) {
-               ms=MONO_INFINITE_WAIT;
-       }
+       if (ms == -1)
+               ms = MONO_INFINITE_WAIT;
        THREAD_DEBUG (g_message ("%s: joining thread handle %p, %d ms", __func__, handle, ms));
-       
        mono_thread_set_state (cur_thread, ThreadState_WaitSleepJoin);
  
-       ret=mono_join_uninterrupted (handle, ms, &error);
+       ret = mono_join_uninterrupted (handle, ms, &error);
  
        mono_thread_clr_state (cur_thread, ThreadState_WaitSleepJoin);
  
        mono_error_set_pending_exception (&error);
  
-       if(ret==MONO_THREAD_INFO_WAIT_RET_SUCCESS_0) {
+       if (ret == MONO_THREAD_INFO_WAIT_RET_SUCCESS_0) {
                THREAD_DEBUG (g_message ("%s: join successful", __func__));
  
-               return(TRUE);
+ #ifdef HOST_WIN32
+               /* TODO: Do this on Unix platforms as well. See PR #5454 for context.  */
+               /* Wait for the thread to really exit */
+               MONO_ENTER_GC_SAFE;
+               /* This shouldn't block */
+               mono_threads_join_lock ();
+               mono_native_thread_join (tid);
+               mono_threads_join_unlock ();
+               MONO_EXIT_GC_SAFE;
+ #endif
+               return TRUE;
        }
        
        THREAD_DEBUG (g_message ("%s: join failed", __func__));
  
-       return(FALSE);
+       return FALSE;
  }
  
  #define MANAGED_WAIT_FAILED 0x7fffffff
@@@ -3037,8 -3049,6 +3049,8 @@@ mono_thread_callbacks_init (void
  void
  mono_thread_cleanup (void)
  {
 +      mono_threads_join_threads ();
 +
  #if !defined(RUN_IN_SUBTHREAD) && !defined(HOST_WIN32)
        /* The main thread must abandon any held mutexes (particularly
         * important for named mutexes as they are shared across