blob: 0b017c6ce215d20c6aa9c53e1a942489df638420 [file] [log] [blame]
/**********************************************************************
* Copyright (c) 2007, 2010 QNX Software Systems and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* QNX Software Systems - Initial API and implementation
**********************************************************************/
package org.eclipse.cdt.debug.mi.core;
import java.io.IOException;
import org.eclipse.cdt.utils.spawner.Spawner;
import org.eclipse.core.runtime.IProgressMonitor;
/**
* @author Doug Schaefer
*/
public class CygwinMIProcessAdapter extends MIProcessAdapter {
/**
* @param args
* @param launchTimeout
* @param monitor
* @throws IOException
*/
public CygwinMIProcessAdapter(String[] args, int launchTimeout,
IProgressMonitor monitor) throws IOException {
super(args, launchTimeout, monitor);
}
@Override
public void interrupt(MIInferior inferior) {
if (fGDBProcess instanceof Spawner) {
if (inferior.isRunning()) {
boolean interruptedInferior = false;
Spawner gdbSpawner = (Spawner) fGDBProcess;
// Cygwin gdb 6.8 is capricious when it comes to interrupting
// the target. MinGW and later versions of Cygwin aren't. A
// simple CTRL-C to gdb seems to do the trick in every case.
// Once we drop support for gdb 6.8, we should be able to ditch
// this method and rely on the base implementation
// See https://bugs.eclipse.org/bugs/show_bug.cgi?id=304096#c56
if (inferior.isRemoteInferior()) {
// Interrupt gdb with a 'kill -SIGINT'. The reason we
// need to send a simulated Cygwin/POSIX SIGINT to
// Cygwin gdb is that it has special handling in the case
// of remote debugging, as explained in the bugzilla
// comment above. That special handling will forward the
// interrupt request through gdbserver to the remote
// inferior, but the interrupt to gdb *must* be a
// simulated Cygwin/POSIX SIGINT; a CTRL-C won't do.
gdbSpawner.interrupt();
}
else if (inferior.isAttachedInferior()) {
// Cygwin gdb 6.8 has no support for forwarding an
// interrupt request to the local process it has
// attached to. That support has since been added and
// will be available in 7.x. So, the only way to suspend the
// attached-to inferior is to interrupt it directly.
// The following call will take a special path in the
// JNI code. See
// Java_org_eclipse_cdt_utils_spawner_Spawner_raise()
// We don't use the Cygwin 'kill' command since (a) we don't
// know if the process associated with PID (the inferior) is
// a cygwin one (kill only works on cygwin programs), and
// (b) a CTRL-C will work just fine whether it's a cygwin
// program or not
interruptInferior(inferior);
interruptedInferior = true;
}
else {
// The typical case--gdb launches the inferior.
// Interrupt gdb but with a CTRL-C. gdb (6.8) itself
// doesn't have a handler for CTRL-C, but all processes
// in the console
// process group will receive the CTRL-C, and gdb
// registers itself to catch any such events that
// happen in the inferior. Thus it is able to determine
// and report that the inferior has been interrupted.
// But it's important we don't interrupt Cygwin gdb with
// a 'kill' since that will only reach gdb, and gdb
// won't forward the request on to the inferior. See
// bugzilla comment referenced above for details.
gdbSpawner.interruptCTRLC();
}
waitForInterrupt(inferior);
// If we are still running try to interrupt the inferior (unless we
// already tried that above)
if (inferior.isRunning() && inferior.getInferiorPID() > 0 && !interruptedInferior) {
// lets try something else.
interruptInferior(inferior);
}
}
}
}
}