Bug #15385
Ruby process hang in ensure
Description
While playing with mutation testing of my code I've found a weird mutation that hangs Ruby process. The isolated code which triggers this freeze is:
require 'timeout'
puts Process.pid
def raise_before_returning
raise
[]
end
def doh
value = raise_before_returning
ensure
# p value # <-- that unblocks it
value if nil
end
Timeout.timeout(3) do
doh
end
Timeout
is unnecessary and was added to illustrate that it has no effect to interrupt hanged process.Process.pid
is printed for convenience to kill hanged process.- Printing
value
in ensure changes behavior, there is no hang when encounteringvalue if nil
below.
I've also checked ruby 2.6.0preview3 (2018-11-06 trunk 65578) [x86_64-darwin18]
and the problem persists.
Files
Related issues
Associated revisions
Fix infinite loop by ensure
- compile.c (iseq_insert_nop_between_end_and_cont): insert nop so that the end of rescue and continuing points are not same, to get rid of infinite loop. [Bug #15385]
Fix infinite loop by ensure
- compile.c (iseq_insert_nop_between_end_and_cont): insert nop so that the end of rescue and continuing points are not same, to get rid of infinite loop. [Bug #15385]
test_optimization.rb: increase timeout for RubyCI
History
Updated by ujihisa (Tatsuhiro Ujihisa) 3 months ago
This reproduces even without timeout library.
def doh
raise
ensure
123 if false
end
doh
looks like this is because the optimizer removed if false
or if nil
without adding nop
iseq.
Updated by pawelpacana (Paweł Pacana) 3 months ago
ujihisa (Tatsuhiro Ujihisa) wrote:
looks like this is because the optimizer removedif false
orif nil
without addingnop
iseq.
Could it be related then to https://bugs.ruby-lang.org/issues/14959#note-7 and https://bugs.ruby-lang.org/issues/15392 then?
Updated by shyouhei (Shyouhei Urabe) 2 months ago
- Related to Bug #14897: Unexpected behavior of `if` in specific code added
Updated by nobu (Nobuyoshi Nakada) 2 months ago
- Status changed from Open to Closed
Applied in changeset trunk|r66326.
Fix infinite loop by ensure
- compile.c (iseq_insert_nop_between_end_and_cont): insert nop so that the end of rescue and continuing points are not same, to get rid of infinite loop. [Bug #15385]
Updated by nagachika (Tomoyuki Chikanaga) 2 months ago
- Backport changed from 2.4: UNKNOWN, 2.5: UNKNOWN to 2.4: REQUIRED, 2.5: REQUIRED
I didn't confirm this can be reproduced on ruby_2_4 too.
After a quick code reading, I think it might be.
Fix infinite loop by ensure
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66326 b2dd03c8-39d4-4d8f-98ff-823fe69b080e