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

ruby-changes:54225

From: normal <ko1@a...>
Date: Wed, 19 Dec 2018 03:26:00 +0900 (JST)
Subject: [ruby-changes:54225] normal:r66446 (trunk): thread_pthread.c (ubf_timer_destroy): more careful state transition

normal	2018-12-19 03:25:54 +0900 (Wed, 19 Dec 2018)

  New Revision: 66446

  https://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=revision&revision=66446

  Log:
    thread_pthread.c (ubf_timer_destroy): more careful state transition
    
    We must not call timer_destroy while another thread is
    calling timer_settime to arm the timer.
    
    cf. http://ci.rvm.jp/results/trunk-iseq_binary@silicon-docker/1541578

  Modified files:
    trunk/thread_pthread.c
Index: thread_pthread.c
===================================================================
--- thread_pthread.c	(revision 66445)
+++ thread_pthread.c	(revision 66446)
@@ -1787,11 +1787,34 @@ ubf_timer_destroy(void) https://github.com/ruby/ruby/blob/trunk/thread_pthread.c#L1787
 {
 #if UBF_TIMER == UBF_TIMER_POSIX
     if (timer_posix.owner == getpid()) {
-        /* prevent signal handler from arming: */
-        ATOMIC_SET(timer_posix.state, RTIMER_DEAD);
+        rb_atomic_t expect = RTIMER_DISARM;
+        size_t i, max = 10000000;
 
-        if (timer_settime(timer_posix.timerid, 0, &zero, 0))
-            rb_bug_errno("timer_settime (destroy)", errno);
+        /* prevent signal handler from arming: */
+        for (i = 0; i < max; i++) {
+            switch (ATOMIC_CAS(timer_posix.state, expect, RTIMER_DEAD)) {
+              case RTIMER_DISARM:
+                if (expect == RTIMER_DISARM) goto done;
+                expect = RTIMER_DISARM;
+                break;
+              case RTIMER_ARMING:
+                native_thread_yield(); /* let another thread finish arming */
+                expect = RTIMER_ARMED;
+                break;
+              case RTIMER_ARMED:
+                if (expect == RTIMER_ARMED) {
+                    if (timer_settime(timer_posix.timerid, 0, &zero, 0))
+                        rb_bug_errno("timer_settime (destroy)", errno);
+                    goto done;
+                }
+                expect = RTIMER_ARMED;
+                break;
+              case RTIMER_DEAD:
+                rb_bug("RTIMER_DEAD unexpected");
+            }
+        }
+        rb_bug("timed out waiting for timer to arm");
+done:
         if (timer_delete(timer_posix.timerid) < 0)
             rb_sys_fail("timer_delete");
 

--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

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