thread.c: fix overly long Thread#join w/ timeout
* test/ruby/test_thread.rb (test_signal_at_join): test with timeout * thread.c (sleep_wait_for_interrupt): remove (thread_join_sleep): use native_sleep directly to avoid extra missing thread status change [Bug #14181] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@61302 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
78cc1491d5
commit
db9523ef47
@ -1284,6 +1284,20 @@ q.pop
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
n.times do
|
||||||
|
w = Thread.start { sleep 30 }
|
||||||
|
begin
|
||||||
|
f.puts
|
||||||
|
f.gets
|
||||||
|
ensure
|
||||||
|
w.kill
|
||||||
|
t0 = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
||||||
|
w.join(30)
|
||||||
|
t1 = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
||||||
|
diff = t1 - t0
|
||||||
|
assert_operator diff, :<=, 2
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
};
|
};
|
||||||
end
|
end
|
||||||
|
17
thread.c
17
thread.c
@ -91,7 +91,6 @@ static VALUE sym_never;
|
|||||||
static ID id_locals;
|
static ID id_locals;
|
||||||
|
|
||||||
static void sleep_timeval(rb_thread_t *th, struct timeval time, int spurious_check);
|
static void sleep_timeval(rb_thread_t *th, struct timeval time, int spurious_check);
|
||||||
static void sleep_wait_for_interrupt(rb_thread_t *th, double sleepsec, int spurious_check);
|
|
||||||
static void sleep_forever(rb_thread_t *th, int nodeadlock, int spurious_check);
|
static void sleep_forever(rb_thread_t *th, int nodeadlock, int spurious_check);
|
||||||
static void rb_thread_sleep_deadly_allow_spurious_wakeup(void);
|
static void rb_thread_sleep_deadly_allow_spurious_wakeup(void);
|
||||||
static double timeofday(void);
|
static double timeofday(void);
|
||||||
@ -888,18 +887,22 @@ thread_join_sleep(VALUE arg)
|
|||||||
rb_check_deadlock(th->vm);
|
rb_check_deadlock(th->vm);
|
||||||
native_sleep(th, 0);
|
native_sleep(th, 0);
|
||||||
th->vm->sleeper--;
|
th->vm->sleeper--;
|
||||||
RUBY_VM_CHECK_INTS_BLOCKING(th->ec);
|
|
||||||
th->status = THREAD_RUNNABLE;
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
double now = timeofday();
|
double now = timeofday();
|
||||||
|
struct timeval tv;
|
||||||
|
|
||||||
if (now > limit) {
|
if (now > limit) {
|
||||||
thread_debug("thread_join: timeout (thid: %"PRI_THREAD_ID")\n",
|
thread_debug("thread_join: timeout (thid: %"PRI_THREAD_ID")\n",
|
||||||
thread_id_str(target_th));
|
thread_id_str(target_th));
|
||||||
return Qfalse;
|
return Qfalse;
|
||||||
}
|
}
|
||||||
sleep_wait_for_interrupt(th, limit - now, 0);
|
tv = double2timeval(limit - now);
|
||||||
|
th->status = THREAD_STOPPED;
|
||||||
|
native_sleep(th, &tv);
|
||||||
}
|
}
|
||||||
|
RUBY_VM_CHECK_INTS_BLOCKING(th->ec);
|
||||||
|
th->status = THREAD_RUNNABLE;
|
||||||
thread_debug("thread_join: interrupted (thid: %"PRI_THREAD_ID", status: %s)\n",
|
thread_debug("thread_join: interrupted (thid: %"PRI_THREAD_ID", status: %s)\n",
|
||||||
thread_id_str(target_th), thread_status_name(target_th, TRUE));
|
thread_id_str(target_th), thread_status_name(target_th, TRUE));
|
||||||
}
|
}
|
||||||
@ -1231,12 +1234,6 @@ timeofday(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
sleep_wait_for_interrupt(rb_thread_t *th, double sleepsec, int spurious_check)
|
|
||||||
{
|
|
||||||
sleep_timeval(th, double2timeval(sleepsec), spurious_check);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
rb_thread_wait_for(struct timeval time)
|
rb_thread_wait_for(struct timeval time)
|
||||||
{
|
{
|
||||||
|
Loading…
x
Reference in New Issue
Block a user