180 Commits
Author SHA1 Message Date
Alexander Momchilov 977e7fd392 [Bug #22070] Fix segfault in Thread.each_caller_location 2026-05-14 11:58:17 -07:00
Alan Wu 1a52c42e61 Always use assert-free APIs when profiling and crashing
rb_profile_frames() is used by profilers in a way such that it can run
on any instruction in the binary, and it crashed previously in the
following situation in `RUBY_DEBUG` builds:

```
* thread #1, queue = 'com.apple.main-thread', stop reason = step over
    frame #0: 0x00000001002827f0 miniruby`vm_make_env_each(ec=0x0000000101866b00, cfp=0x000000080c91bee8) at vm.c:992:74
   989              }
   990
   991              vm_make_env_each(ec, prev_cfp);
-> 992              VM_FORCE_WRITE_SPECIAL_CONST(&ep[VM_ENV_DATA_INDEX_SPECVAL], VM_GUARDED_PREV_EP(prev_cfp->ep));
   993          }
   994      }
   995      else {
(lldb) call rb_profile_frames(0, 100, $2, $3)
/Users/alan/ruby/vm_core.h:1448: Assertion Failed: VM_ENV_FLAGS:FIXNUM_P(flags)
ruby 3.5.0dev (2025-09-23T20:20:04Z master 06b7a70837) +PRISM [arm64-darwin25]

-- Crash Report log information --------------------------------------------
   See Crash Report log file in one of the following locations:
     * ~/Library/Logs/DiagnosticReports
     * /Library/Logs/DiagnosticReports
   for more details.
Don't forget to include the above Crash Report log file in bug reports.

-- Control frame information -----------------------------------------------
c:0008 p:---- s:0029 e:000028 CFUNC  :lambda
/Users/alan/ruby/vm_core.h:1448: Assertion Failed: VM_ENV_FLAGS:FIXNUM_P(flags)
ruby 3.5.0dev (2025-09-23T20:20:04Z master 06b7a70837) +PRISM [arm64-darwin25]

-- Crash Report log information --------------------------------------------
<snip>
```

There is a small window where the control frame is invalid and fails the
assert.

The double crash also shows that in `RUBY_DEBUG` builds, the crash reporter was
previously not resilient to corrupt frame state. In release builds, it
prints more info.

Add unchecked APIs for the crash reporter and profilers so they work
as well in `RUBY_DEBUG` builds as non-debug builds.
2025-09-25 18:30:12 -04:00
Alan Wu 06b7a70837 Fix thread_profile_frames crashing due to uninitialized PC
ZJIT never sets `cfp->jit_return`, so to avoid crashing while
profiling, we need to explicitly validate the PC of the top most frame.
Particularly pertinent for profilers that call rb_profile_frames() from
within a signal handler such as Vernier and Stackprof since they
can sample at any time and observe an invalid PC.
2025-09-23 16:20:04 -04:00
Peter Zhu b62753246e Fix out-of-bounds read in rb_location_ary_to_backtrace
rb_location_ary_to_backtrace was not checking the length of the array before
reading the first element. It can be reproduced by the following script:

    begin
      raise
    rescue
      $@ = []
    end

With assertions enabled, it crashes with:

    internal/array.h:143: Assertion Failed: RARRAY_AREF:i < RARRAY_LEN(ary)
    ruby 3.5.0dev (2025-09-10T19:01:16Z array-aref-assert-.. c431de0c64) +PRISM [arm64-darwin24]

    -- Crash Report log information --------------------------------------------
      See Crash Report log file in one of the following locations:
        * ~/Library/Logs/DiagnosticReports
        * /Library/Logs/DiagnosticReports
      for more details.
    Don't forget to include the above Crash Report log file in bug reports.

    -- Control frame information -----------------------------------------------
    c:0004 p:---- s:0015 e:000014 CFUNC  :set_backtrace
    c:0003 p:0013 s:0012 e:000009 RESCUE test.rb:4
    c:0002 p:0004 s:0006 e:000005 EVAL   test.rb:1 [FINISH]
    c:0001 p:0000 s:0003 E:001bb0 DUMMY  [FINISH]

    -- Ruby level backtrace information ----------------------------------------
    test.rb:1:in '<main>'
    test.rb:4:in 'rescue in <main>'
    test.rb:4:in 'set_backtrace'

    -- Threading information ---------------------------------------------------
    Total ractor count: 1
    Ruby thread count for this ractor: 1

    -- C level backtrace information -------------------------------------------
    miniruby(rb_vm_bugreport+0xb88) [0x1002adb88] vm_dump.c:1175
    miniruby(rb_vm_bugreport) (null):0
    miniruby(rb_assert_failure_detail+0xd4) [0x1003fbf90] error.c:1215
    miniruby(rb_assert_failure_detail+0x0) [0x1003fbebc] error.c:1191
    miniruby(rb_assert_failure) (null):0
    miniruby(RARRAY_AREF+0x20) [0x1003f82c8] internal/array.h:143
    miniruby(rb_keyword_error_new.cold.2) class.c:2867
    miniruby(rb_keyword_error_new.cold.4) (null):0
    miniruby(rb_location_ary_to_backtrace+0x244) [0x1002a8a60] internal/array.h:143
    miniruby(RB_TEST+0x0) [0x1000ba648] error.c:2111
    miniruby(exc_set_backtrace) error.c:2112
    miniruby(vm_call0_body+0x7d0) [0x1002a414c] vm_eval.c:164
    miniruby(rb_vm_call0+0x100) [0x100286ee4] vm_eval.c:101
    miniruby(set_backtrace+0xfc) [0x1000c88a4] eval_error.c:75
    miniruby(rb_gvar_set_entry+0x10) [0x100269230] variable.c:990
    miniruby(rb_gvar_set) variable.c:1021
    miniruby(vm_exec_core+0x1258) [0x10027a744] insns.def:319
    miniruby(rb_vm_exec+0x324) [0x100277a8c] vm.c:2666
    miniruby(rb_ec_exec_node+0x74) [0x1000c4a38] eval.c:282
    miniruby(ruby_run_node+0x64) [0x1000c4968] eval.c:320
    miniruby(rb_main+0x1c) [0x100000980] main.c:42
    miniruby(main) main.c:62
2025-09-11 08:14:25 -04:00
Yusuke Endoh ed8fe53e80 Allow to get a NODE_SCOPE node of dummy stack frame of ArgumentError
Previously, it was not possible to obtain a node of the callee's
`Thread::Backtrace::Location` for cases like "wrong number of
arguments" by using `RubyVM::AST.of`. This change allows that retrieval.

This is preparation for [Feature #21543].
2025-08-28 12:44:29 +09:00
Yusuke Endoh fd59ac6410 vm_backtrace.c: add RB_GC_GUARD for name in location_format
`name` is used via `RSTRING_PTR` within rb_str_catf, which may allocate
and thus potentially trigger GC. Although `name` is still referenced
by a local variable, the compiler might optimize away the reference
before the GC sees it, especially under aggressive optimization or when
debugging tools like ASAN are used.

This patch adds an explicit `RB_GC_GUARD` to ensure `name` is kept alive
until after the last use.

While it's not certain this is the root cause of the following observed
use-after-poison ASAN error, I believe this fix is indeed needed and
hopefully a likely candidate for preventing the error.

```
==1960369==ERROR: AddressSanitizer: use-after-poison on address 0x7ec6a00f1d88 at pc 0x5fb5bcafcf2e bp 0x7ffcc1178cb0 sp 0x7ffcc1178470
READ of size 61 at 0x7ec6a00f1d88 thread T0
    #0 0x5fb5bcafcf2d in __asan_memcpy (/tmp/ruby/build/trunk_asan/ruby+0x204f2d) (BuildId: 6d92c84a27b87cfd253c38eeb552593f215ffb3d)
    #1 0x5fb5bcde1fa5 in memcpy /usr/include/x86_64-linux-gnu/bits/string_fortified.h:29:10
    #2 0x5fb5bcde1fa5 in ruby_nonempty_memcpy /tmp/ruby/src/trunk_asan/include/ruby/internal/memory.h:758:16
    #3 0x5fb5bcde1fa5 in ruby__sfvwrite /tmp/ruby/src/trunk_asan/sprintf.c:1083:9
    #4 0x5fb5bcde1521 in BSD__sprint /tmp/ruby/src/trunk_asan/vsnprintf.c:318:8
    #5 0x5fb5bcde0fbc in BSD_vfprintf /tmp/ruby/src/trunk_asan/vsnprintf.c:1215:3
    #6 0x5fb5bcdde4b1 in ruby_vsprintf0 /tmp/ruby/src/trunk_asan/sprintf.c:1164:5
    #7 0x5fb5bcddd648 in rb_str_vcatf /tmp/ruby/src/trunk_asan/sprintf.c:1234:5
    #8 0x5fb5bcddd648 in rb_str_catf /tmp/ruby/src/trunk_asan/sprintf.c:1245:11
    #9 0x5fb5bcf97c67 in location_format /tmp/ruby/src/trunk_asan/vm_backtrace.c:462:9
    #10 0x5fb5bcf97c67 in location_to_str /tmp/ruby/src/trunk_asan/vm_backtrace.c:493:12
    #11 0x5fb5bcf90a37 in location_to_str_dmyarg /tmp/ruby/src/trunk_asan/vm_backtrace.c:795:12
    #12 0x5fb5bcf90a37 in backtrace_collect /tmp/ruby/src/trunk_asan/vm_backtrace.c:786:28
    #13 0x5fb5bcf90a37 in backtrace_to_str_ary /tmp/ruby/src/trunk_asan/vm_backtrace.c:804:9
    #14 0x5fb5bcf90a37 in rb_backtrace_to_str_ary /tmp/ruby/src/trunk_asan/vm_backtrace.c:816:9
    #15 0x5fb5bd335b25 in exc_backtrace /tmp/ruby/src/trunk_asan/error.c:1904:15
    #16 0x5fb5bd335b25 in rb_get_backtrace /tmp/ruby/src/trunk_asan/error.c:1924:16
```
https://ci.rvm.jp/results/trunk_asan@ruby-sp1/5810304
2025-06-30 16:00:04 +09:00
Yusuke Endoh a18fa86351 Change how to correct the first lineno in the backtrace on ArgumentError
Follow up to fix 3b7373fd00.
In that commit, the line number in the first frame was overwritten after
the whole backtrace was created. There was a problem that the line
number was overwritten even if the location was backpatched.

Instead, this commit uses first_lineno if the frame is
VM_FRAME_MAGIC_DUMMY when generating the backtrace.

Before the patch:
```
$ ./miniruby -e '[1, 2].inject(:tap)'
-e:in '<main>': wrong number of arguments (given 1, expected 0) (ArgumentError)
        from -e:1:in 'Enumerable#inject'
        from -e:1:in '<main>'
```

After the patch:
```
$ ./miniruby -e '[1, 2].inject(:tap)'
-e:1:in '<main>': wrong number of arguments (given 1, expected 0) (ArgumentError)
        from -e:1:in 'Enumerable#inject'
        from -e:1:in '<main>'
```
2025-06-24 11:39:58 +09:00
Yusuke Endoh 10767283dd Exclude internal frames from backtrace
This changeset suppresses backtrace locations like
`<internal:array>:211` as much as possible.

Before the patch:
```
$ ruby -e '[1].fetch_values(42)'
<internal:array>:211:in 'Array#fetch': index 42 outside of array bounds: -1...1 (IndexError)
        from <internal:array>:211:in 'block in Array#fetch_values'
        from <internal:array>:211:in 'Array#map!'
        from <internal:array>:211:in 'Array#fetch_values'
        from -e:1:in '<main>'
```

After the patch:
```
$ ./miniruby -e '[1].fetch_values(42)'
-e:1:in 'Array#fetch_values': index 42 outside of array bounds: -1...1 (IndexError)
        from -e:1:in '<main>'
```

Specifically:

* The special backtrace handling of BUILTIN_ATTR_C_TRACE is now always
  applied to frames with `<internal:...>`.
* When multiple consecutive internal frames appear, all but the bottom
  (caller-side) frame are removed.

[Misc #20968]
2025-06-18 14:51:56 +09:00
Yusuke Endoh ca10c521ff refactor: rename bt_update_cfunc_loc to bt_backpatch_loc
In preparation for using it to update not only cfunc frames but also
internal frames, the function (and related variable names) are chagned.

I felt that the word "backpatch" is more appropriate than the more
general verb "update" here.
2025-06-18 14:51:56 +09:00
Yusuke Endoh caa6ba1a46 Make rb_debug_inspector_backtrace_locations return a raw backtrace
Previously, a user of the debug inspector API was supposed to use
`rb_debug_inspector_backtrace_locations` to get an array of
`Thread::Backtrace::Location`, and then used its index to get more
information from `rb_debug_inspector _frame_binding_get(index)`, etc.

However, `rb_debug_inspector_backtrace_locations` returned an array of
backtraces excluding rescue/ensure frames. On the other hand,
`rb_debug_inspector_frame_binding_get(index)` interprets index with
rescue/ensure frames. This led to inconsistency of the index, and it was
very difficult to correctly use the debug inspector API.

This is a minimal fix for the issue by making
`rb_debug_inspector_backtrace_locations` return a raw backtrace
including rescue/ensure frames.
2025-06-04 19:53:16 +09:00
Masataka Pocke KuwabaraandJeremy Evans 0cab608d3a [Bug #21127] Thread deadlock does not display backtraces (#12721)
Previously, Ruby displayed backtraces for each thread on deadlock. However, it has not been shown since Ruby 3.0.
It should display the backtrace for debugging.

Co-authored-by: Jeremy Evans <code@jeremyevans.net>
2025-02-14 16:31:58 +09:00
Takashi Kokubun 478e0fc710 YJIT: Replace Array#each only when YJIT is enabled (#11955)
* YJIT: Replace Array#each only when YJIT is enabled

* Add comments about BUILTIN_ATTR_C_TRACE

* Make Ruby Array#each available with --yjit as well

* Fix all paths that expect a C location

* Use method_basic_definition_p to detect patches

* Copy a comment about C_TRACE flag to compilers

* Rephrase a comment about add_yjit_hook

* Give METHOD_ENTRY_BASIC flag to Array#each

* Add --yjit-c-builtin option

* Allow inconsistent source_location in test-spec

* Refactor a check of BUILTIN_ATTR_C_TRACE

* Set METHOD_ENTRY_BASIC without touching vm->running
2024-11-04 11:14:28 -05:00
Nobuyoshi Nakada 09638741ba [Feature #20335] Thread.each_caller_location arguments
Accecpt the same arguments as `caller` and `caller_locations`.
2024-04-17 18:47:07 +09:00
Koichi Sasada 9180e33ca3 show warning for unused block
With verbopse mode (-w), the interpreter shows a warning if
a block is passed to a method which does not use the given block.

Warning on:

* the invoked method is written in C
* the invoked method is not `initialize`
* not invoked with `super`
* the first time on the call-site with the invoked method
  (`obj.foo{}` will be warned once if `foo` is same method)

[Feature #15554]

`Primitive.attr! :use_block` is introduced to declare that primitive
functions (written in C) will use passed block.

For minitest, test needs some tweak, so use
https://github.com/minitest/minitest/commit/ea9caafc0754b1d6236a490d59e624b53209734a
for `test-bundled-gems`.
2024-04-15 12:08:07 +09:00
Peter Zhu 3e0eea644f Don't set RUBY_TYPED_EMBEDDABLE flag on backtrace 2024-03-26 13:53:00 -04:00
Gannon McGibbonandPeter Zhu 4bdb79618b Mark frame info structs with rb_gc_mark_movable
Using rb_gc_mark_movable and a reference update function, we can make
frame infos movable in memory, and avoid pinning frame info backtraces.

```
require "objspace"
exceptions = []
GC.disable
50_000.times do
  begin
    raise "some exception"
  rescue => exception
    exception.backtrace_locations
    exceptions << exception
  end
end
GC.enable
GC.compact
p ObjectSpace.dump_all(output: :string).lines.grep(/"pinned":true/).count
```

Co-authored-by: Peter Zhu <peter@peterzhu.ca>
2024-03-26 13:53:00 -04:00
Xavier Noria 3b4dacf2ed Let the docs of base_label and label be similar 2024-03-25 14:13:05 +01:00
Xavier NoriaandJean Boussier dadaa1142f Update vm_backtrace.c
Co-authored-by: Jean Boussier <jean.boussier@gmail.com>
2024-03-25 14:13:05 +01:00
Xavier Noria 4235bc295b Add an example to base_label API 2024-03-25 14:13:05 +01:00
Benoit Daloze 74995a1a77 [Feature #20275] Remove extra backtrace entries for rescue and ensure 2024-03-22 12:30:15 +01:00
Jean BoussierandÉtienne Barrié 315bde5a0f Exception#set_backtrace accept arrays of Backtrace::Location
[Feature #13557]

Setting the backtrace with an array of strings is lossy. The resulting
exception will return nil on `#backtrace_locations`.

By accepting an array of `Backtrace::Location` instance, we can rebuild
a `Backtrace` instance and have a fully functioning Exception.

Co-Authored-By: Étienne Barrié <etienne.barrie@gmail.com>
2024-03-14 11:38:40 +01:00
Jean Boussier d4f3dcf4df Refactor VM root modules
This `st_table` is used to both mark and pin classes
defined from the C API. But `vm->mark_object_ary` already
does both much more efficiently.

Currently a Ruby process starts with 252 rooted classes,
which uses `7224B` in an `st_table` or `2016B` in an `RArray`.

So a baseline of 5kB saved, but since `mark_object_ary` is
preallocated with `1024` slots but only use `405` of them,
it's a net `7kB` save.

`vm->mark_object_ary` is also being refactored.

Prior to this changes, `mark_object_ary` was a regular `RArray`, but
since this allows for references to be moved, it was marked a second
time from `rb_vm_mark()` to pin these objects.

This has the detrimental effect of marking these references on every
minors even though it's a mostly append only list.

But using a custom TypedData we can save from having to mark
all the references on minor GC runs.

Addtionally, immediate values are now ignored and not appended
to `vm->mark_object_ary` as it's just wasted space.
2024-03-06 15:33:43 -05:00
Jean Boussier b4a69351ec Move FL_SINGLETON to FL_USER1
This frees FL_USER0 on both T_MODULE and T_CLASS.

Note: prior to this, FL_SINGLETON was never set on T_MODULE,
so checking for `FL_SINGLETON` without first checking that
`FL_TYPE` was `T_CLASS` was valid. That's no longer the case.
2024-03-06 13:11:41 -05:00
Yusuke Endoh a7718c914a Do not show an anonymous class as a receiver 2024-02-15 20:43:11 +09:00
Yusuke Endoh 9d1b000bd1 Show the method owner in backtraces
```
test.rb:1:in 'Object#toplevel_meth': unhandled exception
        from test.rb:4:in 'Foo.class_meth'
        from test.rb:6:in 'Foo#instance_meth'
        from test.rb:11:in 'singleton_meth'
        from test.rb:13:in '<main>'
```

[Feature #19117]
2024-02-15 19:11:58 +09:00
Yusuke Endoh 61819c87b2 Let Thread::Backtrace::Location have a method entry
Instead of having iseq and cfunc separately, this change lets
Thread::Backtrace::Location have them together as
rb_callable_method_entry_t.

This is a refactoring, but also a preparation for implementing
[Feature #19117].
2024-02-15 19:11:58 +09:00
Yusuke Endoh 25d74b9527 Do not include a backtick in error messages and backtraces
[Feature #16495]
2024-02-15 18:42:31 +09:00
Dylan Thacker-Smith 2b96737636 Fix use of the rb_profile_frames start parameter
Previously, it was decrementing the start argument until it reached
zero without actually changing the control frame pointer.

[Bug #14607]
2023-12-28 08:58:21 -08:00
John HawthornandDustin Brown ffa5f16273 Make rb_profile_frames return 0 for NULL ec
When using M:N threads, EC is set to NULL in the shared native thread
when nothing is scheduled. This previously caused a segfault when we try
to examine the EC.

Returning 0 instead means we may miss profiling information, but a
profiler relying on this isn't thread aware anyways, and observing that
"nothing" is running is probably correct.

Fixes [Bug #20017]

Co-authored-by: Dustin Brown <dbrown9@gmail.com>
2023-12-21 15:23:19 -08:00
Jean Boussier b4f551686b Get rid of useless dsize functions
If we always return 0, we might as well not define
the function at all.
2023-11-21 15:15:03 +01:00
Étienne BarriéandJean Boussier 46ef74f270 Embed Thread::Backtrace::Location into Thread::Backtrace
Co-authored-by: Jean Boussier <byroot@ruby-lang.org>
2023-11-20 15:23:56 +01:00
Jean BoussierandÉtienne Barrié 3b69637eba Embed Backtrace objects
rb_backtrace_t is 32B, so it fits well in a 80B slot.

There is some unused spaces but given Backtrace objects are
rarely held onto it should be inconsequential and avoid
the malloc churn.

Co-Authored-By: Étienne Barrié <etienne.barrie@gmail.com>
2023-11-10 15:56:42 +01:00
Jean BoussierandÉtienne Barrié a2442e91fd Embed Backtrace::Location objects
The struct is 16B, so they will use the 80B size pool, so on paper it
wastes 80 - 32 - 16 = 52B, however most malloc implementations will
either pad sizes or use an extra 16B for each segment, so in practice
the waste isn't that big. Also `Backtrace::Location` are rarely held
on for long, so avoiding the malloc churn help performance.

Co-Authored-By: Étienne Barrié <etienne.barrie@gmail.com>
2023-11-10 15:56:22 +01:00
Daisuke AritomoandMike Perham 4adf418be9 [Feature #10602] Add new API rb_profile_thread_frames()
Add a new API rb_profile_thread_frames(), which is essentialy a
per-thread version of rb_profile_frames().

While the original rb_profile_frames() always returns results about the
current active thread obtained by GET_EC(), this new API takes a Thread
to be profiled as an argument.

This should come in handy when profiling I/O-bound programs such as
webapps, since this new API allows us to learn about Threads performing
I/O (which do not have the GVL).

Profiling worker threads (such as Sidekiq workers) may be another
application.

Implements [Feature #10602]

Co-authored-by: Mike Perham <mike@perham.net>
2023-10-31 11:16:18 +09:00
Nobuyoshi Nakada ac244938e8 Dump backtraces to an arbitrary stream 2023-09-25 22:57:28 +09:00
Aaron Patterson a1dc1a3de9 Return line 0 for JIT frames
Frames pushed by YJIT have an unreliable PC.  The PC could be garbage,
and if we try to read the line number with a garbage PC, then the
program can crash.

This commit returns line 0 for programs where there is a `jit_return`
function.  If `jit_return` has been set then this frame was pushed by
the JIT, and we cannot trust the PC.

Here is a debugger session for a program that crashed due to a broken
PC:

```
(lldb) p ruby_current_vm_ptr->ractor.main_thread->ec->cfp->iseq->body->iseq_encoded
(VALUE *) $0 = 0x0000000118a30e00
(lldb) p/x ruby_current_vm_ptr->ractor.main_thread->ec->cfp->pc
(const VALUE *) $1 = 0x0000600000b02d00
(lldb) p/x ruby_current_vm_ptr->ractor.main_thread->ec->cfp->jit_return
(void *) $2 = 0x000000010622942c
```

You can see the PC is completely out of range, but there is a
`jit_return` pointer so we can avoid this crash.
2023-09-15 09:01:02 -07:00
Peter Zhu 58386814a7 Don't check for null pointer in calls to free
According to the C99 specification section 7.20.3.2 paragraph 2:

> If ptr is a null pointer, no action occurs.

So we do not need to check that the pointer is a null pointer.
2023-06-30 09:13:31 -04:00
Nobuyoshi Nakada b738cb01b6 Suppress -Wsign-compare warning 2023-03-23 23:31:46 +09:00
Takashi Kokubun 233ddfac54 Stop exporting symbols for MJIT 2023-03-06 21:59:23 -08:00
Jean Boussier 7413079dae Encapsulate RCLASS_ATTACHED_OBJECT
Right now the attached object is stored as an instance variable
and all the call sites that either get or set it have to know how it's
stored.

It's preferable to hide this implementation detail behind accessors
so that it is easier to change how it's stored.
2023-02-15 15:24:22 +01:00
John HawthornandAdam Hess 91b18dc88c Use write barriers for Backtrace objects
Backtrace objects hold references to:
* iseqs - via the captured locations
* strary - a lazily allocated array of strings
* locary - a lazily allocated array of backtrace locations

Co-authored-by: Adam Hess <HParker@github.com>
2023-02-07 11:16:50 -08:00
Jean Boussier 8e7d2cc2ab Implement Write Barrier for Backtrace::Location
It only has a single reference, set in a single place.
2023-02-03 15:58:44 +01:00
Aaron Patterson eab7f4623f Return 0 if there is no CFP on the EC yet
StackProf uses a signal handler to call `rb_profile_frames`.  Signals
are delivered to threads randomly, and can be delivered after the thread
has been created but before the CFP has been established on the EC.

This commit returns early if there is no CFP to use.

Here is some info from the core files we are seeing.  Here you can see
the CFP on the current EC is 0x0:

```
(gdb) p ruby_current_ec
$20 = (struct rb_execution_context_struct *) 0x7f3481301b50
(gdb) p ruby_current_ec->cfp
$21 = (rb_control_frame_t *) 0x0
```

Here is where VM_FRAME_CFRAME_P gets a 0x0 CFP:

```
6  VM_FRAME_CFRAME_P (cfp=0x0) at vm_core.h:1350
7  VM_FRAME_RUBYFRAME_P (cfp=<optimized out>) at vm_core.h:1350
8  rb_profile_frames (start=0, limit=2048, buff=0x7f3493809590, lines=0x7f349380d590) at vm_backtrace.c:1587
```

Down the stack we can see this is happening after thread creation:

```
19 0x00007f3495bf9420 in <signal handler called> () at /lib/x86_64-linux-gnu/libpthread.so.0
20 0x000055d531574e55 in thread_start_func_2 (th=<optimized out>, stack_start=<optimized out>) at thread.c:676
21 0x000055d531575b31 in thread_start_func_1 (th_ptr=<optimized out>) at thread_pthread.c:1170
22 0x00007f3495bed609 in start_thread (arg=<optimized out>) at pthread_create.c:477
23 0x00007f3495b12133 in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:95
```
2023-01-12 17:11:40 -08:00
Koichi Sasada 67766cd55c add debug context APIs for debuggers (frame depth)
The following new debug context APIs are for implementing debugger's
`next` (step over) and similar functionality.

* `rb_debug_inspector_frame_depth(dc, index)` returns `index`-th
  frame's depth.
* `rb_debug_inspector_current_depth()` returns current frame depth.

The frame depth is not related to the frame index because debug
context API skips some special frames but proposed `_depth()` APIs
returns the count of all frames (raw depth).
2022-11-25 14:01:36 +09:00
Yudai Takada 29e6d97517 Fix typos (#6775)
* s/Innteger/Integer/

* s/diretory/directory/

* s/Bufer/Buffer/

* s/defalt/default/

* s/covearge/coverage/
2022-11-20 21:07:18 -08:00
Koichi Sasada e35c528d72 push dummy frame for loading process
This patch pushes dummy frames when loading code for the
profiling purpose.

The following methods push a dummy frame:
* `Kernel#require`
* `Kernel#load`
* `RubyVM::InstructionSequence.compile_file`
* `RubyVM::InstructionSequence.load_from_binary`

https://bugs.ruby-lang.org/issues/18559
2022-10-20 17:38:28 +09:00
Samuel Williams 22af2e9084 Rework vm_core to use int first_lineno struct member. 2022-09-26 00:41:16 +13:00
Nobuyoshi Nakada 58c8b6e862 Adjust styles [ci skip] 2022-08-06 10:13:20 +09:00
Ivo Anjo 649bfbe00d Fix rb_profile_frames output includes dummy main thread frame
The `rb_profile_frames` API did not skip the two dummy frames that
each thread has at its beginning. This was unlike `backtrace_each` and
`rb_ec_parcial_backtrace_object`, which do skip them.

This does not seem to be a problem for non-main thread frames,
because both `VM_FRAME_RUBYFRAME_P(cfp)` and
`rb_vm_frame_method_entry(cfp)` are NULL for them.

BUT, on the main thread `VM_FRAME_RUBYFRAME_P(cfp)` was true
and thus the dummy thread was still included in the output of
`rb_profile_frames`.

I've now made `rb_profile_frames` skip this extra frame (like
`backtrace_each` and friends), as well as add a test that asserts
the size and contents of `rb_profile_frames`.

Fixes [Bug #18907] (<https://bugs.ruby-lang.org/issues/18907>)
2022-07-26 10:43:44 +09:00
Takashi Kokubun 5b21e94beb Expand tabs [ci skip]
[Misc #18891]
2022-07-21 09:42:04 -07:00