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

ruby-changes:24874

From: kosaki <ko1@a...>
Date: Sun, 9 Sep 2012 15:27:13 +0900 (JST)
Subject: [ruby-changes:24874] kosaki:r36926 (trunk): * thread.c (rb_mutex_lock): stop multiple threads use

kosaki	2012-09-09 15:27:02 +0900 (Sun, 09 Sep 2012)

  New Revision: 36926

  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=36926

  Log:
    * thread.c (rb_mutex_lock): stop multiple threads use
      pthread_cond_timedwait() concurrently. [Bug #6278] [ruby-core:44275]

  Modified files:
    trunk/ChangeLog
    trunk/thread.c

Index: ChangeLog
===================================================================
--- ChangeLog	(revision 36925)
+++ ChangeLog	(revision 36926)
@@ -1,3 +1,8 @@
+Sun Sep  9 15:21:52 2012  KOSAKI Motohiro  <kosaki.motohiro@g...>
+
+	* thread.c (rb_mutex_lock): stop multiple threads use
+	  pthread_cond_timedwait() concurrently. [Bug #6278] [ruby-core:44275]
+
 Sat Sep  8 18:52:22 2012  Nobuyoshi Nakada  <nobu@r...>
 
 	* internal.h (struct rb_classext_struct): move allocator function into
Index: thread.c
===================================================================
--- thread.c	(revision 36925)
+++ thread.c	(revision 36926)
@@ -3911,6 +3911,13 @@
 }
 
 /*
+ * At maximum, only one thread can use cond_timedwait and watch deadlock
+ * periodically. Multiple polling thread (i.e. concurrent deadlock check)
+ * introduces new race conditions. [Bug #6278] [ruby-core:44275]
+ */
+rb_thread_t *patrol_thread = NULL;
+
+/*
  * call-seq:
  *    mutex.lock  -> self
  *
@@ -3947,14 +3954,20 @@
 	     * vm->sleepr is unstable value. we have to avoid both deadlock
 	     * and busy loop.
 	     */
-	    if (vm_living_thread_num(th->vm) == th->vm->sleeper) {
+	    if ((vm_living_thread_num(th->vm) == th->vm->sleeper) &&
+		!patrol_thread) {
 		timeout_ms = 100;
+		patrol_thread = th;
 	    }
+
 	    GVL_UNLOCK_BEGIN();
 	    interrupted = lock_func(th, mutex, timeout_ms);
 	    native_mutex_unlock(&mutex->lock);
 	    GVL_UNLOCK_END();
 
+	    if (patrol_thread == th)
+		patrol_thread = NULL;
+
 	    reset_unblock_function(th, &oldubf);
 
 	    th->locking_mutex = Qfalse;
@@ -4642,6 +4655,7 @@
 
     if (vm_living_thread_num(vm) > vm->sleeper) return;
     if (vm_living_thread_num(vm) < vm->sleeper) rb_bug("sleeper must not be more than vm_living_thread_num(vm)");
+    if (patrol_thread && patrol_thread != GET_THREAD()) return;
 
     st_foreach(vm->living_threads, check_deadlock_i, (st_data_t)&found);
 

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

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