[前][次][番号順一覧][スレッド一覧]

ruby-changes:53250

From: normal <ko1@a...>
Date: Wed, 31 Oct 2018 11:31:20 +0900 (JST)
Subject: [ruby-changes:53250] normal:r65465 (trunk): thread_pthread.c (ubf_select): avoid deadlock on contention

normal	2018-10-31 11:31:15 +0900 (Wed, 31 Oct 2018)

  New Revision: 65465

  https://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=revision&revision=65465

  Log:
    thread_pthread.c (ubf_select): avoid deadlock on contention
    
    vm->gvl.lock can be held by another thread, we must not wait
    on it when called by the MJIT worker thread when it migrates
    work to another thread.  ubf_select is designed to do retrying
    anyways, so it has no obligation to wake up a timer thread.
    
    cf.  http://ci.rvm.jp/results/trunk-mjit-wait@silicon-docker/1437880

  Modified files:
    trunk/thread_pthread.c
Index: thread_pthread.c
===================================================================
--- thread_pthread.c	(revision 65464)
+++ thread_pthread.c	(revision 65465)
@@ -1342,11 +1342,17 @@ ubf_select(void *ptr) https://github.com/ruby/ruby/blob/trunk/thread_pthread.c#L1342
      * in unblock_function_clear.
      */
     if (cur != vm->gvl.timer && cur != sigwait_th) {
-        rb_native_mutex_lock(&vm->gvl.lock);
-        if (!vm->gvl.timer) {
-            rb_thread_wakeup_timer_thread(-1);
+        /*
+         * Double-checked locking above was to prevent nested locking
+         * by the SAME thread.  We use trylock here to prevent deadlocks
+         * between DIFFERENT threads
+         */
+        if (native_mutex_trylock(&vm->gvl.lock) == 0) {
+            if (!vm->gvl.timer) {
+                rb_thread_wakeup_timer_thread(-1);
+            }
+            rb_native_mutex_unlock(&vm->gvl.lock);
         }
-        rb_native_mutex_unlock(&vm->gvl.lock);
     }
 
     ubf_wakeup_thread(th);

--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]