summaryrefslogtreecommitdiff
path: root/thread_sync.c
diff options
context:
space:
mode:
authornormal <normal@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2018-12-05 18:58:45 +0000
committernormal <normal@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2018-12-05 18:58:45 +0000
commit818f1c65ab6534acdbe539616843cfec3ac794fa (patch)
tree01852c8e2482eb356c6409cb9ec99fbe4e08aed6 /thread_sync.c
parente941daa6dd114b52356a63d3c3db5684e6c66717 (diff)
thread_sync.c (mutex_ptr): handle mutexes held by parent threads in children
Mutexes may be held by threads which only exist in the parent process, so their waitqueues may be populated with references to other dead threads. We must reset them at fork. I am a moron for introducing this bug :< [ruby-core:90312] [Bug #15383] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66230 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'thread_sync.c')
-rw-r--r--thread_sync.c11
1 files changed, 11 insertions, 0 deletions
diff --git a/thread_sync.c b/thread_sync.c
index b79db1fee3..e478a96b88 100644
--- a/thread_sync.c
+++ b/thread_sync.c
@@ -45,6 +45,7 @@ typedef struct rb_mutex_struct {
rb_thread_t *th;
struct rb_mutex_struct *next_mutex;
struct list_head waitq; /* protected by GVL */
+ rb_serial_t fork_gen;
} rb_mutex_t;
#if defined(HAVE_WORKING_FORK)
@@ -121,8 +122,18 @@ static rb_mutex_t *
mutex_ptr(VALUE obj)
{
rb_mutex_t *mutex;
+ rb_serial_t fork_gen = GET_VM()->fork_gen;
TypedData_Get_Struct(obj, rb_mutex_t, &mutex_data_type, mutex);
+
+ if (mutex->fork_gen != fork_gen) {
+ /* forked children can't reach into parent thread stacks */
+ mutex->fork_gen = fork_gen;
+ list_head_init(&mutex->waitq);
+ mutex->next_mutex = 0;
+ mutex->th = 0;
+ }
+
return mutex;
}