Skip to content

Commit 68c52f9

Browse files
authored
Merge pull request jruby#9283 from headius/tracepoint_starts_global
Only localize TracePoint to thread if specified
2 parents fde405b + 5c2be17 commit 68c52f9

1 file changed

Lines changed: 102 additions & 51 deletions

File tree

core/src/main/java/org/jruby/ext/tracepoint/TracePoint.java

Lines changed: 102 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import org.jruby.RubyClass;
88
import org.jruby.RubyObject;
99
import org.jruby.RubySymbol;
10+
import org.jruby.RubyThread;
1011
import org.jruby.anno.JRubyMethod;
1112
import org.jruby.exceptions.RaiseException;
1213
import org.jruby.runtime.Block;
@@ -77,60 +78,70 @@ public IRubyObject initialize(ThreadContext context, IRubyObject[] _events, fina
7778

7879
if (!block.isGiven()) throw argumentError(context, "must be called with a block");
7980

80-
final ThreadContext threadToTrace = context;
81-
hook = new EventHook() {
82-
@Override
83-
public void event(ThreadContext context, RubyEvent event, String file, int line, String name, IRubyObject type) {
84-
if (!enabled || threadToTrace != context || context.isWithinTrace()) return;
81+
hook = new TracePointEventHook(eventSet, block);
82+
83+
return context.nil;
84+
}
8585

86-
int savedCallInfo = resetCallInfo(context);
86+
private class TracePointEventHook extends EventHook {
87+
protected ThreadContext threadToTrace;
88+
private final Block block;
89+
private final EnumSet<RubyEvent> eventSet;
8790

88-
synchronized (this) {
89-
inside = true;
91+
public TracePointEventHook(EnumSet<RubyEvent> eventSet, Block block) {
92+
this.block = block;
93+
this.eventSet = eventSet;
94+
}
9095

91-
if (file == null) file = "(ruby)";
92-
if (type == null) type = context.fals;
96+
@Override
97+
public void event(ThreadContext context, RubyEvent event, String file, int line, String name, IRubyObject type) {
98+
if (!enabled || (threadToTrace != null && threadToTrace != context) || context.isWithinTrace()) return;
9399

94-
IRubyObject binding;
95-
if (event == RubyEvent.THREAD_BEGIN || event == RubyEvent.THREAD_END) {
96-
binding = context.nil;
97-
} else {
98-
binding = RubyBinding.newBinding(context.runtime, context.currentBinding());
99-
}
100+
int savedCallInfo = resetCallInfo(context);
100101

101-
context.preTrace();
102+
synchronized (this) {
103+
inside = true;
102104

103-
// FIXME: get return value
104-
update(event.getName(), file, line, name, type, context.getErrorInfo(), context.nil, binding);
105+
if (file == null) file = "(ruby)";
106+
if (type == null) type = context.fals;
105107

106-
try {
107-
block.yieldSpecific(context, TracePoint.this);
108-
} finally {
109-
update(null, null, line, null, context.nil, context.nil, context.nil, context.nil);
110-
context.postTrace();
111-
inside = false;
112-
context.callInfo = savedCallInfo;
113-
}
108+
IRubyObject binding;
109+
if (event == RubyEvent.THREAD_BEGIN || event == RubyEvent.THREAD_END) {
110+
binding = context.nil;
111+
} else {
112+
binding = RubyBinding.newBinding(context.runtime, context.currentBinding());
114113
}
115-
}
116114

117-
@Override
118-
public void eventHandler(ThreadContext context, String eventName, String file, int line, String name, IRubyObject type) {
119-
event(context, RubyEvent.fromName(eventName), file, line, name, type);
120-
}
115+
context.preTrace();
121116

122-
@Override
123-
public boolean isInterestedInEvent(RubyEvent event) {
124-
return eventSet.contains(event);
125-
}
117+
// FIXME: get return value
118+
update(event.getName(), file, line, name, type, context.getErrorInfo(), context.nil, binding);
126119

127-
@Override
128-
public EnumSet<RubyEvent> eventSet() {
129-
return eventSet;
120+
try {
121+
block.yieldSpecific(context, TracePoint.this);
122+
} finally {
123+
update(null, null, line, null, context.nil, context.nil, context.nil, context.nil);
124+
context.postTrace();
125+
inside = false;
126+
context.callInfo = savedCallInfo;
127+
}
130128
}
131-
};
132-
133-
return context.nil;
129+
}
130+
131+
@Override
132+
public void eventHandler(ThreadContext context, String eventName, String file, int line, String name, IRubyObject type) {
133+
event(context, RubyEvent.fromName(eventName), file, line, name, type);
134+
}
135+
136+
@Override
137+
public boolean isInterestedInEvent(RubyEvent event) {
138+
return eventSet.contains(event);
139+
}
140+
141+
@Override
142+
public EnumSet<RubyEvent> eventSet() {
143+
return eventSet;
144+
}
134145
}
135146

136147
@JRubyMethod
@@ -149,12 +160,48 @@ public IRubyObject defined_class(ThreadContext context) {
149160

150161
@JRubyMethod
151162
public IRubyObject disable(ThreadContext context, Block block) {
152-
return doToggle(context, block, false);
163+
return doToggle(context, null, block, false);
153164
}
154-
165+
155166
@JRubyMethod
156167
public IRubyObject enable(ThreadContext context, Block block) {
157-
return doToggle(context, block, true);
168+
return doToggle(context, null, block, true);
169+
}
170+
171+
@JRubyMethod
172+
public IRubyObject enable(ThreadContext context, IRubyObject target, Block block) {
173+
// TODO: implement target
174+
if (!target.isNil()) {
175+
context.runtime.getWarnings().warning("target argument to TracePoint.enable is unsupported");
176+
}
177+
178+
return doToggle(context, null, block, true);
179+
}
180+
181+
@JRubyMethod
182+
public IRubyObject enable(ThreadContext context, IRubyObject target, IRubyObject targetLine, Block block) {
183+
// TODO: implement target, target_line
184+
if (!target.isNil() || !targetLine.isNil()) {
185+
context.runtime.getWarnings().warning("target and target_line arguments to TracePoint.enable are unsupported");
186+
}
187+
188+
return doToggle(context, null, block, true);
189+
}
190+
191+
@JRubyMethod
192+
public IRubyObject enable(ThreadContext context, IRubyObject target, IRubyObject targetLine, IRubyObject _targetThread, Block block) {
193+
// TODO: implement target, target_line
194+
if (!target.isNil() || !targetLine.isNil()) {
195+
context.runtime.getWarnings().warning("target and target_line arguments to TracePoint.enable are unsupported");
196+
}
197+
198+
RubyThread targetThread = null;
199+
if (_targetThread != asSymbol(context, "default")) {
200+
if (!(_targetThread instanceof RubyThread th)) throw argumentError(context, "target must be a Thread");
201+
targetThread = th;
202+
}
203+
204+
return doToggle(context, targetThread, block, true);
158205
}
159206

160207
@JRubyMethod(name = "enabled?")
@@ -244,32 +291,36 @@ private void update(String eventName, String file, int line, String name, IRubyO
244291
this.binding = binding;
245292
}
246293

247-
private synchronized IRubyObject doToggle(ThreadContext context, Block block, boolean toggle) {
294+
private synchronized IRubyObject doToggle(ThreadContext context, RubyThread _targetThread, Block block, boolean toggle) {
248295
if (block.isGiven()) {
249296
boolean old = enabled;
250297
try {
251-
updateEnabled(context, toggle);
298+
updateEnabled(context, _targetThread, toggle);
252299

253300
return block.yieldSpecific(context);
254301
} finally {
255-
updateEnabled(context, old);
302+
updateEnabled(context, _targetThread, old);
256303
}
257304
}
258305

259306
IRubyObject old = asBoolean(context, enabled);
260-
updateEnabled(context, toggle);
307+
updateEnabled(context, _targetThread, toggle);
261308

262309
return old;
263310
}
264311

265-
public void updateEnabled(ThreadContext context, boolean toggle) {
312+
public void updateEnabled(ThreadContext context, RubyThread targetThread, boolean toggle) {
266313
if (toggle == enabled) return; // don't re-add or re-remove hook
267314

268315
enabled = toggle;
269316

270317
if (toggle) {
318+
if (targetThread != null && !targetThread.isNil()) {
319+
hook.threadToTrace = targetThread.getContext();
320+
}
271321
context.traceEvents.addEventHook(context, hook);
272322
} else {
323+
hook.threadToTrace = null;
273324
context.traceEvents.removeEventHook(hook);
274325
}
275326
}
@@ -282,7 +333,7 @@ private static JavaSites.TracePointSites sites(ThreadContext context) {
282333
return context.sites.TracePoint;
283334
}
284335

285-
private EventHook hook;
336+
private TracePointEventHook hook;
286337
private volatile boolean enabled = false;
287338
private String eventName;
288339
private String file;

0 commit comments

Comments
 (0)