зеркало из https://github.com/github/ruby.git
* thread.c (rb_mutex_lock): stop multiple threads use
pthread_cond_timedwait() concurrently. [Bug #6278] [ruby-core:44275] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@36926 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
Родитель
5fbfc21b67
Коммит
10c14095de
|
@ -1,3 +1,8 @@
|
|||
Sun Sep 9 15:21:52 2012 KOSAKI Motohiro <kosaki.motohiro@gmail.com>
|
||||
|
||||
* 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@ruby-lang.org>
|
||||
|
||||
* internal.h (struct rb_classext_struct): move allocator function into
|
||||
|
|
16
thread.c
16
thread.c
|
@ -3910,6 +3910,13 @@ lock_interrupt(void *ptr)
|
|||
native_mutex_unlock(&mutex->lock);
|
||||
}
|
||||
|
||||
/*
|
||||
* 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 @@ rb_mutex_lock(VALUE self)
|
|||
* 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 @@ rb_check_deadlock(rb_vm_t *vm)
|
|||
|
||||
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);
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче