Skip to content

Commit ba2240c

Browse files
committed
Use TracePoint.allow_reentry to support TracePoint events while eval
1 parent 920c352 commit ba2240c

3 files changed

Lines changed: 86 additions & 5 deletions

File tree

ext/byebug/threads.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,8 +180,16 @@ release_lock(void)
180180
static VALUE
181181
Unlock(VALUE self)
182182
{
183+
debug_context_t *dc;
184+
VALUE context;
185+
183186
UNUSED(self);
184187

188+
thread_context_lookup(rb_thread_current(), &context);
189+
Data_Get_Struct(context, debug_context_t, dc);
190+
191+
CTX_FL_SET(dc, CTX_FL_IGNORE);
192+
185193
release_lock();
186194

187195
return locker;
@@ -209,6 +217,8 @@ Lock(VALUE self)
209217

210218
acquire_lock(dc);
211219

220+
CTX_FL_UNSET(dc, CTX_FL_IGNORE);
221+
212222
return locker;
213223
}
214224

lib/byebug/helpers/eval.rb

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -88,14 +88,12 @@ def warning_msg(exception)
8888
# creating new threads won't be properly evaluated because new threads
8989
# will get blocked by byebug's main thread.
9090
#
91-
def allowing_other_threads
91+
def allowing_other_threads(&block)
9292
Byebug.unlock
9393

94-
res = yield
95-
94+
tracepoint_allow_reentry(&block)
95+
ensure
9696
Byebug.lock
97-
98-
res
9997
end
10098

10199
#
@@ -121,6 +119,16 @@ def safe_to_s(var)
121119
rescue StandardError
122120
"*Error in evaluation*"
123121
end
122+
123+
if TracePoint.respond_to?(:allow_reentry)
124+
def tracepoint_allow_reentry(&block)
125+
TracePoint.allow_reentry(&block)
126+
end
127+
else
128+
def tracepoint_allow_reentry
129+
yield
130+
end
131+
end
124132
end
125133
end
126134
end

test/commands/eval_test.rb

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
# frozen_string_literal: true
2+
3+
require "test_helper"
4+
5+
module Byebug
6+
#
7+
# Tests expression evaluation.
8+
#
9+
class EvalTest < TestCase
10+
def program
11+
strip_line_numbers <<-RUBY
12+
1: module Byebug
13+
2: Foo = "Foo constant"
14+
3: foo = :foo_variable
15+
4: byebug
16+
5: end
17+
RUBY
18+
end
19+
20+
def test_eval_prints_values
21+
enter "Foo", "foo"
22+
debug_code(program)
23+
check_output_includes('"Foo constant"')
24+
check_output_includes(":foo_variable")
25+
end
26+
end
27+
28+
#
29+
# Tests expression evalution of the code that uses TracePoint.
30+
#
31+
class EvalTracePointClassTest < TestCase
32+
def program
33+
strip_line_numbers <<-RUBY
34+
1: result = :tp_class_not_called
35+
2: autoload :Foo, "./foo"
36+
3: TracePoint.new(:class) { |tp| result = :tp_class_called }.enable
37+
4: byebug
38+
5: result
39+
RUBY
40+
end
41+
42+
def foo_program
43+
strip_line_numbers <<-RUBY
44+
1: module Foo
45+
2: def self.bar
46+
3: "Foo.bar called"
47+
4: end
48+
5: end
49+
RUBY
50+
end
51+
52+
def test_eval_triggers_class_tracepoint
53+
skip unless TracePoint.respond_to?(:allow_reentry) # TracePoint.allow_reentry only supported in >= 3.1
54+
55+
with_new_file("foo.rb", foo_program) do
56+
enter "Foo.bar", "result"
57+
debug_code(program)
58+
check_output_includes('"Foo.bar called"')
59+
check_output_includes(":tp_class_called")
60+
end
61+
end
62+
end
63+
end

0 commit comments

Comments
 (0)