Skip to content

Commit 4584bd5

Browse files
committed
[GR-60633] Fix JDWP reconnect logic not resetting all state properly.
PullRequest: graal/19704
2 parents 2c7b520 + 0251f1f commit 4584bd5

File tree

12 files changed

+81
-12
lines changed

12 files changed

+81
-12
lines changed

espresso/src/com.oracle.truffle.espresso.jdwp/src/com/oracle/truffle/espresso/jdwp/api/FieldRef.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,4 +114,6 @@ public interface FieldRef {
114114
* @return true if this field has any breakpoints, false otherwise
115115
*/
116116
boolean hasActiveBreakpoint();
117+
118+
void disposeFieldBreakpoint();
117119
}

espresso/src/com.oracle.truffle.espresso.jdwp/src/com/oracle/truffle/espresso/jdwp/api/JDWPContext.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
import com.oracle.truffle.api.frame.Frame;
3030
import com.oracle.truffle.api.nodes.Node;
3131
import com.oracle.truffle.api.nodes.RootNode;
32+
import com.oracle.truffle.espresso.jdwp.impl.DebuggerController;
3233

3334
/**
3435
* Interface that defines required methods for a guest language when implementing JDWP.
@@ -500,4 +501,6 @@ public interface JDWPContext {
500501
Object allocateInstance(KlassRef klass);
501502

502503
void steppingInProgress(Thread t, boolean value);
504+
505+
void replaceController(DebuggerController newController);
503506
}

espresso/src/com.oracle.truffle.espresso.jdwp/src/com/oracle/truffle/espresso/jdwp/api/MethodRef.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -232,6 +232,8 @@ public interface MethodRef {
232232
*/
233233
boolean hasActiveHook();
234234

