ruby-changes:50347
From: normal <ko1@a...>
Date: Sun, 18 Feb 2018 12:00:37 +0900 (JST)
Subject: [ruby-changes:50347] normal:r62462 (trunk): thread.c (thread_join_m): handle negative timeouts correctly
normal 2018-02-18 12:00:33 +0900 (Sun, 18 Feb 2018) New Revision: 62462 https://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=revision&revision=62462 Log: thread.c (thread_join_m): handle negative timeouts correctly Users may subtract and round into negative values when using Thread#join, so clamp the timeout to zero to avoid infinite/long timeouts. Note: other methods such as Kernel#sleep and IO.select will raise on negative values, but Thread#join is an outlier *shrug* This restores Ruby 2.5 (and earlier) behavior. Fixes: r62182 (commit c915390b9530c31b4665aacf27c1adfc114f768e) ("thread.c: avoid FP for Thread#join") Modified files: trunk/test/ruby/test_thread.rb trunk/thread.c Index: test/ruby/test_thread.rb =================================================================== --- test/ruby/test_thread.rb (revision 62461) +++ test/ruby/test_thread.rb (revision 62462) @@ -234,6 +234,13 @@ class TestThread < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_thread.rb#L234 t = Thread.new {} assert_same t, t.join(limit), "limit=#{limit.inspect}" end + t = Thread.new { sleep } + [ -1, -0.1, RbConfig::LIMITS['FIXNUM_MIN'], RbConfig::LIMITS['INT64_MIN'], + -Float::INFINITY + ].each do |limit| + assert_nil t.join(limit), "limit=#{limit.inspect}" + end + t.kill end def test_kill_main_thread Index: thread.c =================================================================== --- thread.c (revision 62461) +++ thread.c (revision 62462) @@ -1061,6 +1061,8 @@ thread_join_m(int argc, VALUE *argv, VAL https://github.com/ruby/ruby/blob/trunk/thread.c#L1061 case T_NIL: break; case T_FIXNUM: timespec.tv_sec = NUM2TIMET(limit); + if (timespec.tv_sec < 0) + timespec.tv_sec = 0; timespec.tv_nsec = 0; ts = ×pec; break; @@ -1116,8 +1118,8 @@ double2timespec(struct timespec *ts, dou https://github.com/ruby/ruby/blob/trunk/thread.c#L1118 if (TIMESPEC_SEC_MAX_PLUS_ONE <= d) { return NULL; } - else if (d <= TIMESPEC_SEC_MIN) { - ts->tv_sec = TIMESPEC_SEC_MIN; + else if (d <= 0) { + ts->tv_sec = 0; ts->tv_nsec = 0; } else { -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/