Project

General

Profile

Bug #15385

Ruby process hang in ensure

Added by pawelpacana (Paweł Pacana) 7 days ago. Updated 2 days ago.

Status:
Closed
Priority:
Normal
Assignee:
-
Target version:
-
ruby -v:
ruby 2.5.3p105 (2018-10-18 revision 65156) [x86_64-darwin18]
[ruby-core:90332]

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
  1. Timeout is unnecessary and was added to illustrate that it has no effect to interrupt hanged process.
  2. Process.pid is printed for convenience to kill hanged process.
  3. Printing value in ensure changes behavior, there is no hang when encountering value if nil below.

I've also checked ruby 2.6.0preview3 (2018-11-06 trunk 65578) [x86_64-darwin18] and the problem persists.

reproduce.rb (216 Bytes) reproduce.rb reproduction script pawelpacana (Paweł Pacana), 12/06/2018 01:42 AM

Related issues

Related to Ruby trunk - Bug #14897: Unexpected behavior of `if` in specific codeClosed

Associated revisions

Revision b91599c4
Added by nobu (Nobuyoshi Nakada) 2 days ago

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]

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66326 b2dd03c8-39d4-4d8f-98ff-823fe69b080e

Revision 66326
Added by nobu (Nobuyoshi Nakada) 2 days ago

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]

History

#2 [ruby-core:90333] Updated by ujihisa (Tatsuhiro Ujihisa) 7 days 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.

#3 [ruby-core:90373] Updated by pawelpacana (Paweł Pacana) 5 days ago

ujihisa (Tatsuhiro Ujihisa) wrote:
looks like this is because the optimizer removed if false or if nil without adding nop 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?

#4 Updated by shyouhei (Shyouhei Urabe) 3 days ago

  • Related to Bug #14897: Unexpected behavior of `if` in specific code added

#5 Updated by nobu (Nobuyoshi Nakada) 2 days 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]

#6 [ruby-core:90419] Updated by nagachika (Tomoyuki Chikanaga) 2 days 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.

Also available in: Atom PDF