From 57b8687debea4e532898cdf0380d63bb62749b9a Mon Sep 17 00:00:00 2001 From: nobu Date: Sat, 5 Oct 2013 02:21:12 +0000 Subject: 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] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@43148 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- thread.c | 32 ++++++++++++++++++++++++++------ 1 file changed, 26 insertions(+), 6 deletions(-) (limited to 'thread.c') diff --git a/thread.c b/thread.c index ea11ee064c..463f5d3b0e 100644 --- a/thread.c +++ b/thread.c @@ -396,6 +396,8 @@ typedef struct rb_mutex_struct } 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_data_t val, st_data_t current_th) 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) #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 @@ -4487,6 +4485,28 @@ rb_mutex_unlock(VALUE self) return self; } +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) { -- cgit v1.2.3