From 856bd77aea9450e63a3acdc2deba04613050da43 Mon Sep 17 00:00:00 2001 From: normal Date: Sat, 28 Jul 2018 03:10:10 +0000 Subject: thread.c (blocking_region_end): clear ubf before unregister_ubf_list If we keep ubf set after unregistering, there is a window for other threads (including timer thread) to put this thread back on the ubf_list right away. Entering ubf_list unexpectedly after GVL acquisition may cause spurious wakeup and trigger unexpected behavior. Finally, clear ubf before acquiring GVL, to since ubf is useless during GVL acquisition anyways and we don't want to waste cycles in other threads calling ubf for useless work. [ruby-core:88141] [Bug #14945] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@64083 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- thread.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'thread.c') diff --git a/thread.c b/thread.c index 6181a75ae6..a7d48a464f 100644 --- a/thread.c +++ b/thread.c @@ -1397,12 +1397,15 @@ blocking_region_begin(rb_thread_t *th, struct rb_blocking_region_buffer *region, static inline void blocking_region_end(rb_thread_t *th, struct rb_blocking_region_buffer *region) { + /* entry to ubf_list still permitted at this point, make it impossible: */ + unblock_function_clear(th); + /* entry to ubf_list impossible at this point, so unregister is safe: */ + unregister_ubf_list(th); + gvl_acquire(th->vm, th); rb_thread_set_current(th); thread_debug("leave blocking region (%p)\n", (void *)th); - unregister_ubf_list(th); th->blocking_region_buffer = 0; - unblock_function_clear(th); if (th->status == THREAD_STOPPED) { th->status = region->prev_status; } -- cgit v1.2.3