Issue #18053 has been updated by jeremyevans0 (Jeremy Evans).

Backport changed from 2.6: UNKNOWN, 2.7: UNKNOWN, 3.0: UNKNOWN to 2.6: DONTNEED, 2.7: DONTNEED, 3.0: REQUIRED

I committed my rewrite of backtrace generation (commit:1a05dc03f953830564c272665c47a61e53550f3e), which fixes these issues in master/3.1. I took the examples from this issue and added them as tests in that commit.

For Ruby 3.0, there are a few options:

1. Backout partial backtrace optimization
2. Merge rewrite of backtrace generation
3. Fix partial backtrace optimization.

The issue with option 1 is that commit:cffdacb15a363321e1c1879aa7d94924acafd1cf was merged after the optimization was committed, and it is nontrivial to backout the partial backtrace optimization and still keep that feature.  I tried, but my attempt could not pass CI.  Additionally, even if the issues with the backout could be fixed, using the backout approach would make partial backtraces slower.

The issue with option 2 is that commit:1a05dc03f953830564c272665c47a61e53550f3e is fairly invasive.  I'm fairly sure it would apply cleanly to 3.0, but I'm not sure if @nagachika would be comfortable backporting such a large change.  

So I worked on implementing option 3.  It took many hours to make the new test cases pass without breaking existing test cases, but I eventually did get it to work.  The way I got it to work was using a similar strategy as was used for commit:1a05dc03f953830564c272665c47a61e53550f3e. Basically, scan the backtrace from the current frame toward the earliest frame instead of from the earlier frame to the current frame.  When we come to the frame that will complete the partial backtrace, we use that as the starting frame for backtrace generation, and backtrace generation still works from earlier frames towards the current frame. I submitted a pull request for this option: https://github.com/ruby/ruby/pull/4714

----------------------------------------
Bug #18053: Crashes and infinite loops when generating partial backtraces in Ruby 3.0+
https://bugs.ruby-lang.org/issues/18053#change-93150

* Author: jhawthorn (John Hawthorn)
* Status: Closed
* Priority: Normal
* ruby -v: ruby 3.1.0dev (2021-07-29T22:19:12Z master 9931e2f509) [x86_64-linux]
* Backport: 2.6: DONTNEED, 2.7: DONTNEED, 3.0: REQUIRED
----------------------------------------
In Ruby 3.0+ there are some cases where generating a partial backtrace will hang (due to an infinite loop) or segfault. This is also an issue in Ruby master.

``` ruby
def foo
  caller_locations(2, 1).inspect # this will segv
  # caller_locations(2, 1)[0].path # this will infinite loop
end

1.times.map { 1.times.map { foo } }
```

```
$ ./ruby test_caller_locations.rb
test_caller_locations.rb:4: [BUG] Segmentation fault at 0x00000000000027e1
ruby 3.1.0dev (2021-07-29T22:19:12Z master 9931e2f509) [x86_64-linux]

-- Control frame information -----------------------------------------------
c:0015 p:---- s:0049 e:000048 CFUNC  :inspect
c:0014 p:---- s:0046 e:000045 CFUNC  :inspect
c:0013 p:0008 s:0042 e:000041 METHOD test_caller_locations.rb:4
c:0012 p:0003 s:0038 e:000037 BLOCK  test_caller_locations.rb:8 [FINISH]
c:0011 p:---- s:0035 e:000034 IFUNC
c:0010 p:---- s:0032 e:000031 CFUNC  :times
c:0009 p:---- s:0029 e:000028 CFUNC  :each
c:0008 p:---- s:0026 e:000025 CFUNC  :map
c:0007 p:0006 s:0022 e:000021 BLOCK  test_caller_locations.rb:8 [FINISH]
c:0006 p:---- s:0019 e:000018 IFUNC
c:0005 p:---- s:0016 e:000015 CFUNC  :times
c:0004 p:---- s:0013 e:000012 CFUNC  :each
c:0003 p:---- s:0010 e:000009 CFUNC  :map
c:0002 p:0009 s:0006 e:000005 EVAL   test_caller_locations.rb:8 [FINISH]
c:0001 p:0000 s:0003 E:0002b0 (none) [FINISH]
```

At least part of what seems to be happening is that the backtrace locations are generated with `prev_loc` pointing to itself. I added some assertions to catch this, but had a hard time finding what the intended behaviour should have been from there.

cc @jeremyevans0

---Files--------------------------------
output.txt (21.2 KB)
0001-Add-assertions-for-bad-backtrace-locations.patch (2.51 KB)


-- 
https://bugs.ruby-lang.org/

Unsubscribe: <mailto:ruby-core-request / ruby-lang.org?subject=unsubscribe>
<http://lists.ruby-lang.org/cgi-bin/mailman/options/ruby-core>