235+
void disposeHooks();
236+
235237
/**
236238
* Determine if this method is obsolete. A method is obsolete if it has been replaced by a
237239
* non-equivalent method using the RedefineClasses command. The original and redefined methods

espresso/src/com.oracle.truffle.espresso.jdwp/src/com/oracle/truffle/espresso/jdwp/api/VMEventListenerImpl.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,10 @@ public void activate(Object mainThread, DebuggerController control, JDWPContext
9090
this.ids = context.getIds();
9191
}
9292

93+
public void replaceController(DebuggerController newController) {
94+
this.debuggerController = newController;
95+
}
96+
9397
@Override
9498
public void onDetach() {
9599
// free up request, to avoid attempting to send anything further

espresso/src/com.oracle.truffle.espresso.jdwp/src/com/oracle/truffle/espresso/jdwp/impl/BreakpointInfo.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,4 +58,8 @@ public interface BreakpointInfo {
5858
void addSuspendPolicy(byte suspendPolicy);
5959

6060
byte getSuspendPolicy();
61+
62+
default void dispose() {
63+
// do nothing by default
64+
}
6165
}

espresso/src/com.oracle.truffle.espresso.jdwp/src/com/oracle/truffle/espresso/jdwp/impl/DebuggerController.java

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,7 @@ public void reInitialize() {
157157
DebuggerController newController = new DebuggerController(jdwpLogger);
158158
newController.truffleContext = truffleContext;
159159
newController.initialize(debugger, options, context, initialThread, eventListener);
160+
context.replaceController(newController);
160161
assert newController.setupState != null;
161162

162163
if (newController.setupState.fatalConnectionError) {
@@ -186,6 +187,10 @@ public void reset(boolean prepareForReconnect) {
186187
// existence state.
187188
resetting.lockInterruptibly();
188189

190+
// end the current debugger session to avoid hitting any further breakpoints
191+
// when resuming all threads
192+
endSession();
193+
189194
currentReceiverThread = receiverThread;
190195

191196
// Close the server socket used to listen for transport dt_socket.
@@ -207,16 +212,14 @@ public void reset(boolean prepareForReconnect) {
207212
// re-enable GC for all objects
208213
getGCPrevention().clearAll();
209214

210-
// end the current debugger session to avoid hitting any further breakpoints
211-
// when resuming all threads
212-
endSession();
213-
214-
// resume all threads
215-
forceResumeAll();
215+
eventFilters.clearAll();
216216

217217
// Now, close the socket, which will force the receiver thread to complete eventually.
218218
// Note that we might run this code in the receiver thread, so we can't simply join.
219219
closeSocket();
220+
221+
// resume all threads
222+
forceResumeAll();
220223
} catch (InterruptedException e) {
221224
Thread.currentThread().interrupt();
222225
} finally {
@@ -822,8 +825,8 @@ private void lockThread(Object thread, boolean forceSuspend, List<Callable<Void>
822825
while (!Thread.currentThread().isInterrupted()) {
823826
try {
824827
synchronized (lock) {
825-
if (!lock.isLocked()) {
826-
// released from other thread, so break loop
828+
if (!lock.isLocked() || !connection.isOpen()) {
829+
// released from other thread or session ended, so break loop
827830
break;
828831
}
829832
// no reason to hold a hard suspension status, since now

espresso/src/com.oracle.truffle.espresso.jdwp/src/com/oracle/truffle/espresso/jdwp/impl/EventFilters.java

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,4 +62,20 @@ public RequestFilter getRequestFilter(int requestId) {
6262
readLock.unlock();
6363
}
6464
}
65+
66+
public void clearAll() {
67+
try {
68+
lock.writeLock().lock();
69+
// traverse all filters and clear all registered breakpoint information
70+
for (RequestFilter requestFilter : requestFilters) {
71+
BreakpointInfo breakpointInfo = requestFilter.getBreakpointInfo();
72+
if (breakpointInfo != null) {
73+
breakpointInfo.dispose();
74+
}
75+
}
76+
requestFilters = new RequestFilter[0];
77+
} finally {
78+
lock.writeLock().unlock();
79+
}
80+
}
6581
}

espresso/src/com.oracle.truffle.espresso.jdwp/src/com/oracle/truffle/espresso/jdwp/impl/FieldBreakpointInfo.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,4 +63,9 @@ public boolean isModificationBreakpoint() {
6363
public boolean isAccessBreakpoint() {
6464
return accessBreakpoint;
6565
}
66+
67+
@Override
68+
public void dispose() {
69+
field.disposeFieldBreakpoint();
70+
}
6671
}

espresso/src/com.oracle.truffle.espresso.jdwp/src/com/oracle/truffle/espresso/jdwp/impl/MethodBreakpointInfo.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,4 +63,11 @@ public boolean onMethodEnter(@SuppressWarnings("unused") MethodRef method, @Supp
6363
public boolean onMethodExit(@SuppressWarnings("unused") MethodRef method, @SuppressWarnings("unused") Object returnValue) {
6464
return isMethodExit;
6565
}
66+
67+
@Override
68+
public void dispose() {
69+
for (MethodRef method : methods) {
70+
method.disposeHooks();
71+
}
72+
}
6673
}

espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/impl/Field.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -945,11 +945,16 @@ public final void removeFieldBreakpointInfo(int requestId) {
945945
// remove index 1, but keep info at index 0
946946
temp[0] = infos[0];
947947
infos = temp;
948-
return;
949948
}
950949
}
951950
}
952951

952+
@Override
953+
public void disposeFieldBreakpoint() {
954+
hasActiveBreakpoints.set(false);
955+
infos = null;
956+
}
957+
953958
public void setCompatibleField(@SuppressWarnings("unused") Field field) {
954959
// only applicable to RedefineAddedFields
955960
}

espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/impl/Method.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1120,6 +1120,11 @@ public synchronized void removeActiveHook(MethodHook hook) {
11201120
}
11211121
}
11221122

1123+
public synchronized void disposeHooks() {
1124+
hasActiveHook.set(false);
1125+
hooks = MethodHook.EMPTY;
1126+
}
1127+
11231128
public SharedRedefinitionContent redefine(ObjectKlass.KlassVersion klassVersion, ParserMethod newMethod, ParserKlass newKlass, Ids<Object> ids) {
11241129
// install the new method version immediately
11251130
LinkedMethod newLinkedMethod = new LinkedMethod(newMethod);
@@ -1890,6 +1895,11 @@ public void removedMethodHook(MethodHook hook) {
18901895
getMethod().removeActiveHook(hook);
18911896
}
18921897

1898+
@Override
1899+
public void disposeHooks() {
1900+
getMethod().disposeHooks();
1901+
}
1902+
18931903
@Override
18941904
public boolean hasActiveHook() {
18951905
return getMethod().hasActiveHook();

espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/runtime/JDWPContextImpl.java

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -98,18 +98,20 @@ public final class JDWPContextImpl implements JDWPContext {
9898
private RedefinitionPluginHandler redefinitionPluginHandler;
9999
private final ArrayList<ReloadingAction> classInitializerActions = new ArrayList<>(1);
100100
private DebuggerController controller;
101+
private VMEventListenerImpl vmEventListener;
101102

102103
public JDWPContextImpl(EspressoContext context) {
103104
this.context = context;
104105
this.ids = new Ids<>(StaticObject.NULL);
105106
this.innerClassRedefiner = new InnerClassRedefiner(context);
106107
}
107108

108-
public void jdwpInit(TruffleLanguage.Env env, Object mainThread, VMEventListenerImpl vmEventListener) {
109+
public void jdwpInit(TruffleLanguage.Env env, Object mainThread, VMEventListenerImpl eventListener) {
109110
Debugger debugger = env.lookup(env.getInstruments().get("debugger"), Debugger.class);
110111
this.controller = env.lookup(env.getInstruments().get(JDWPInstrument.ID), DebuggerController.class);
111-
vmEventListener.activate(mainThread, controller, this);
112-
controller.initialize(debugger, context.getEspressoEnv().JDWPOptions, this, mainThread, vmEventListener);
112+
vmEventListener = eventListener;
113+
eventListener.activate(mainThread, controller, this);
114+
controller.initialize(debugger, context.getEspressoEnv().JDWPOptions, this, mainThread, eventListener);
113115
redefinitionPluginHandler = RedefinitionPluginHandler.create(context);
114116
classRedefinition = context.createClassRedefinition(ids, redefinitionPluginHandler);
115117
}
@@ -120,6 +122,12 @@ public void finalizeContext() {
120122
}
121123
}
122124

125+
@Override
126+
public void replaceController(DebuggerController newController) {
127+
this.controller = newController;
128+
vmEventListener.replaceController(newController);
129+
}
130+
123131
@Override
124132
public Ids<Object> getIds() {
125133
return ids;

0 commit comments

Comments
 (0)