thread_sync.c (rb_mutex_t): eliminate fork_gen
The true bug fork_gen was hiding was rb_mutex_abandon_locking_mutex failing to unconditionally clear the waitq of mutexes it was waiting on. So we fix rb_mutex_abandon_locking_mutex, instead, and eliminate rb_mutex_cleanup_keeping_mutexes. This commit was tested heavily on a single-core Pentium-M which was my most reliable reproducer of the "crash.rb" script from [Bug #15383] [Bug #14578] [Bug #15383] Note: [Bug #15430] turned out to be an entirely different problem: RLIMIT_NPROC limit was hit on the CI VMs. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66489 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
5072f03741
commit
0fd53f519f
1
thread.c
1
thread.c
@ -4449,7 +4449,6 @@ rb_thread_atfork(void)
|
|||||||
rb_thread_t *th = GET_THREAD();
|
rb_thread_t *th = GET_THREAD();
|
||||||
rb_thread_atfork_internal(th, terminate_atfork_i);
|
rb_thread_atfork_internal(th, terminate_atfork_i);
|
||||||
th->join_list = NULL;
|
th->join_list = NULL;
|
||||||
rb_mutex_cleanup_keeping_mutexes(th);
|
|
||||||
rb_fiber_atfork(th);
|
rb_fiber_atfork(th);
|
||||||
|
|
||||||
/* We don't want reproduce CVE-2003-0900. */
|
/* We don't want reproduce CVE-2003-0900. */
|
||||||
|
@ -45,17 +45,6 @@ typedef struct rb_mutex_struct {
|
|||||||
rb_thread_t *th;
|
rb_thread_t *th;
|
||||||
struct rb_mutex_struct *next_mutex;
|
struct rb_mutex_struct *next_mutex;
|
||||||
struct list_head waitq; /* protected by GVL */
|
struct list_head waitq; /* protected by GVL */
|
||||||
|
|
||||||
/*
|
|
||||||
* FIXME: belt-and-suspenders redundancy. This field should NOT
|
|
||||||
* be necessary at all if:
|
|
||||||
* - rb_mutex_cleanup_keeping_mutexes
|
|
||||||
* - rb_mutex_abandon_keeping_mutexes
|
|
||||||
* - rb_mutex_abandon_locking_mutex
|
|
||||||
* are all correct, but I suspect one of them is buggy.
|
|
||||||
* [Bug #15383] [Bug #15430]
|
|
||||||
*/
|
|
||||||
rb_serial_t fork_gen;
|
|
||||||
} rb_mutex_t;
|
} rb_mutex_t;
|
||||||
|
|
||||||
#if defined(HAVE_WORKING_FORK)
|
#if defined(HAVE_WORKING_FORK)
|
||||||
@ -132,17 +121,9 @@ static rb_mutex_t *
|
|||||||
mutex_ptr(VALUE obj)
|
mutex_ptr(VALUE obj)
|
||||||
{
|
{
|
||||||
rb_mutex_t *mutex;
|
rb_mutex_t *mutex;
|
||||||
rb_serial_t fork_gen = GET_VM()->fork_gen;
|
|
||||||
|
|
||||||
TypedData_Get_Struct(obj, rb_mutex_t, &mutex_data_type, mutex);
|
TypedData_Get_Struct(obj, rb_mutex_t, &mutex_data_type, mutex);
|
||||||
|
|
||||||
/* FIXME: remove (see comment at rb_mutex_t definition) */
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
return mutex;
|
return mutex;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -428,8 +409,7 @@ rb_mutex_abandon_locking_mutex(rb_thread_t *th)
|
|||||||
if (th->locking_mutex) {
|
if (th->locking_mutex) {
|
||||||
rb_mutex_t *mutex = mutex_ptr(th->locking_mutex);
|
rb_mutex_t *mutex = mutex_ptr(th->locking_mutex);
|
||||||
|
|
||||||
if (mutex->th == th)
|
list_head_init(&mutex->waitq);
|
||||||
rb_mutex_abandon_all(mutex);
|
|
||||||
th->locking_mutex = Qfalse;
|
th->locking_mutex = Qfalse;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -447,25 +427,6 @@ rb_mutex_abandon_all(rb_mutex_t *mutexes)
|
|||||||
list_head_init(&mutex->waitq);
|
list_head_init(&mutex->waitq);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* All other threads are dead in the a new child process, so waitqs
|
|
||||||
* contain references to dead threads which we need to clean up
|
|
||||||
*/
|
|
||||||
static void
|
|
||||||
rb_mutex_cleanup_keeping_mutexes(const rb_thread_t *current_thread)
|
|
||||||
{
|
|
||||||
rb_mutex_t *mutex = current_thread->keeping_mutexes;
|
|
||||||
rb_serial_t fork_gen = current_thread->vm->fork_gen;
|
|
||||||
|
|
||||||
while (mutex) {
|
|
||||||
/* FIXME: remove (see comment at rb_mutex_t definition) */
|
|
||||||
mutex->fork_gen = fork_gen;
|
|
||||||
|
|
||||||
list_head_init(&mutex->waitq);
|
|
||||||
mutex = mutex->next_mutex;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static VALUE
|
static VALUE
|
||||||
|
Loading…
x
Reference in New Issue
Block a user