package com.aptana.ruby.debug.core.launching;
import java.lang.reflect.Field;
import java.util.Map;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.Status;
import org.eclipse.debug.core.DebugException;
import org.eclipse.debug.core.ILaunch;
import org.eclipse.debug.core.IProcessFactory;
import org.eclipse.debug.core.model.IProcess;
import org.eclipse.debug.core.model.RuntimeProcess;
import com.aptana.core.util.PlatformUtil;
import com.aptana.ruby.debug.core.RubyDebugCorePlugin;
/**
* When terminating processes generated by this factory, on Mac/Unix we send a SIGINT to the process before doing our
* normal termination.
*
* @author cwilliams
*/
public class InterruptingProcessFactory implements IProcessFactory
{
public static final String ID = "com.aptana.ruby.debug.core.interruptingProcessFactory"; //$NON-NLS-1$
@SuppressWarnings("rawtypes")
public IProcess newProcess(ILaunch launch, Process process, String label, Map attributes)
{
return new RuntimeProcess(launch, process, label, attributes)
{
@Override
public void terminate() throws DebugException
{
if (!Platform.getOS().equals(Platform.OS_WIN32))
{
killProcess();
}
super.terminate();
}
private Integer grabPid()
{
// FIXME This only works on Unix/Mac Sun JDK and is a nasty hack to grab the underlying process' pid
try
{
Process realProcess = getSystemProcess();
Field f = realProcess.getClass().getDeclaredField("pid"); //$NON-NLS-1$
f.setAccessible(true);
return (Integer) f.get(realProcess);
}
catch (Exception e)
{
// ignore
}
return -1;
}
/**
* Attempts to send a SIGINT to the underlying process. This is equivalent to Ctrl+C.
*
* @return
*/
private IStatus killProcess()
{
int pid = grabPid();
if (pid <= 0)
{
return new Status(IStatus.ERROR, RubyDebugCorePlugin.getPluginIdentifier(),
Messages.InterruptingProcessFactory_UnableToGrabPIDMsg);
}
PlatformUtil.killProcess(pid, 2); // SIGINT = 2
return Status.OK_STATUS;
}
};
}
}