Skip to content

Commit 0963874

Browse files
committed
[Feature #20335] Thread.each_caller_location arguments
Accecpt the same arguments as `caller` and `caller_locations`.
1 parent 7bc66a3 commit 0963874

File tree

5 files changed

+42
-33
lines changed

5 files changed

+42
-33
lines changed

lib/bundled_gems.rb

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -143,18 +143,8 @@ def self.build_message(gem)
143143
# Additionally, we need to skip Bootsnap and Zeitwerk if present, these
144144
# gems decorate Kernel#require, so they are not really the ones issuing
145145
# the require call users should be warned about. Those are upwards.
146-
frames_to_skip = 2
147-
location = nil
148-
Thread.each_caller_location do |cl|
149-
if frames_to_skip >= 1
150-
frames_to_skip -= 1
151-
next
152-
end
153-
154-
if cl.base_label != "require"
155-
location = cl.path
156-
break
157-
end
146+
location = Thread.each_caller_location(2) do |cl|
147+
break cl.path unless cl.base_label == "require"
158148
end
159149

160150
if location && File.file?(location) && !location.start_with?(Gem::BUNDLED_GEMS::LIBDIR)

spec/ruby/core/thread/each_caller_location_spec.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,10 +40,10 @@
4040
}.should raise_error(LocalJumpError, "no block given")
4141
end
4242

43-
it "doesn't accept positional and keyword arguments" do
43+
it "doesn't accept keyword arguments" do
4444
-> {
4545
Thread.each_caller_location(12, foo: 10) {}
46-
}.should raise_error(ArgumentError, "wrong number of arguments (given 2, expected 0)")
46+
}.should raise_error(ArgumentError);
4747
end
4848
end
4949
end

spec/ruby/optional/capi/spec_helper.rb

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -33,12 +33,6 @@ def compile_extension(name)
3333
ruby_header = "#{rubyhdrdir}/ruby.h"
3434
abi_header = "#{rubyhdrdir}/ruby/internal/abi.h"
3535

36-
if RbConfig::CONFIG["ENABLE_SHARED"] == "yes"
37-
# below is defined since 2.1, except for mswin, and maybe other platforms
38-
libdirname = RbConfig::CONFIG.fetch 'libdirname', 'libdir'
39-
libruby = "#{RbConfig::CONFIG[libdirname]}/#{RbConfig::CONFIG['LIBRUBY']}"
40-
end
41-
4236
begin
4337
mtime = File.mtime(lib)
4438
rescue Errno::ENOENT
@@ -49,7 +43,6 @@ def compile_extension(name)
4943
when mtime <= File.mtime("#{spec_ext_dir}/#{ext}.c")
5044
when mtime <= File.mtime(ruby_header)
5145
when (mtime <= File.mtime(abi_header) rescue nil)
52-
when libruby && mtime <= File.mtime(libruby)
5346
else
5447
return lib # up-to-date
5548
end

test/ruby/test_backtrace.rb

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,10 @@ def test_caller_with_nil_length
155155
end
156156

157157
def test_each_backtrace_location
158+
assert_nil(Thread.each_caller_location {})
159+
160+
assert_raise(LocalJumpError) {Thread.each_caller_location}
161+
158162
i = 0
159163
cl = caller_locations(1, 1)[0]; ecl = Thread.each_caller_location{|x| i+=1; break x if i == 1}
160164
assert_equal(cl.to_s, ecl.to_s)
@@ -181,6 +185,10 @@ def test_each_backtrace_location
181185
assert_raise(StopIteration) {
182186
ecl.next
183187
}
188+
189+
ary = []
190+
cl = caller_locations(1, 2); Thread.each_caller_location(1, 2) {|x| ary << x}
191+
assert_equal(cl.map(&:to_s), ary.map(&:to_s))
184192
end
185193

186194
def test_caller_locations_first_label

vm_backtrace.c

Lines changed: 30 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1170,17 +1170,17 @@ rb_make_backtrace(void)
11701170
return rb_ec_backtrace_str_ary(GET_EC(), BACKTRACE_START, ALL_BACKTRACE_LINES);
11711171
}
11721172

