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 git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66446 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
75f36bdc1e
commit
a57acb731a
@ -1787,11 +1787,34 @@ ubf_timer_destroy(void)
|
||||
{
|
||||
#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");
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user