blob: b915939020c15aead7272a0144c1992948875204 [file] [log] [blame]
/*=============================================================================#
# Copyright (c) 2007, 2021 Stephan Wahlbrink and others.
#
# This program and the accompanying materials are made available under the
# terms of the Eclipse Public License 2.0 which is available at
# https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
# which is available at https://www.apache.org/licenses/LICENSE-2.0.
#
# SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
#
# Contributors:
# Stephan Wahlbrink <sw@wahlbrink.eu> - initial API and implementation
#=============================================================================*/
package org.eclipse.statet.r.nico.impl;
import static org.eclipse.statet.jcommons.lang.ObjectUtils.nonNullAssert;
import java.io.File;
import java.io.IOException;
import java.lang.ProcessBuilder.Redirect;
import java.net.URL;
import org.eclipse.core.runtime.FileLocator;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.Status;
import org.eclipse.statet.jcommons.lang.NonNullByDefault;
import org.eclipse.statet.jcommons.lang.ObjectUtils.ToStringBuilder;
import org.eclipse.statet.jcommons.runtime.ProcessUtils;
import org.eclipse.statet.jcommons.status.ProgressMonitor;
import org.eclipse.statet.jcommons.status.StatusException;
import org.eclipse.statet.jcommons.status.WarningStatus;
import org.eclipse.statet.jcommons.ts.core.Tool;
import org.eclipse.statet.jcommons.ts.core.ToolRunnable;
import org.eclipse.statet.jcommons.ts.core.ToolService;
import org.eclipse.statet.internal.r.console.core.RConsoleCorePlugin;
import org.eclipse.statet.internal.r.nico.RNicoMessages;
import org.eclipse.statet.r.console.core.IRBasicAdapter;
import org.eclipse.statet.rj.renv.core.REnvConfiguration;
/**
* Cancel support for windows/rterm.
*/
@NonNullByDefault
class RTermCancelRunnable implements ToolRunnable {
RTermCancelRunnable() {
}
@Override
public String getLabel() {
return RNicoMessages.RTerm_CancelTask_label;
}
@Override
@SuppressWarnings("null")
public String getTypeId() {
return null; // not a real runnable
}
@Override
public boolean changed(final int event, final Tool process) {
return true;
}
@Override
public boolean canRunIn(final Tool tool) {
return true;
}
@Override
public void run(final ToolService service, final ProgressMonitor m) throws StatusException {
final IRBasicAdapter r= (IRBasicAdapter) service;
final REnvConfiguration rEnvConfig= nonNullAssert(
r.getTool().getAdapter(REnvConfiguration.class) );
String arch= rEnvConfig.getRArch();
if (arch == null) {
arch= Platform.getOSArch();
}
try {
m.beginTask(RNicoMessages.RTerm_CancelTask_SendSignal_label, 10);
URL url= RConsoleCorePlugin.getInstance().getBundle().getEntry(
"/win32/" + arch + "/sendsignal.exe"); //$NON-NLS-1$ //$NON-NLS-2$
if (url == null) {
throw new IOException("Missing 'sendsignal' tool for arch '" + arch + "'."); //$NON-NLS-1$
}
url= FileLocator.toFileURL(url);
final File file= new File(url.getPath());
if (!file.exists()) {
throw new IOException("Missing file '"+url.toExternalForm()+ "'."); //$NON-NLS-1$ //$NON-NLS-2$
}
m.addWorked(1);
final RTermController controller= (RTermController) r.getController();
final Process rProcess= controller.getProcess();
if (rProcess == null) {
return;
}
final ProcessBuilder processBuilder= new ProcessBuilder(
file.getAbsolutePath(), Long.toString(rProcess.pid()) );
processBuilder.redirectOutput(Redirect.DISCARD);
processBuilder.redirectErrorStream(true);
final Process process= processBuilder.start();
m.addWorked(1);
while (true) {
try {
final int code= process.exitValue();
if (code != 0) {
final ToStringBuilder detail= new ToStringBuilder("Command failed:");
detail.addProp("command", //$NON-NLS-1$
ProcessUtils.generateCommandLine(processBuilder.command()) );
detail.addProp("os.name", //$NON-NLS-1$
System.getProperty("os.name") ); //$NON-NLS-1$
detail.addProp("os.version", //$NON-NLS-1$
System.getProperty("os.version") ); //$NON-NLS-1$
detail.addProp("os.arch", //$NON-NLS-1$
System.getProperty("os.arch") ); //$NON-NLS-1$
detail.addProp("r.arch", //$NON-NLS-1$
arch );
detail.addProp("exit.code", //$NON-NLS-1$
"0x" + Integer.toHexString(code) );
throw new IOException(detail.toString());
}
break;
}
catch (final IllegalThreadStateException e) {
}
if (m.isCanceled()) {
process.destroy();
RConsoleCorePlugin.log(new Status(IStatus.WARNING, RConsoleCorePlugin.BUNDLE_ID, -1,
"Sending CTRL+C to R process canceled.", null )); //$NON-NLS-1$
break;
}
try {
Thread.sleep(50);
}
catch (final InterruptedException e) {
// continue directly
}
}
}
catch (final IOException e) {
throw new StatusException(new WarningStatus(RConsoleCorePlugin.BUNDLE_ID,
"Error Sending CTRL+C to R process.",
e ));
}
}
}