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

ruby-changes:31069

From: nobu <ko1@a...>
Date: Sat, 5 Oct 2013 11:21:18 +0900 (JST)
Subject: [ruby-changes:31069] nobu:r43148 (trunk): thread.c: fix some mutexes remaining locked after forking

nobu	2013-10-05 11:21:12 +0900 (Sat, 05 Oct 2013)

  New Revision: 43148

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

  Log:
    thread.c: fix some mutexes remaining locked after forking
    
    * thread.c (terminate_atfork_i): fix locking mutexes not unlocked in
      forks when not tracked in thread.  [ruby-core:55102] [Bug #8433]

  Modified files:
    trunk/ChangeLog
    trunk/test/ruby/test_thread.rb
    trunk/thread.c
Index: ChangeLog
===================================================================
--- ChangeLog	(revision 43147)
+++ ChangeLog	(revision 43148)
@@ -1,3 +1,8 @@ https://github.com/ruby/ruby/blob/trunk/ChangeLog#L1
+Sat Oct  5 11:20:24 2013  Aaron Pfeifer  <aaron.pfeifer@g...>
+
+	* thread.c (terminate_atfork_i): fix locking mutexes not unlocked in
+	  forks when not tracked in thread.  [ruby-core:55102] [Bug #8433]
+
 Fri Oct  4 19:54:09 2013  Zachary Scott  <e@z...>
 
 	* ext/dbm/dbm.c: [DOC] Fix wrong constant name in DBM by @edward
Index: thread.c
===================================================================
--- thread.c	(revision 43147)
+++ thread.c	(revision 43148)
@@ -396,6 +396,8 @@ typedef struct rb_mutex_struct https://github.com/ruby/ruby/blob/trunk/thread.c#L396
 } rb_mutex_t;
 
 static void rb_mutex_abandon_all(rb_mutex_t *mutexes);
+static void rb_mutex_abandon_keeping_mutexes(rb_thread_t *th);
+static void rb_mutex_abandon_locking_mutex(rb_thread_t *th);
 static const char* rb_mutex_unlock_th(rb_mutex_t *mutex, rb_thread_t volatile *th);
 
 void
@@ -3892,10 +3894,8 @@ terminate_atfork_i(st_data_t key, st_dat https://github.com/ruby/ruby/blob/trunk/thread.c#L3894
     GetThreadPtr(thval, th);
 
     if (th != (rb_thread_t *)current_th) {
-	if (th->keeping_mutexes) {
-	    rb_mutex_abandon_all(th->keeping_mutexes);
-	}
-	th->keeping_mutexes = NULL;
+	rb_mutex_abandon_keeping_mutexes(th);
+	rb_mutex_abandon_locking_mutex(th);
 	thread_cleanup_func(th, TRUE);
     }
     return ST_CONTINUE;
@@ -4155,8 +4155,6 @@ thgroup_add(VALUE group, VALUE thread) https://github.com/ruby/ruby/blob/trunk/thread.c#L4155
 #define GetMutexPtr(obj, tobj) \
     TypedData_Get_Struct((obj), rb_mutex_t, &mutex_data_type, (tobj))
 
-static const char *rb_mutex_unlock_th(rb_mutex_t *mutex, rb_thread_t volatile *th);
-
 #define mutex_mark NULL
 
 static void
@@ -4488,6 +4486,28 @@ rb_mutex_unlock(VALUE self) https://github.com/ruby/ruby/blob/trunk/thread.c#L4486
 }
 
 static void
+rb_mutex_abandon_keeping_mutexes(rb_thread_t *th)
+{
+    if (th->keeping_mutexes) {
+	rb_mutex_abandon_all(th->keeping_mutexes);
+    }
+    th->keeping_mutexes = NULL;
+}
+
+static void
+rb_mutex_abandon_locking_mutex(rb_thread_t *th)
+{
+    rb_mutex_t *mutex;
+
+    if (!th->locking_mutex) return;
+
+    GetMutexPtr(th->locking_mutex, mutex);
+    if (mutex->th == th)
+	rb_mutex_abandon_all(mutex);
+    th->locking_mutex = Qfalse;
+}
+
+static void
 rb_mutex_abandon_all(rb_mutex_t *mutexes)
 {
     rb_mutex_t *mutex;
Index: test/ruby/test_thread.rb
===================================================================
--- test/ruby/test_thread.rb	(revision 43147)
+++ test/ruby/test_thread.rb	(revision 43148)
@@ -909,4 +909,31 @@ Thread.new(Thread.current) {|mth| https://github.com/ruby/ruby/blob/trunk/test/ruby/test_thread.rb#L909
     size_large = invoke_rec script, vm_stack_size, 1024 * 1024 * 10
     assert_operator(size_default, :<=, size_large, "large size")
   end
+
+  def test_blocking_mutex_unlocked_on_fork
+    bug8433 = '[ruby-core:55102] [Bug #8433]'
+
+    mutex = Mutex.new
+    flag = false
+    mutex.lock
+
+    th = Thread.new do
+      mutex.synchronize do
+        flag = true
+        sleep
+      end
+    end
+
+    Thread.pass until th.stop?
+    mutex.unlock
+
+    pid = Process.fork do
+      exit(mutex.locked?)
+    end
+
+    th.kill
+
+    pid, status = Process.waitpid2(pid)
+    assert_equal(false, status.success?, bug8433)
+  end
 end

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

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