[前][次][番号順一覧][スレッド一覧]

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/

[前][次][番号順一覧][スレッド一覧]