diff options
author | normal <normal@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2018-07-28 03:10:10 +0000 |
---|---|---|
committer | normal <normal@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2018-07-28 03:10:10 +0000 |
commit | 856bd77aea9450e63a3acdc2deba04613050da43 (patch) | |
tree | 58f7db6e7ad9d3f47289dfc39c3e77a59901e16f | |
parent | 297ae3437e168e8cdeae24c44f56fc373a83d098 (diff) | |
download | ruby-856bd77aea9450e63a3acdc2deba04613050da43.tar.gz |
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
-rw-r--r-- | thread.c | 7 |
1 files changed, 5 insertions, 2 deletions
@@ -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; } |