From 3b373bb5a578b714c74d9f20d754e06eb151da24 Mon Sep 17 00:00:00 2001 From: Marc Khouzam Date: Tue, 15 Mar 2011 20:17:36 +0000 Subject: [PATCH] Bug 340021: GDB process not killed when canceling a launch --- .../cdt/dsf/gdb/service/GDBBackend.java | 63 +++++++++++-------- 1 file changed, 37 insertions(+), 26 deletions(-) diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBBackend.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBBackend.java index d9e21806a10..c3e8e72c849 100644 --- a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBBackend.java +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBBackend.java @@ -88,6 +88,7 @@ public class GDBBackend extends AbstractDsfService implements IGDBBackend { private Properties fEnvVariables; private SessionType fSessionType; private Boolean fAttach; + private State fBackendState = State.NOT_INITIALIZED; /** * Unique ID of this service instance. @@ -446,13 +447,7 @@ public class GDBBackend extends AbstractDsfService implements IGDBBackend { } public State getState() { - if (fMonitorJob == null) { - return State.NOT_INITIALIZED; - } else if (fMonitorJob.fExited) { - return State.TERMINATED; - } else { - return State.STARTED; - } + return fBackendState; } public int getExitCode() { @@ -519,6 +514,9 @@ public class GDBBackend extends AbstractDsfService implements IGDBBackend { try { fProcess = launchGDBProcess(commandLine); + fBackendState = State.STARTED; + // Don't send the backendStarted event yet. We wait until we have registered this service + // so that other services can have access to it. } catch(CoreException e) { gdbLaunchRequestMonitor.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, -1, e.getMessage(), e)); gdbLaunchRequestMonitor.done(); @@ -572,7 +570,17 @@ public class GDBBackend extends AbstractDsfService implements IGDBBackend { @Override protected IStatus run(IProgressMonitor monitor) { - destroy(); + if (GDBBackend.this.getState() == State.STARTED) { + // If we get here, our monitoring thread has been cleaned up already, + // but GDB is running. We have to terminate GDB and send + // the proper event. + assert fMonitorJob.fMonitorExited == true; + destroy(); + fBackendState = State.TERMINATED; + getSession().dispatchEvent( + new BackendStateChangedEvent(getSession().getId(), getId(), State.TERMINATED), + getProperties()); + } int attempts = 0; while (attempts < 10) { @@ -616,8 +624,8 @@ public class GDBBackend extends AbstractDsfService implements IGDBBackend { @Override protected void shutdown(RequestMonitor requestMonitor) { - if (!fMonitorJob.fExited) { - fMonitorJob.kill(); + if (fMonitorJob != null) { + fMonitorJob.kill(); } requestMonitor.done(); } @@ -639,9 +647,12 @@ public class GDBBackend extends AbstractDsfService implements IGDBBackend { * the GDBControlInitializedDMEvent that's used to indicate that GDB * back end is ready for MI commands. But we still fire the event as * it does no harm and may be needed sometime.... 09/29/2008 + * + * We send the event in the register step because that is when + * other services have access to it. */ getSession().dispatchEvent( - new BackendStateChangedEvent(getSession().getId(), getId(), IMIBackend.State.STARTED), + new BackendStateChangedEvent(getSession().getId(), getId(), State.STARTED), getProperties()); requestMonitor.done(); @@ -660,7 +671,7 @@ public class GDBBackend extends AbstractDsfService implements IGDBBackend { * then notifies the associated runtime process. */ private class MonitorJob extends Job { - boolean fExited = false; + boolean fMonitorExited = false; DsfRunnable fMonitorStarted; Process fMonProcess; @@ -668,20 +679,20 @@ public class GDBBackend extends AbstractDsfService implements IGDBBackend { protected IStatus run(IProgressMonitor monitor) { synchronized(fMonProcess) { getExecutor().submit(fMonitorStarted); - while (!fExited) { - try { - fMonProcess.waitFor(); - fGDBExitValue = fMonProcess.exitValue(); - } catch (InterruptedException ie) { - // clear interrupted state - Thread.interrupted(); - } finally { - fExited = true; - getSession().dispatchEvent( - new BackendStateChangedEvent(getSession().getId(), getId(), IMIBackend.State.TERMINATED), - getProperties()); - } + try { + fMonProcess.waitFor(); + fGDBExitValue = fMonProcess.exitValue(); + + fBackendState = State.TERMINATED; + getSession().dispatchEvent( + new BackendStateChangedEvent(getSession().getId(), getId(), State.TERMINATED), + getProperties()); + } catch (InterruptedException ie) { + // clear interrupted state + Thread.interrupted(); } + + fMonitorExited = true; } return Status.OK_STATUS; } @@ -695,7 +706,7 @@ public class GDBBackend extends AbstractDsfService implements IGDBBackend { void kill() { synchronized(fMonProcess) { - if (!fExited) { + if (!fMonitorExited) { getThread().interrupt(); } }