{"record":{"id":"6d29ce16e44517d5","repo":"NationalSecurityAgency/ghidra","slug":"timed-out-waiting-for-thread-to-stop-6d29ce","errorCode":null,"errorMessage":"Timed out waiting for thread to stop","messagePattern":"Timed out waiting for thread to stop","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"Ghidra/Debug/Debugger-jpda/src/main/java/ghidra/dbg/jdi/rmi/jpda/JdiCommands.java","lineNumber":2177,"sourceCode":"\t}\n\n\tpublic void ghidraTraceSyncSynthStopped() {\n\t\tconnector.getHooks().onStop(null, state.trace);\n\t}\n\n\tpublic void ghidraTraceWaitStopped(int timeout) {\n\t\tThreadReference currentThread = connector.getJdi().getCurrentThread();\n\t\tif (currentThread == null) {\n\t\t\treturn;\n\t\t}\n\t\tlong start = System.currentTimeMillis();\n\t\twhile (!currentThread.isSuspended()) {\n\t\t\tcurrentThread = connector.getJdi().getCurrentThread();\n\t\t\ttry {\n\t\t\t\tThread.sleep(100);\n\t\t\t\tlong elapsed = System.currentTimeMillis() - start;\n\t\t\t\tif (elapsed > timeout) {\n\t\t\t\t\tthrow new RuntimeException(\"Timed out waiting for thread to stop\");\n\t\t\t\t}\n\t\t\t}\n\t\t\tcatch (InterruptedException e) {\n\t\t\t\tMsg.error(this, \"Wait interrupted\");\n\t\t\t}\n\t\t}\n\t}\n\n\tpublic void execute(ClassType ct, ThreadReference thread, Method method, List<Value> args,\n\t\t\tint options) {\n\t\ttry {\n\t\t\tValue val = ct.invokeMethod(thread, method, args, options);\n\t\t\tSystem.err.println(val);\n\t\t}\n\t\tcatch (Exception e) {\n\t\t\tthrow new RuntimeException(e.getMessage());\n\t\t}\n\t}","sourceCodeStart":2159,"sourceCodeEnd":2195,"githubUrl":"https://github.com/NationalSecurityAgency/ghidra/blob/d5f144c24d6bc53c9cbf4448c6d11143e7696206/Ghidra/Debug/Debugger-jpda/src/main/java/ghidra/dbg/jdi/rmi/jpda/JdiCommands.java#L2159-L2195","documentation":"Thrown by ghidraTraceWaitStopped(int timeout) when the target thread does not report isSuspended()==true within the given timeout milliseconds. The method polls every 100ms, and if elapsed time exceeds the timeout it aborts — the trace cannot proceed because operations require a stopped target.","triggerScenarios":"Calling ghidraTraceWaitStopped after requesting a suspend (or expecting a breakpoint hit) but the thread keeps running. Causes: the suspend request is still in flight, the target is executing a long native call, the breakpoint was never hit, or the JDI event stream is delayed.","commonSituations":"Timeout value too small for a slow or heavily loaded target; the breakpoint condition was never satisfied; the target is stuck in a native/JIT-compiled region that doesn't honor suspend promptly; event delivery latency over a remote JDI connection.","solutions":["Increase the timeout value passed to ghidraTraceWaitStopped to accommodate a slow target.","Confirm the suspend request or breakpoint actually reached the target VM (check JDI event requests).","If the thread is genuinely stuck, interrupt or forcibly suspend it via the connector before waiting.","Re-issue the wait after a short delay in case of transient event-delivery latency."],"exampleFix":"// before\nghidraTraceWaitStopped(1000); // too short, throws\n\n// after\nghidraTraceWaitStopped(10000); // allow more time for the suspend to land","handlingStrategy":"retry","validationCode":"// Verify suspend before waiting\nThreadReference t = connector.getJdi().getCurrentThread();\nif (t != null && t.isSuspended()) { /* already stopped, no wait needed */ }\nelse { /* choose a generous timeout */ }","typeGuard":null,"tryCatchPattern":"try { ghidraTraceWaitStopped(timeoutMs); }\ncatch (RuntimeException e) {\n    if (e.getMessage().contains(\"Timed out\")) { /* optionally re-issue once with a larger timeout */ }\n    else throw e;\n}","preventionTips":["Size the timeout to the slowest expected target operation, not the average.","Confirm the suspend/breakpoint request reached the target VM before waiting.","Watch the target's terminal for signs it is still executing."],"tags":["timeout","thread-state","jdi","ghidra-debug"],"backgroundTag":null,"analyzedSha":"d5f144c24d6bc53c9cbf4448c6d11143e7696206","analyzedAt":"2026-08-14T01:00:57.564Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}