On Thu, 21 Oct 2021 19:37:41 GMT, Richard Reingruber <rr...@openjdk.org> wrote:
>> This change fixes deadlocks described in the JBS-bug by: >> >> * Releasing `handlerLock` before waiting on `threadLock` in >> `blockOnDebuggerSuspend()` >> >> * Notifying on `threadLock` in `threadControl_reset()` >> >> Also the actions in handleAppResumeBreakpoint() are moved/deferred until >> doPendingTasks() runs. This is necessary because an event handler must not >> release handlerLock first and foremost because handlers are called while >> iterating the handler chain for an event type which is protected by >> handlerLock >> (see https://github.com/openjdk/jdk/pull/5805) >> >> The first commit delays the cleanup actions after leaving the loop in >> `debugLoop_run()`. It allows to reproduce the deadlock running the dispose003 >> test with the command >> >> >> make run-test >> TEST=test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/dispose/dispose003 >> >> >> The second commit adds a new test that reproduces the deadlock when calling >> threadControl_resumeThread() while a thread is waiting in >> blockOnDebuggerSuspend(). >> >> The third commit contains the fix described above. With it the deadlocks >> cannot be reproduced anymore. >> >> The forth commit removes the diagnostic code introduced with the first >> commit again. >> >> The fix passed >> >> test/hotspot/jtreg/serviceability/jdwp >> test/jdk/com/sun/jdi >> test/hotspot/jtreg/vmTestbase/nsk/jdwp >> test/hotspot/jtreg/vmTestbase/nsk/jdi > > Richard Reingruber has updated the pull request incrementally with one > additional commit since the last revision: > > Hoist locking from trackAppResume() up to it its caller doPendingTasks() src/jdk.jdwp.agent/share/native/libjdwp/threadControl.c line 2212: > 2210: * handlerLock is not needed anymore. We release it before > calling > 2211: * blockOnDebuggerSuspend() because it is required for resumes > by the > 2212: * debugger so we cannot wait for that holding handlerLock. * handlerLock is not needed anymore. We must release it before calling * blockOnDebuggerSuspend() because it is required for resumes done by * the debugger. If resumee is currently suspended by the debugger, then * blockOnDebuggerSuspend() will block until a debugger resume is done. * If it blocks while holding the handlerLock, then the resume will deadlock. ------------- PR: https://git.openjdk.java.net/jdk/pull/5849