diff options
author | Koichi Sasada <[email protected]> | 2023-10-14 08:32:22 +0900 |
---|---|---|
committer | Koichi Sasada <[email protected]> | 2023-10-14 13:26:02 +0900 |
commit | eb79b0319bc9b04067bd9c795f9447dd03615df2 (patch) | |
tree | 8edd4d2394cdc4341f0fe3b1394c4dff0fd4c10c /thread_pthread.c | |
parent | 16d14f425f1452e9117b5a23af24bc93f570541a (diff) |
release sched_lock before VM lock
to avoid deadlock
```ruby
r = Ractor.new do
obj = Thread.new{}
Ractor.yield obj
rescue => e
e.message
end
p r.take
```
```
(lldb) bt
* thread #1, name = 'miniruby', stop reason = signal SIGSTOP
* frame #0: 0x0000ffff44881410 libpthread.so.0`__lll_lock_wait + 88
frame #1: 0x0000ffff4487a078 libpthread.so.0`__pthread_mutex_lock + 232
frame #2: 0x0000aaab617c0980 miniruby`rb_native_mutex_lock(lock=<unavailable>) at thread_pthread.c:109:14
frame #3: 0x0000aaab617c1d58 miniruby`ubf_event_waiting [inlined] thread_sched_lock_(th=0x0000aaab9df82980, file=<unavailable>, line=46, sched=0x0000aaab9dec79b8) at thread_pthread.c:351:5
frame #4: 0x0000aaab617c1d50 miniruby`ubf_event_waiting(ptr=0x0000aaab9df82980) at thread_pthread_mn.c:46:5
frame #5: 0x0000aaab617c6020 miniruby`rb_threadptr_interrupt [inlined] rb_threadptr_interrupt_common(trap=0, th=0x0000aaab9df82980) at thread.c:352:25
frame #6: 0x0000aaab617c5fec miniruby`rb_threadptr_interrupt(th=0x0000aaab9df82980) at thread.c:365:5
frame #7: 0x0000aaab617379b0 miniruby`rb_ractor_terminate_all at ractor.c:2364:13
frame #8: 0x0000aaab6173797c miniruby`rb_ractor_terminate_all at ractor.c:2383:17
frame #9: 0x0000aaab61737958 miniruby`rb_ractor_terminate_all [inlined] ractor_terminal_interrupt_all(vm=0x0000aaab9dea3320) at ractor.c:2375:1
frame #10: 0x0000aaab61737950 miniruby`rb_ractor_terminate_all at ractor.c:2424:13
frame #11: 0x0000aaab6164f108 miniruby`rb_ec_cleanup(ec=0x0000aaab9dea5900, ex=RUBY_TAG_NONE) at eval.c:239:9
frame #12: 0x0000aaab6164fa3c miniruby`ruby_run_node(n=0x0000ffff417ed178) at eval.c:328:12
frame #13: 0x0000aaab615a5ab0 miniruby`main at main.c:39:12
frame #14: 0x0000aaab615a5a98 miniruby`main(argc=<unavailable>, argv=<unavailable>) at main.c:58:12
frame #15: 0x0000ffff44714b2c libc.so.6`__libc_start_main + 228
frame #16: 0x0000aaab615a5b0c miniruby`_start + 52
(lldb) thread select 3
* thread #3, name = 'bootstraptest.*', stop reason = signal SIGSTOP
frame #0: 0x0000ffff448813ec libpthread.so.0`__lll_lock_wait + 52
libpthread.so.0`__lll_lock_wait:
-> 0xffff448813ec <+52>: svc #0
0xffff448813f0 <+56>: eor w20, w20, #0x80
0xffff448813f4 <+60>: sxtw x20, w20
0xffff448813f8 <+64>: b 0xffff44881414 ; <+92>
(lldb) bt
* thread #3, name = 'bootstraptest.*', stop reason = signal SIGSTOP
* frame #0: 0x0000ffff448813ec libpthread.so.0`__lll_lock_wait + 52
frame #1: 0x0000ffff4487a078 libpthread.so.0`__pthread_mutex_lock + 232
frame #2: 0x0000aaab617c0980 miniruby`rb_native_mutex_lock(lock=<unavailable>) at thread_pthread.c:109:14
frame #3: 0x0000aaab61823d68 miniruby`rb_vm_lock_enter_body [inlined] vm_lock_enter(no_barrier=false, lev=0x0000ffff215bfbe4, locked=false, vm=0x0000aaab9dea3320, cr=0x0000aaab9dec7890) at vm_sync.c:57:9
frame #4: 0x0000aaab61823d60 miniruby`rb_vm_lock_enter_body(lev=0x0000ffff215bfbe4) at vm_sync.c:119:9
frame #5: 0x0000aaab617c1b30 miniruby`thread_sched_setup_running_threads [inlined] rb_vm_lock_enter(file=<unavailable>, line=597, lev=0x0000ffff215bfbe4) at vm_sync.h:75:9
frame #6: 0x0000aaab617c1b14 miniruby`thread_sched_setup_running_threads(vm=0x0000aaab9dea3320, add_th=0x0000aaab9df82980, del_th=<unavailable>, add_timeslice_th=0x0000000000000000, cr=<unavailable>, sched=<unavailable>, sched=<unavailable>) at thread_pthread.c:597:9
frame #7: 0x0000aaab617c29b4 miniruby`thread_sched_wait_running_turn at thread_pthread.c:614:5
frame #8: 0x0000aaab617c298c miniruby`thread_sched_wait_running_turn(sched=0x0000aaab9dec79b8, th=0x0000aaab9df82980, can_direct_transfer=true) at thread_pthread.c:868:9
frame #9: 0x0000aaab617c6f0c miniruby`thread_sched_wait_events(sched=0x0000aaab9dec79b8, th=0x0000aaab9df82980, fd=<unavailable>, events=<unavailable>, rel=<unavailable>) at thread_pthread_mn.c:90:17
frame #10: 0x0000aaab617c7354 miniruby`rb_thread_terminate_all at thread_pthread.c:3248:13
frame #11: 0x0000aaab617c733c miniruby`rb_thread_terminate_all(th=0x0000aaab9df82980) at thread.c:466:13
frame #12: 0x0000aaab617c7a64 miniruby`thread_start_func_2(th=0x0000aaab9df82980, stack_start=<unavailable>) at thread.c:713:9
frame #13: 0x0000aaab617c7d1c miniruby`co_start [inlined] call_thread_start_func_2(th=0x0000aaab9df82980) at thread_pthread.c:2165:5
frame #14: 0x0000aaab617c7cd0 miniruby`co_start(from=<unavailable>, self=0x0000aaab9df0f760) at thread_pthread_mn.c:421:9
```
Diffstat (limited to 'thread_pthread.c')
-rw-r--r-- | thread_pthread.c | 12 |
1 files changed, 10 insertions, 2 deletions
diff --git a/thread_pthread.c b/thread_pthread.c index 4a240f4fbe..cae4a8e1bd 100644 --- a/thread_pthread.c +++ b/thread_pthread.c @@ -593,8 +593,16 @@ thread_sched_setup_running_threads(struct rb_thread_sched *sched, rb_ractor_t *c if (add_th && !del_th && UNLIKELY(vm->ractor.sync.lock_owner != NULL)) { // it can be after barrier synchronization by another ractor - RB_VM_LOCK_ENTER(); - RB_VM_LOCK_LEAVE(); + rb_thread_t *lock_owner = NULL; +#if VM_CHECK_MODE + lock_owner = sched->lock_owner; +#endif + thread_sched_unlock(sched, lock_owner); + { + RB_VM_LOCK_ENTER(); + RB_VM_LOCK_LEAVE(); + } + thread_sched_lock(sched, lock_owner); } //RUBY_DEBUG_LOG("+:%u -:%u +ts:%u -ts:%u run:%u->%u", |