summaryrefslogtreecommitdiff
path: root/thread.c
diff options
context:
space:
mode:
authorkosaki <kosaki@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2012-11-30 13:52:34 +0000
committerkosaki <kosaki@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2012-11-30 13:52:34 +0000
commit15b25acd2541ae37f4f874b50128d34d8b079457 (patch)
tree81e7d590c4cf77775ce25653b9091b3ece42e587 /thread.c
parent2e72d1c3236c8ec1c0cb8f35c1dd6b64fde02fce (diff)
* vm_core.h (rb_vm_struct): add thread_destruct_lock field.
* thread.c (Init_Thread): ditto. * thread.c (rb_vm_gvl_destroy): ditto. * thread.c (thread_start_func_2): make sure vm->running_thread don't point to dead thread. * thread.c (timer_thread_function): close a race against thead destruction. [Bug #4911][ruby-dev:43859] * vm_core.h (rb_thread_set_current): reset running time of current thread instead of previous thread. We no longer assume previous running thread still live. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@38063 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'thread.c')
-rw-r--r--thread.c16
1 files changed, 15 insertions, 1 deletions
diff --git a/thread.c b/thread.c
index 5a97b5202f..43b1ad19a9 100644
--- a/thread.c
+++ b/thread.c
@@ -238,6 +238,7 @@ rb_vm_gvl_destroy(rb_vm_t *vm)
{
gvl_release(vm);
gvl_destroy(vm);
+ native_mutex_destroy(&vm->thread_destruct_lock);
}
void
@@ -552,6 +553,10 @@ thread_start_func_2(rb_thread_t *th, VALUE *stack_start, VALUE *register_stack_s
th->stack = 0;
}
}
+ native_mutex_lock(&th->vm->thread_destruct_lock);
+ /* make sure vm->running_thread never point me after this point.*/
+ th->vm->running_thread = NULL;
+ native_mutex_unlock(&th->vm->thread_destruct_lock);
thread_cleanup_func(th, FALSE);
gvl_release(th->vm);
@@ -3632,8 +3637,16 @@ timer_thread_function(void *arg)
{
rb_vm_t *vm = GET_VM(); /* TODO: fix me for Multi-VM */
+ /*
+ * Tricky: thread_destruct_lock doesn't close a race against
+ * vm->running_thread switch. however it guarantee th->running_thread
+ * point to valid pointer or NULL.
+ */
+ native_mutex_lock(&vm->thread_destruct_lock);
/* for time slice */
- RUBY_VM_SET_TIMER_INTERRUPT(vm->running_thread);
+ if (vm->running_thread)
+ RUBY_VM_SET_TIMER_INTERRUPT(vm->running_thread);
+ native_mutex_unlock(&vm->thread_destruct_lock);
/* check signal */
rb_threadptr_check_signal(vm->main_thread);
@@ -4870,6 +4883,7 @@ Init_Thread(void)
/* acquire global vm lock */
gvl_init(th->vm);
gvl_acquire(th->vm, th);
+ native_mutex_initialize(&th->vm->thread_destruct_lock);
native_mutex_initialize(&th->interrupt_lock);
th->async_errinfo_queue = rb_ary_tmp_new(0);