ruby-changes:49184
From: normal <ko1@a...>
Date: Sun, 17 Dec 2017 17:26:22 +0900 (JST)
Subject: [ruby-changes:49184] normal:r61302 (trunk): thread.c: fix overly long Thread#join w/ timeout
normal 2017-12-17 17:26:17 +0900 (Sun, 17 Dec 2017) New Revision: 61302 https://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=revision&revision=61302 Log: 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] Modified files: trunk/test/ruby/test_thread.rb trunk/thread.c Index: test/ruby/test_thread.rb =================================================================== --- test/ruby/test_thread.rb (revision 61301) +++ test/ruby/test_thread.rb (revision 61302) @@ -1284,6 +1284,20 @@ q.pop https://github.com/ruby/ruby/blob/trunk/test/ruby/test_thread.rb#L1284 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 Index: thread.c =================================================================== --- thread.c (revision 61301) +++ thread.c (revision 61302) @@ -91,7 +91,6 @@ static VALUE sym_never; https://github.com/ruby/ruby/blob/trunk/thread.c#L91 static ID id_locals; 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 rb_thread_sleep_deadly_allow_spurious_wakeup(void); static double timeofday(void); @@ -888,18 +887,22 @@ thread_join_sleep(VALUE arg) https://github.com/ruby/ruby/blob/trunk/thread.c#L887 rb_check_deadlock(th->vm); native_sleep(th, 0); th->vm->sleeper--; - RUBY_VM_CHECK_INTS_BLOCKING(th->ec); - th->status = THREAD_RUNNABLE; } else { double now = timeofday(); + struct timeval tv; + if (now > limit) { thread_debug("thread_join: timeout (thid: %"PRI_THREAD_ID")\n", thread_id_str(target_th)); 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_id_str(target_th), thread_status_name(target_th, TRUE)); } @@ -1231,12 +1234,6 @@ timeofday(void) https://github.com/ruby/ruby/blob/trunk/thread.c#L1234 } } -static void -sleep_wait_for_interrupt(rb_thread_t *th, double sleepsec, int spurious_check) -{ - sleep_timeval(th, double2timeval(sleepsec), spurious_check); -} - void rb_thread_wait_for(struct timeval time) { -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/