ruby-changes:51869
From: normal <ko1@a...>
Date: Sat, 28 Jul 2018 12:10:15 +0900 (JST)
Subject: [ruby-changes:51869] normal:r64083 (trunk): thread.c (blocking_region_end): clear ubf before unregister_ubf_list
normal 2018-07-28 12:10:10 +0900 (Sat, 28 Jul 2018) New Revision: 64083 https://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=revision&revision=64083 Log: 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] Modified files: trunk/thread.c Index: thread.c =================================================================== --- thread.c (revision 64082) +++ thread.c (revision 64083) @@ -1397,12 +1397,15 @@ blocking_region_begin(rb_thread_t *th, s https://github.com/ruby/ruby/blob/trunk/thread.c#L1397 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; } -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/