1173-
static VALUE
1174-
ec_backtrace_to_ary(const rb_execution_context_t *ec, int argc, const VALUE *argv, int lev_default, int lev_plus, int to_str)
1173+
static long
1174+
ec_backtrace_range(const rb_execution_context_t *ec, int argc, const VALUE *argv, int lev_default, int lev_plus, long *len_ptr)
11751175
{
1176-
VALUE level, vn;
1176+
VALUE level, vn, opts;
11771177
long lev, n;
1178-
VALUE btval;
1179-
VALUE r;
1180-
int too_large;
11811178

1182-
rb_scan_args(argc, argv, "02", &level, &vn);
1179+
rb_scan_args(argc, argv, "02:", &level, &vn, &opts);
11831180

1181+
if (!NIL_P(opts)) {
1182+
rb_get_kwargs(opts, (ID []){0}, 0, 0, NULL);
1183+
}
11841184
if (argc == 2 && NIL_P(vn)) argc--;
11851185

11861186
switch (argc) {
@@ -1201,7 +1201,7 @@ ec_backtrace_to_ary(const rb_execution_context_t *ec, int argc, const VALUE *arg
12011201
n = ALL_BACKTRACE_LINES;
12021202
break;
12031203
case Qnil:
1204-
return Qnil;
1204+
return -1;
12051205
default:
12061206
lev = beg + lev_plus;
12071207
n = len;
@@ -1225,6 +1225,20 @@ ec_backtrace_to_ary(const rb_execution_context_t *ec, int argc, const VALUE *arg
12251225
break;
12261226
}
12271227

1228+
*len_ptr = n;
1229+
return lev;
1230+
}
1231+
1232+
static VALUE
1233+
ec_backtrace_to_ary(const rb_execution_context_t *ec, int argc, const VALUE *argv, int lev_default, int lev_plus, int to_str)
1234+
{
1235+
long lev, n;
1236+
VALUE btval, r;
1237+
int too_large;
1238+
1239+
lev = ec_backtrace_range(ec, argc, argv, lev_default, lev_plus, &n);
1240+
if (lev < 0) return Qnil;
1241+
12281242
if (n == 0) {
12291243
return rb_ary_new();
12301244
}
@@ -1354,15 +1368,19 @@ rb_f_caller_locations(int argc, VALUE *argv, VALUE _)
13541368

13551369
/*
13561370
* call-seq:
1357-
* Thread.each_caller_location{ |loc| ... } -> nil
1371+
* Thread.each_caller_location(...) { |loc| ... } -> nil
13581372
*
13591373
* Yields each frame of the current execution stack as a
13601374
* backtrace location object.
13611375
*/
13621376
static VALUE
1363-
each_caller_location(VALUE unused)
1377+
each_caller_location(int argc, VALUE *argv, VALUE _)
13641378
{
1365-
rb_ec_partial_backtrace_object(GET_EC(), 2, ALL_BACKTRACE_LINES, NULL, FALSE, TRUE);
1379+
rb_execution_context_t *ec = GET_EC();
1380+
long n, lev = ec_backtrace_range(ec, argc, argv, 1, 1, &n);
1381+
if (lev >= 0 && n != 0) {
1382+
rb_ec_partial_backtrace_object(ec, lev, n, NULL, FALSE, TRUE);
1383+
}
13661384
return Qnil;
13671385
}
13681386

@@ -1442,7 +1460,7 @@ Init_vm_backtrace(void)
14421460
rb_define_global_function("caller", rb_f_caller, -1);
14431461
rb_define_global_function("caller_locations", rb_f_caller_locations, -1);
14441462

1445-
rb_define_singleton_method(rb_cThread, "each_caller_location", each_caller_location, 0);
1463+
rb_define_singleton_method(rb_cThread, "each_caller_location", each_caller_location, -1);
14461464
}
14471465

14481466
/* debugger API */

0 commit comments

Comments
 (0)