1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00

remain enabled and line specified trace points

If two or more tracepoints enabled with the same target and with
different target lines, the only last line is activated.
This patch fixes this issue by remaining existing trace instructions.
[Bug #17302]
This commit is contained in:
Koichi Sasada 2020-11-16 16:40:04 +09:00
parent 1271782f9d
commit 084e7e31b2
Notes: git 2020-11-17 07:34:08 +09:00
2 changed files with 33 additions and 5 deletions

13
iseq.c
View file

@ -3168,13 +3168,16 @@ rb_vm_insn_addr2insn(const void *addr)
}
static inline int
encoded_iseq_trace_instrument(VALUE *iseq_encoded_insn, rb_event_flag_t turnon)
encoded_iseq_trace_instrument(VALUE *iseq_encoded_insn, rb_event_flag_t turnon, bool remain_current_trace)
{
st_data_t key = (st_data_t)*iseq_encoded_insn;
st_data_t val;
if (st_lookup(encoded_insn_data, key, &val)) {
insn_data_t *e = (insn_data_t *)val;
if (remain_current_trace && key == (st_data_t)e->trace_encoded_insn) {
turnon = 1;
}
*iseq_encoded_insn = (VALUE) (turnon ? e->trace_encoded_insn : e->notrace_encoded_insn);
return e->insn_len;
}
@ -3187,7 +3190,7 @@ rb_iseq_trace_flag_cleared(const rb_iseq_t *iseq, size_t pos)
{
const struct rb_iseq_constant_body *const body = iseq->body;
VALUE *iseq_encoded = (VALUE *)body->iseq_encoded;
encoded_iseq_trace_instrument(&iseq_encoded[pos], 0);
encoded_iseq_trace_instrument(&iseq_encoded[pos], 0, false);
}
static int
@ -3216,7 +3219,7 @@ iseq_add_local_tracepoint(const rb_iseq_t *iseq, rb_event_flag_t turnon_events,
if (pc_events & target_events) {
n++;
}
pc += encoded_iseq_trace_instrument(&iseq_encoded[pc], pc_events & (target_events | iseq->aux.exec.global_trace_events));
pc += encoded_iseq_trace_instrument(&iseq_encoded[pc], pc_events & (target_events | iseq->aux.exec.global_trace_events), true);
}
if (n > 0) {
@ -3281,7 +3284,7 @@ iseq_remove_local_tracepoint(const rb_iseq_t *iseq, VALUE tpval)
for (pc = 0; pc<body->iseq_size;) {
rb_event_flag_t pc_events = rb_iseq_event_flags(iseq, pc);
pc += encoded_iseq_trace_instrument(&iseq_encoded[pc], pc_events & (local_events | iseq->aux.exec.global_trace_events));
pc += encoded_iseq_trace_instrument(&iseq_encoded[pc], pc_events & (local_events | iseq->aux.exec.global_trace_events), false);
}
}
return n;
@ -3333,7 +3336,7 @@ rb_iseq_trace_set(const rb_iseq_t *iseq, rb_event_flag_t turnon_events)
for (pc=0; pc<body->iseq_size;) {
rb_event_flag_t pc_events = rb_iseq_event_flags(iseq, pc);
pc += encoded_iseq_trace_instrument(&iseq_encoded[pc], pc_events & enabled_events);
pc += encoded_iseq_trace_instrument(&iseq_encoded[pc], pc_events & enabled_events, true);
}
}
}

View file

@ -2175,6 +2175,31 @@ class TestSetTraceFunc < Test::Unit::TestCase
assert_equal 'target_line is specified, but line event is not specified', e.message
end
def test_tracepoint_enable_with_target_line_two_times
events = []
line_0 = __LINE__
code1 = proc{
events << 1 # tp1
events << 2
events << 3 # tp2
}
tp1 = TracePoint.new(:line) do |tp|
events << :tp1
end
tp2 = TracePoint.new(:line) do |tp|
events << :tp2
end
tp1.enable(target: code1, target_line: line_0 + 2) do
tp2.enable(target: code1, target_line: line_0 + 4) do
# two hooks
code1.call
end
end
assert_equal [:tp1, 1, 2, :tp2, 3], events
end
def test_script_compiled
events = []
tp = TracePoint.new(:script_compiled){|tp|