Issue #7624 has been reported by ko1 (Koichi Sasada). ---------------------------------------- Bug #7624: How to handle exceptions raised in event hook? https://bugs.ruby-lang.org/issues/7624 Author: ko1 (Koichi Sasada) Status: Open Priority: Normal Assignee: ko1 (Koichi Sasada) Category: core Target version: 2.0.0 ruby -v: ruby 2.0.0dev (2012-12-21 trunk 38515) [i386-mswin32_100] The following program raises an exception in `return' event hook. ### class FOO < RuntimeError; end class BAR < RuntimeError; end def m1; m2; end def m2; m3; end def m3; raise FOO; end set_trace_func(lambda{|*args| if args[0] == 'return' p args raise BAR # raise in trace_func end}) begin m1 rescue => e p e ensure p :ensure end ### And this program cause strange behavior in each versions. --- # 2.0 trunk ruby 2.0.0dev (2012-12-21 trunk 38515) [i386-mswin32_100] ["return", "test.rb", 5, :m3, #<Binding:0x9781c8>, Object] test.rb:9:in `block in <main>': BAR (BAR) from test.rb:5:in `m3' from test.rb:4:in `m2' from test.rb:3:in `m1' from test.rb:12:in `<main>' # 1.9.3p332 (2012-11-15 revision 37660) ruby 1.9.3p332 (2012-11-15 revision 37660) [i386-mswin32_100] ["return", "test.rb", 5, :m3, #<Binding:0x2682980>, Object] ["return", "test.rb", 5, :m3, #<Binding:0x268278c>, Object] ... # infinite loop # 1.8.7 ruby 1.8.7 (2012-06-29 patchlevel 370) [i386-cygwin] ["return", "test.rb", 5, :m3, #<Binding:0x80057adc>, Object] ["return", "test.rb", 5, :m2, #<Binding:0x80057a64>, Object] ["return", "test.rb", 5, :m1, #<Binding:0x80057884>, Object] test.rb:13: [BUG] unexpected local variable assignment ruby 1.8.7 (2012-06-29 patchlevel 370) [i386-cygwin] 1 [sig] ruby 7388 open_stackdumpfile: Dumping stack trace to ruby.exe.stackdump # [BUG] !! and line number is not correct. --- # JRuby $ bin/jruby --debug -v test.rb jruby 1.7.2.dev (1.9.3p327) 2012-12-25 dc3af39 on OpenJDK Client VM 1.6.0_18-b18 [linux-i386] ["return", "test.rb", 5, :m3, #<Binding:0x1f7896f>, Object] ["return", "test.rb", 4, :m2, #<Binding:0x1abbec4>, Object] ["return", "test.rb", 3, :m1, #<Binding:0x2c03ff>, Object] #<BAR: BAR> :ensure --- # Ancient Ruby # 1.6.5 $ versions/install-tags_v1_6_5_/bin/ruby 'test.rb' 2>&1 ["return", "test.rb", 3, :m3, #<Binding:0xf755c7d0>, Object] ["return", "test.rb", 12, :m2, #<Binding:0xf755c5c8>, Object] ["return", "test.rb", 5, :m1, #<Binding:0xf755c424>, Object] #<BAR: BAR> :ensure # 1.8.6 $ versions/install-tags_v1_8_6_420_/bin/ruby 'test.rb' 2>&1 ["return", "test.rb", 5, :m3, #<Binding:0x7f9bc3032530>, Object] ["return", "test.rb", 4, :m2, #<Binding:0x7f9bc3032440>, Object] ["return", "test.rb", 3, :m1, #<Binding:0x7f9bc3032080>, Object] test.rb:13: [BUG] unexpected local variable assignment ruby 1.8.6 (2010-09-02) [x86_64-linux] --- 1.8 and before, exceptions from trace_fook are raised as normal exceptions. JRuby (with --debug) emulates this behavior correctly. Also CRuby 1.9 tried to handle exceptions as normal exceptions. However, it becomes infinite loop. ### (1) exception are occurred at m3 m1 m2 m3 raise ### (2) pop stack frames m1 m2 m3 ### (3) try m3 return hook m1 m2 m3 m3_return_hook ### (4) exception at m3_return_hook m1 m2 m3 m3_return_hook raise ### (5) pop stack frames and go to (3) m1 m2 m3 MRI 1.8 invokes hooks *after* pop m3. However, MRI 1.9 invoke hooks *before* pop m3. This is why infinite loop was made. ---- To solve this issue, current 2.0 pop all stack frames before return hook (when handling exception). Hoever, `ensure' etc was skipped. This is also issues. [Bug 7622], [Bug 7592] This corner case is confusing. ---- There are several solution about it. (1) Emulate 1.8's behavior. Which JRuby does :) No compatibility issue. (2) Do not propagate any errors from trace block Like thread, prohibit all of errors and escape (such as throw). (2') Output errors if any errors are occurred (3) Exit thread or program which current trunk done. ---- I think only few people use set_trace_func() because send bug report on it. (3) seems bad because ensure clause is ignored. This means current trunk is buggy. (1) is best way because no incompatibility and no discussion is needed. (2) (and (2')) has incompatible behavior from 1.9 and 1.8. But this approach seems good because trace hooks should not affect main program. I think (1) and (2) is valuable to discuss. ---- I'm sorry to propose such issue includes *compatibility*. I want to make it clear current status and choose correct way.
on 2012-12-25 13:31
on 2012-12-26 09:18
Issue #7624 has been updated by ko1 (Koichi Sasada). I fixed this issue as 1.8 (1.6, JRuby) compatible. 1.9 also needs backport. ---------------------------------------- Bug #7624: How to handle exceptions raised in event hook? https://bugs.ruby-lang.org/issues/7624#change-35086 Author: ko1 (Koichi Sasada) Status: Closed Priority: Normal Assignee: ko1 (Koichi Sasada) Category: core Target version: 2.0.0 ruby -v: ruby 2.0.0dev (2012-12-21 trunk 38515) [i386-mswin32_100] The following program raises an exception in `return' event hook. ### class FOO < RuntimeError; end class BAR < RuntimeError; end def m1; m2; end def m2; m3; end def m3; raise FOO; end set_trace_func(lambda{|*args| if args[0] == 'return' p args raise BAR # raise in trace_func end}) begin m1 rescue => e p e ensure p :ensure end ### And this program cause strange behavior in each versions. --- # 2.0 trunk ruby 2.0.0dev (2012-12-21 trunk 38515) [i386-mswin32_100] ["return", "test.rb", 5, :m3, #<Binding:0x9781c8>, Object] test.rb:9:in `block in <main>': BAR (BAR) from test.rb:5:in `m3' from test.rb:4:in `m2' from test.rb:3:in `m1' from test.rb:12:in `<main>' # 1.9.3p332 (2012-11-15 revision 37660) ruby 1.9.3p332 (2012-11-15 revision 37660) [i386-mswin32_100] ["return", "test.rb", 5, :m3, #<Binding:0x2682980>, Object] ["return", "test.rb", 5, :m3, #<Binding:0x268278c>, Object] ... # infinite loop # 1.8.7 ruby 1.8.7 (2012-06-29 patchlevel 370) [i386-cygwin] ["return", "test.rb", 5, :m3, #<Binding:0x80057adc>, Object] ["return", "test.rb", 5, :m2, #<Binding:0x80057a64>, Object] ["return", "test.rb", 5, :m1, #<Binding:0x80057884>, Object] test.rb:13: [BUG] unexpected local variable assignment ruby 1.8.7 (2012-06-29 patchlevel 370) [i386-cygwin] 1 [sig] ruby 7388 open_stackdumpfile: Dumping stack trace to ruby.exe.stackdump # [BUG] !! and line number is not correct. --- # JRuby $ bin/jruby --debug -v test.rb jruby 1.7.2.dev (1.9.3p327) 2012-12-25 dc3af39 on OpenJDK Client VM 1.6.0_18-b18 [linux-i386] ["return", "test.rb", 5, :m3, #<Binding:0x1f7896f>, Object] ["return", "test.rb", 4, :m2, #<Binding:0x1abbec4>, Object] ["return", "test.rb", 3, :m1, #<Binding:0x2c03ff>, Object] #<BAR: BAR> :ensure --- # Ancient Ruby # 1.6.5 $ versions/install-tags_v1_6_5_/bin/ruby 'test.rb' 2>&1 ["return", "test.rb", 3, :m3, #<Binding:0xf755c7d0>, Object] ["return", "test.rb", 12, :m2, #<Binding:0xf755c5c8>, Object] ["return", "test.rb", 5, :m1, #<Binding:0xf755c424>, Object] #<BAR: BAR> :ensure # 1.8.6 $ versions/install-tags_v1_8_6_420_/bin/ruby 'test.rb' 2>&1 ["return", "test.rb", 5, :m3, #<Binding:0x7f9bc3032530>, Object] ["return", "test.rb", 4, :m2, #<Binding:0x7f9bc3032440>, Object] ["return", "test.rb", 3, :m1, #<Binding:0x7f9bc3032080>, Object] test.rb:13: [BUG] unexpected local variable assignment ruby 1.8.6 (2010-09-02) [x86_64-linux] --- 1.8 and before, exceptions from trace_fook are raised as normal exceptions. JRuby (with --debug) emulates this behavior correctly. Also CRuby 1.9 tried to handle exceptions as normal exceptions. However, it becomes infinite loop. ### (1) exception are occurred at m3 m1 m2 m3 raise ### (2) pop stack frames m1 m2 m3 ### (3) try m3 return hook m1 m2 m3 m3_return_hook ### (4) exception at m3_return_hook m1 m2 m3 m3_return_hook raise ### (5) pop stack frames and go to (3) m1 m2 m3 MRI 1.8 invokes hooks *after* pop m3. However, MRI 1.9 invoke hooks *before* pop m3. This is why infinite loop was made. ---- To solve this issue, current 2.0 pop all stack frames before return hook (when handling exception). Hoever, `ensure' etc was skipped. This is also issues. [Bug 7622], [Bug 7592] This corner case is confusing. ---- There are several solution about it. (1) Emulate 1.8's behavior. Which JRuby does :) No compatibility issue. (2) Do not propagate any errors from trace block Like thread, prohibit all of errors and escape (such as throw). (2') Output errors if any errors are occurred (3) Exit thread or program which current trunk done. ---- I think only few people use set_trace_func() because send bug report on it. (3) seems bad because ensure clause is ignored. This means current trunk is buggy. (1) is best way because no incompatibility and no discussion is needed. (2) (and (2')) has incompatible behavior from 1.9 and 1.8. But this approach seems good because trace hooks should not affect main program. I think (1) and (2) is valuable to discuss. ---- I'm sorry to propose such issue includes *compatibility*. I want to make it clear current status and choose correct way.
on 2012-12-26 09:23
Issue #7624 has been updated by ko1 (Koichi Sasada). File 193backport_exception_in_settracefunc.patch added I tried to move this ticket to backport193, but I can't move it (system error?). I attached a patch for 1.9.3. Please try it. ---------------------------------------- Bug #7624: How to handle exceptions raised in event hook? https://bugs.ruby-lang.org/issues/7624#change-35087 Author: ko1 (Koichi Sasada) Status: Closed Priority: Normal Assignee: ko1 (Koichi Sasada) Category: core Target version: 2.0.0 ruby -v: ruby 2.0.0dev (2012-12-21 trunk 38515) [i386-mswin32_100] The following program raises an exception in `return' event hook. ### class FOO < RuntimeError; end class BAR < RuntimeError; end def m1; m2; end def m2; m3; end def m3; raise FOO; end set_trace_func(lambda{|*args| if args[0] == 'return' p args raise BAR # raise in trace_func end}) begin m1 rescue => e p e ensure p :ensure end ### And this program cause strange behavior in each versions. --- # 2.0 trunk ruby 2.0.0dev (2012-12-21 trunk 38515) [i386-mswin32_100] ["return", "test.rb", 5, :m3, #<Binding:0x9781c8>, Object] test.rb:9:in `block in <main>': BAR (BAR) from test.rb:5:in `m3' from test.rb:4:in `m2' from test.rb:3:in `m1' from test.rb:12:in `<main>' # 1.9.3p332 (2012-11-15 revision 37660) ruby 1.9.3p332 (2012-11-15 revision 37660) [i386-mswin32_100] ["return", "test.rb", 5, :m3, #<Binding:0x2682980>, Object] ["return", "test.rb", 5, :m3, #<Binding:0x268278c>, Object] ... # infinite loop # 1.8.7 ruby 1.8.7 (2012-06-29 patchlevel 370) [i386-cygwin] ["return", "test.rb", 5, :m3, #<Binding:0x80057adc>, Object] ["return", "test.rb", 5, :m2, #<Binding:0x80057a64>, Object] ["return", "test.rb", 5, :m1, #<Binding:0x80057884>, Object] test.rb:13: [BUG] unexpected local variable assignment ruby 1.8.7 (2012-06-29 patchlevel 370) [i386-cygwin] 1 [sig] ruby 7388 open_stackdumpfile: Dumping stack trace to ruby.exe.stackdump # [BUG] !! and line number is not correct. --- # JRuby $ bin/jruby --debug -v test.rb jruby 1.7.2.dev (1.9.3p327) 2012-12-25 dc3af39 on OpenJDK Client VM 1.6.0_18-b18 [linux-i386] ["return", "test.rb", 5, :m3, #<Binding:0x1f7896f>, Object] ["return", "test.rb", 4, :m2, #<Binding:0x1abbec4>, Object] ["return", "test.rb", 3, :m1, #<Binding:0x2c03ff>, Object] #<BAR: BAR> :ensure --- # Ancient Ruby # 1.6.5 $ versions/install-tags_v1_6_5_/bin/ruby 'test.rb' 2>&1 ["return", "test.rb", 3, :m3, #<Binding:0xf755c7d0>, Object] ["return", "test.rb", 12, :m2, #<Binding:0xf755c5c8>, Object] ["return", "test.rb", 5, :m1, #<Binding:0xf755c424>, Object] #<BAR: BAR> :ensure # 1.8.6 $ versions/install-tags_v1_8_6_420_/bin/ruby 'test.rb' 2>&1 ["return", "test.rb", 5, :m3, #<Binding:0x7f9bc3032530>, Object] ["return", "test.rb", 4, :m2, #<Binding:0x7f9bc3032440>, Object] ["return", "test.rb", 3, :m1, #<Binding:0x7f9bc3032080>, Object] test.rb:13: [BUG] unexpected local variable assignment ruby 1.8.6 (2010-09-02) [x86_64-linux] --- 1.8 and before, exceptions from trace_fook are raised as normal exceptions. JRuby (with --debug) emulates this behavior correctly. Also CRuby 1.9 tried to handle exceptions as normal exceptions. However, it becomes infinite loop. ### (1) exception are occurred at m3 m1 m2 m3 raise ### (2) pop stack frames m1 m2 m3 ### (3) try m3 return hook m1 m2 m3 m3_return_hook ### (4) exception at m3_return_hook m1 m2 m3 m3_return_hook raise ### (5) pop stack frames and go to (3) m1 m2 m3 MRI 1.8 invokes hooks *after* pop m3. However, MRI 1.9 invoke hooks *before* pop m3. This is why infinite loop was made. ---- To solve this issue, current 2.0 pop all stack frames before return hook (when handling exception). Hoever, `ensure' etc was skipped. This is also issues. [Bug 7622], [Bug 7592] This corner case is confusing. ---- There are several solution about it. (1) Emulate 1.8's behavior. Which JRuby does :) No compatibility issue. (2) Do not propagate any errors from trace block Like thread, prohibit all of errors and escape (such as throw). (2') Output errors if any errors are occurred (3) Exit thread or program which current trunk done. ---- I think only few people use set_trace_func() because send bug report on it. (3) seems bad because ensure clause is ignored. This means current trunk is buggy. (1) is best way because no incompatibility and no discussion is needed. (2) (and (2')) has incompatible behavior from 1.9 and 1.8. But this approach seems good because trace hooks should not affect main program. I think (1) and (2) is valuable to discuss. ---- I'm sorry to propose such issue includes *compatibility*. I want to make it clear current status and choose correct way.
on 2012-12-26 09:28
Issue #7624 has been updated by usa (Usaku NAKAMURA). Status changed from Closed to Assigned Assignee changed from ko1 (Koichi Sasada) to usa (Usaku NAKAMURA) ---------------------------------------- Backport #7624: How to handle exceptions raised in event hook? https://bugs.ruby-lang.org/issues/7624#change-35089 Author: ko1 (Koichi Sasada) Status: Assigned Priority: Normal Assignee: usa (Usaku NAKAMURA) Category: Target version: The following program raises an exception in `return' event hook. ### class FOO < RuntimeError; end class BAR < RuntimeError; end def m1; m2; end def m2; m3; end def m3; raise FOO; end set_trace_func(lambda{|*args| if args[0] == 'return' p args raise BAR # raise in trace_func end}) begin m1 rescue => e p e ensure p :ensure end ### And this program cause strange behavior in each versions. --- # 2.0 trunk ruby 2.0.0dev (2012-12-21 trunk 38515) [i386-mswin32_100] ["return", "test.rb", 5, :m3, #<Binding:0x9781c8>, Object] test.rb:9:in `block in <main>': BAR (BAR) from test.rb:5:in `m3' from test.rb:4:in `m2' from test.rb:3:in `m1' from test.rb:12:in `<main>' # 1.9.3p332 (2012-11-15 revision 37660) ruby 1.9.3p332 (2012-11-15 revision 37660) [i386-mswin32_100] ["return", "test.rb", 5, :m3, #<Binding:0x2682980>, Object] ["return", "test.rb", 5, :m3, #<Binding:0x268278c>, Object] ... # infinite loop # 1.8.7 ruby 1.8.7 (2012-06-29 patchlevel 370) [i386-cygwin] ["return", "test.rb", 5, :m3, #<Binding:0x80057adc>, Object] ["return", "test.rb", 5, :m2, #<Binding:0x80057a64>, Object] ["return", "test.rb", 5, :m1, #<Binding:0x80057884>, Object] test.rb:13: [BUG] unexpected local variable assignment ruby 1.8.7 (2012-06-29 patchlevel 370) [i386-cygwin] 1 [sig] ruby 7388 open_stackdumpfile: Dumping stack trace to ruby.exe.stackdump # [BUG] !! and line number is not correct. --- # JRuby $ bin/jruby --debug -v test.rb jruby 1.7.2.dev (1.9.3p327) 2012-12-25 dc3af39 on OpenJDK Client VM 1.6.0_18-b18 [linux-i386] ["return", "test.rb", 5, :m3, #<Binding:0x1f7896f>, Object] ["return", "test.rb", 4, :m2, #<Binding:0x1abbec4>, Object] ["return", "test.rb", 3, :m1, #<Binding:0x2c03ff>, Object] #<BAR: BAR> :ensure --- # Ancient Ruby # 1.6.5 $ versions/install-tags_v1_6_5_/bin/ruby 'test.rb' 2>&1 ["return", "test.rb", 3, :m3, #<Binding:0xf755c7d0>, Object] ["return", "test.rb", 12, :m2, #<Binding:0xf755c5c8>, Object] ["return", "test.rb", 5, :m1, #<Binding:0xf755c424>, Object] #<BAR: BAR> :ensure # 1.8.6 $ versions/install-tags_v1_8_6_420_/bin/ruby 'test.rb' 2>&1 ["return", "test.rb", 5, :m3, #<Binding:0x7f9bc3032530>, Object] ["return", "test.rb", 4, :m2, #<Binding:0x7f9bc3032440>, Object] ["return", "test.rb", 3, :m1, #<Binding:0x7f9bc3032080>, Object] test.rb:13: [BUG] unexpected local variable assignment ruby 1.8.6 (2010-09-02) [x86_64-linux] --- 1.8 and before, exceptions from trace_fook are raised as normal exceptions. JRuby (with --debug) emulates this behavior correctly. Also CRuby 1.9 tried to handle exceptions as normal exceptions. However, it becomes infinite loop. ### (1) exception are occurred at m3 m1 m2 m3 raise ### (2) pop stack frames m1 m2 m3 ### (3) try m3 return hook m1 m2 m3 m3_return_hook ### (4) exception at m3_return_hook m1 m2 m3 m3_return_hook raise ### (5) pop stack frames and go to (3) m1 m2 m3 MRI 1.8 invokes hooks *after* pop m3. However, MRI 1.9 invoke hooks *before* pop m3. This is why infinite loop was made. ---- To solve this issue, current 2.0 pop all stack frames before return hook (when handling exception). Hoever, `ensure' etc was skipped. This is also issues. [Bug 7622], [Bug 7592] This corner case is confusing. ---- There are several solution about it. (1) Emulate 1.8's behavior. Which JRuby does :) No compatibility issue. (2) Do not propagate any errors from trace block Like thread, prohibit all of errors and escape (such as throw). (2') Output errors if any errors are occurred (3) Exit thread or program which current trunk done. ---- I think only few people use set_trace_func() because send bug report on it. (3) seems bad because ensure clause is ignored. This means current trunk is buggy. (1) is best way because no incompatibility and no discussion is needed. (2) (and (2')) has incompatible behavior from 1.9 and 1.8. But this approach seems good because trace hooks should not affect main program. I think (1) and (2) is valuable to discuss. ---- I'm sorry to propose such issue includes *compatibility*. I want to make it clear current status and choose correct way.
Please log in before posting. Registration is free and takes only a minute.
Existing account
(Switch to SSL-encrypted connection)
NEW: Do you have a Google/GoogleMail or Yahoo account? No registration required!
Log in with Google account | Log in with Yahoo account
Log in with Google account | Log in with Yahoo account
No account? Register here.