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 UBF_TIMER == UBF_TIMER_POSIX
|
||||||
if (timer_posix.owner == getpid()) {
|
if (timer_posix.owner == getpid()) {
|
||||||
/* prevent signal handler from arming: */
|
rb_atomic_t expect = RTIMER_DISARM;
|
||||||
ATOMIC_SET(timer_posix.state, RTIMER_DEAD);
|
size_t i, max = 10000000;
|
||||||
|
|
||||||
if (timer_settime(timer_posix.timerid, 0, &zero, 0))
|
/* prevent signal handler from arming: */
|
||||||
rb_bug_errno("timer_settime (destroy)", errno);
|
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)
|
if (timer_delete(timer_posix.timerid) < 0)
|
||||||
rb_sys_fail("timer_delete");
|
rb_sys_fail("timer_delete");
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user