blob: fdb514c25073595918417907894336e5268acbe4 [file] [log] [blame]
/*=============================================================================#
# Copyright (c) 2007, 2019 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 java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.Arrays;
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.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.
*/
class RTermCancelRunnable implements ToolRunnable {
RTermCancelRunnable() {
}
@Override
public String getLabel() {
return RNicoMessages.RTerm_CancelTask_label;
}
@Override
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= 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 Long processId = controller.fProcessId;
if (processId == null) {
RConsoleCorePlugin.log(new Status(IStatus.WARNING, RConsoleCorePlugin.BUNDLE_ID,
"Cannot run cancel command: process-id of Rterm process is missing." )); //$NON-NLS-1$
return;
}
final String[] cmd = new String[] {
file.getAbsolutePath(), processId.toString()
// the tool usually does not print output
};
final Process process = Runtime.getRuntime().exec(cmd);
m.addWorked(1);
while (true) {
try {
final int code = process.exitValue();
if (code != 0) {
final StringBuilder detail = new StringBuilder("Command failed:"); //$NON-NLS-1$
detail.append("\n command = "); //$NON-NLS-1$
detail.append(Arrays.toString(cmd));
detail.append("\n os.name = "); //$NON-NLS-1$
detail.append(System.getProperty("os.name")); //$NON-NLS-1$
detail.append("\n os.version = "); //$NON-NLS-1$
detail.append(System.getProperty("os.version")); //$NON-NLS-1$
detail.append("\n os.arch = "); //$NON-NLS-1$
detail.append(System.getProperty("os.arch")); //$NON-NLS-1$
detail.append("\n r.arch = "); //$NON-NLS-1$
detail.append(arch);
detail.append("\n exit.code = 0x"); //$NON-NLS-1$
detail.append(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, command: " + Arrays.toString(cmd), 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 ));
}
}
}