| /*=============================================================================# |
| # 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 )); |
| } |
| } |
| |
| } |