aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndrew Ferrazzutti2013-10-23 10:56:41 (EDT)
committerRoland Grunberg2013-10-30 16:57:47 (EDT)
commit7fa2c8d7e05e5fcaad33667327d8f97ace73461b (patch)
tree5798bb6b6de2ef67ba4c63cec396895b08504a8f
parentfcd723f3b2c59c8cb8d3372aa27a0ca7d66e610d (diff)
downloadorg.eclipse.linuxtools-7fa2c8d7e05e5fcaad33667327d8f97ace73461b.zip
org.eclipse.linuxtools-7fa2c8d7e05e5fcaad33667327d8f97ace73461b.tar.gz
org.eclipse.linuxtools-7fa2c8d7e05e5fcaad33667327d8f97ace73461b.tar.bz2
Systemtap: make fixes to script start/stop actions.refs/changes/39/17739/3
1) The Stop Script button now terminates a Systemtap script if it is clicked before the script actually begins. 2) The Stop Script button now becomes deactivated when a script exits on its own. 3) Starting and stopping scripts is now much more stable. For instance, starting & stopping scripts quickly and repeatedly no longer causes script run failures. Change-Id: I4334eeb9c9cf598eb688356f87f3a3952e3beb40 Signed-off-by: Andrew Ferrazzutti <aferrazz@redhat.com> Reviewed-on: https://git.eclipse.org/r/17739 Tested-by: Hudson CI Reviewed-by: Roland Grunberg <rgrunber@redhat.com> IP-Clean: Roland Grunberg <rgrunber@redhat.com> Tested-by: Roland Grunberg <rgrunber@redhat.com>
-rw-r--r--systemtap/org.eclipse.linuxtools.systemtap.structures/src/org/eclipse/linuxtools/systemtap/structures/runnable/Command.java4
-rw-r--r--systemtap/org.eclipse.linuxtools.systemtap.ui.consolelog/src/org/eclipse/linuxtools/internal/systemtap/ui/consolelog/actions/StopScriptAction.java2
-rw-r--r--systemtap/org.eclipse.linuxtools.systemtap.ui.consolelog/src/org/eclipse/linuxtools/systemtap/ui/consolelog/structures/ScriptConsole.java164
-rw-r--r--systemtap/org.eclipse.linuxtools.systemtap.ui.ide.tests/src/org/eclipse/linuxtools/systemtap/ui/ide/test/swtbot/TestCreateSystemtapScript.java60
4 files changed, 173 insertions, 57 deletions
diff --git a/systemtap/org.eclipse.linuxtools.systemtap.structures/src/org/eclipse/linuxtools/systemtap/structures/runnable/Command.java b/systemtap/org.eclipse.linuxtools.systemtap.structures/src/org/eclipse/linuxtools/systemtap/structures/runnable/Command.java
index 9dd213e..e38891c 100644
--- a/systemtap/org.eclipse.linuxtools.systemtap.structures/src/org/eclipse/linuxtools/systemtap/structures/runnable/Command.java
+++ b/systemtap/org.eclipse.linuxtools.systemtap.structures/src/org/eclipse/linuxtools/systemtap/structures/runnable/Command.java
@@ -160,7 +160,8 @@ public class Command implements Runnable {
/**
* Stops the process from running and stops the <code>StreamGobblers</code> from monitering
- * the dead process and unregisters the StreamListener.
+ * the dead process and unregisters the StreamListener. Also wakes up any threads waiting
+ * on this command.
*/
public synchronized void stop() {
if(!stopped) {
@@ -182,6 +183,7 @@ public class Command implements Runnable {
}
removeInputStreamListener(logger);
stopped = true;
+ notifyAll(); // Wake up threads waiting for this command to stop.
}
}
diff --git a/systemtap/org.eclipse.linuxtools.systemtap.ui.consolelog/src/org/eclipse/linuxtools/internal/systemtap/ui/consolelog/actions/StopScriptAction.java b/systemtap/org.eclipse.linuxtools.systemtap.ui.consolelog/src/org/eclipse/linuxtools/internal/systemtap/ui/consolelog/actions/StopScriptAction.java
index 3807afe..fe55925 100644
--- a/systemtap/org.eclipse.linuxtools.systemtap.ui.consolelog/src/org/eclipse/linuxtools/internal/systemtap/ui/consolelog/actions/StopScriptAction.java
+++ b/systemtap/org.eclipse.linuxtools.systemtap.ui.consolelog/src/org/eclipse/linuxtools/internal/systemtap/ui/consolelog/actions/StopScriptAction.java
@@ -35,7 +35,7 @@ public class StopScriptAction extends ConsoleAction implements ScriptConsoleObse
PlatformUI.getWorkbench().getDisplay().syncExec(new Runnable() {
@Override
public void run() {
- if(null != console && console.isRunning()){
+ if(null != console){
console.stop();
}
}
diff --git a/systemtap/org.eclipse.linuxtools.systemtap.ui.consolelog/src/org/eclipse/linuxtools/systemtap/ui/consolelog/structures/ScriptConsole.java b/systemtap/org.eclipse.linuxtools.systemtap.ui.consolelog/src/org/eclipse/linuxtools/systemtap/ui/consolelog/structures/ScriptConsole.java
index 1d476f8..2bd6c51 100644
--- a/systemtap/org.eclipse.linuxtools.systemtap.ui.consolelog/src/org/eclipse/linuxtools/systemtap/ui/consolelog/structures/ScriptConsole.java
+++ b/systemtap/org.eclipse.linuxtools.systemtap.ui.consolelog/src/org/eclipse/linuxtools/systemtap/ui/consolelog/structures/ScriptConsole.java
@@ -33,16 +33,42 @@ import org.eclipse.ui.console.IOConsole;
/**
- * This class serves as a pain in the ConsoleView. It is used to create a new Command that,
- * through ConsoleDaemons will print all the output the the console. In order to stop the
+ * This class serves as a pane in the ConsoleView. It is used to create a new Command that,
+ * through ConsoleDaemons, will print all the output the the console. In order to stop the
* running Command <code>StopScriptAction</code> should be used to stop this console from
* running.
* @author Ryan Morse
*/
public class ScriptConsole extends IOConsole {
+ private static final long RETRY_STOP_TIME = 500;
+ /**
+ * The command that will run in this console.
+ */
private Command cmd;
+
+ /**
+ * A protocol for sending "stop" signals to cmd when it is forcably
+ * stopped by a user action.
+ */
private Runnable stopCommand;
+
+ /**
+ * A thread in which to asynchronously run stopCommand.
+ */
+ private Thread stopCommandThread;
+
+ /**
+ * A thread used for notifying the console when cmd has successfully stopped.
+ */
+ private Thread onCmdStopThread;
+
+ /**
+ * A thread used for starting a new run of cmd. It starts a new run only
+ * once a previous run of cmd has successfully stopped.
+ */
+ private Thread onCmdStartThread;
+
private String moduleName;
private ErrorStreamDaemon errorDaemon;
@@ -78,8 +104,15 @@ public class ScriptConsole extends IOConsole {
if (consoleIterator instanceof ScriptConsole){
activeConsole = (ScriptConsole) consoleIterator;
if(activeConsole.getName().endsWith(name)) {
- //Stop any script currently running
- activeConsole.stop();
+ //Stop any script currently running, and terminate stream listeners.
+ if (activeConsole.isRunning()) {
+ activeConsole.onCmdStopThread.interrupt();
+ activeConsole.stop();
+ if (activeConsole.errorDaemon != null) {
+ activeConsole.cmd.removeErrorStreamListener(activeConsole.errorDaemon);
+ }
+ activeConsole.cmd.removeInputStreamListener(activeConsole.consoleDaemon);
+ }
//Remove output from last run
activeConsole.clearConsole();
activeConsole.setName(name);
@@ -130,9 +163,7 @@ public class ScriptConsole extends IOConsole {
for(IConsole con : ic) {
if (con instanceof ScriptConsole){
console = (ScriptConsole)con;
- if(console.isRunning()){
- console.stop();
- }
+ console.stop();
}
}
}
@@ -171,15 +202,30 @@ public class ScriptConsole extends IOConsole {
* @since 2.0
*/
public void run(String[] command, String[] envVars, IErrorParser errorParser) {
- cmd = new ScpExec(command);
+ // Don't start a new command if one is already waiting to be started.
+ if (onCmdStartThread != null && onCmdStartThread.isAlive()) {
+ return;
+ }
+ cmd = new ScpExec(command);
+
this.stopCommand = new Runnable() {
+ private Command stopcmd = cmd;
+ private String stopString = getStopString();
+
@Override
public void run() {
- ScpExec stop = new ScpExec(new String[]{getStopString()});
+ ScpExec stop = new ScpExec(new String[]{stopString});
try {
- stop.start();
+ do {
+ stop.start();
+ synchronized (stopcmd) {
+ stopcmd.wait(RETRY_STOP_TIME);
+ }
+ } while (stopcmd.isRunning());
} catch (CoreException e) {
- // Failed to start the 'stop' process. Ignore.
+ // Failed to start the 'stop' process. Ignore.
+ } catch (InterruptedException e) {
+ // Wait was interrupted. Exit.
}
}
};
@@ -195,37 +241,90 @@ public class ScriptConsole extends IOConsole {
* @since 2.0
*/
public void runLocally(String[] command, String[] envVars, IErrorParser errorParser) {
+ // Don't start a new command if one is already waiting to be started.
+ if (onCmdStartThread != null && onCmdStartThread.isAlive()) {
+ return;
+ }
cmd = new Command(command, envVars);
+
this.stopCommand = new Runnable() {
+ private Command stopcmd = cmd;
+ String stopString = getStopString();
+
@Override
public void run() {
try {
- RuntimeProcessFactory.getFactory().exec(getStopString(), null, null);
+ do {
+ RuntimeProcessFactory.getFactory().exec(stopString, null, null);
+ synchronized (stopcmd) {
+ stopcmd.wait(RETRY_STOP_TIME);
+ }
+ } while (stopcmd.isRunning());
} catch (IOException e) {
ExceptionErrorDialog.openError(Localization.getString("ScriptConsole.ErrorKillingStap"), e); //$NON-NLS-1$
+ } catch (InterruptedException e) {
+ //Wait was interrupted. Exit.
}
}
};
this.run(cmd, errorParser);
}
- private void run(Command cmd, IErrorParser errorParser){
- createConsoleDaemon();
- if (errorParser != null) {
+ private void run(final Command cmd, IErrorParser errorParser){
+ final Runnable onCmdStop = new Runnable() {
+ @Override
+ public void run() {
+ try {
+ synchronized (cmd) {
+ cmd.wait();
+ }
+ onCmdStopActions();
+ } catch (InterruptedException e) {
+ return;
+ }
+ }
+ };
+ Runnable onCmdStart = new Runnable() {
+ @Override
+ public void run() {
+ if (stopCommandThread != null && stopCommandThread.isAlive()) {
+ try {
+ stopCommandThread.join();
+ } catch (InterruptedException e) {
+ return;
+ }
+ }
+ createConsoleDaemon();
+ if (errorDaemon != null) {
+ cmd.addErrorStreamListener(errorDaemon);
+ }
+ cmd.addInputStreamListener(consoleDaemon);
+ try {
+ cmd.start();
+ } catch (CoreException e) {
+ ExceptionErrorDialog.openError(e.getMessage(), e);
+ notifyConsoleObservers(false);
+ cmd.dispose();
+ return;
+ }
+ notifyConsoleObservers(true);
+ onCmdStopThread = new Thread(onCmdStop);
+ onCmdStopThread.start();
+ }
+ };
+
+ if (errorParser != null) {
createErrorDaemon(errorParser);
}
- if (errorDaemon != null) {
- cmd.addErrorStreamListener(errorDaemon);
- }
- cmd.addInputStreamListener(consoleDaemon);
- try {
- cmd.start();
- } catch (CoreException e) {
- ExceptionErrorDialog.openError(e.getMessage(), e);
- }
- activate();
- notifyConsoleObservers(true);
- ConsolePlugin.getDefault().getConsoleManager().showConsoleView(this);
+ activate();
+ ConsolePlugin.getDefault().getConsoleManager().showConsoleView(this);
+
+ onCmdStartThread = new Thread(onCmdStart);
+ onCmdStartThread.start();
+ }
+
+ private final void onCmdStopActions() {
+ notifyConsoleObservers(false);
}
void notifyConsoleObservers(boolean running){
@@ -295,12 +394,11 @@ public class ScriptConsole extends IOConsole {
* Stops the running command and the associated listeners.
*/
public synchronized void stop() {
- if(isRunning()) {
- // Stop the underlying stap process
- this.stopCommand.run();
-
- setName(Localization.getString("ScriptConsole.Terminated") + super.getName()); //$NON-NLS-1$
- notifyConsoleObservers(false);
+ if (isRunning() && (stopCommandThread == null || !stopCommandThread.isAlive())) {
+ // Stop the underlying stap process
+ stopCommandThread = new Thread(this.stopCommand);
+ stopCommandThread.start();
+ setName(Localization.getString("ScriptConsole.Terminated") + super.getName()); //$NON-NLS-1$
}
}
diff --git a/systemtap/org.eclipse.linuxtools.systemtap.ui.ide.tests/src/org/eclipse/linuxtools/systemtap/ui/ide/test/swtbot/TestCreateSystemtapScript.java b/systemtap/org.eclipse.linuxtools.systemtap.ui.ide.tests/src/org/eclipse/linuxtools/systemtap/ui/ide/test/swtbot/TestCreateSystemtapScript.java
index ac7ebb2..4d45070 100644
--- a/systemtap/org.eclipse.linuxtools.systemtap.ui.ide.tests/src/org/eclipse/linuxtools/systemtap/ui/ide/test/swtbot/TestCreateSystemtapScript.java
+++ b/systemtap/org.eclipse.linuxtools.systemtap.ui.ide.tests/src/org/eclipse/linuxtools/systemtap/ui/ide/test/swtbot/TestCreateSystemtapScript.java
@@ -12,11 +12,10 @@
package org.eclipse.linuxtools.systemtap.ui.ide.test.swtbot;
+import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
-import java.io.IOException;
-
-import org.eclipse.linuxtools.tools.launch.core.factory.RuntimeProcessFactory;
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.MenuItem;
@@ -42,6 +41,7 @@ import org.junit.runner.RunWith;
public class TestCreateSystemtapScript {
static SWTWorkbenchBot bot;
+ static boolean stapInstalled;
private static final String SYSTEMTAP_PROJECT_NAME = "SystemtapTest";
@@ -89,11 +89,10 @@ public class TestCreateSystemtapScript {
private static class StapHasExited extends DefaultCondition{
@Override
- public boolean test() throws IOException, InterruptedException {
- Process process = RuntimeProcessFactory.getFactory().exec(
- new String[] {"pgrep","stap"}, null); //$NON-NLS-1$
- process.waitFor();
- return (process.exitValue() != 0);
+ public boolean test() {
+ SWTBotView console = TestCreateSystemtapScript.bot.viewById("org.eclipse.ui.console.ConsoleView");
+ console.setFocus();
+ return (!console.toolbarButton("Stop Script").isEnabled());
}
@Override
@@ -105,10 +104,12 @@ public class TestCreateSystemtapScript {
@BeforeClass
public static void beforeClass() {
bot = new SWTWorkbenchBot();
+ stapInstalled = true;
// Dismiss "Systemtap not installed" dialog(s) if present.
try {
SWTBotShell shell = bot.shell("Cannot Run Systemtap").activate();
+ stapInstalled = false;
shell.close();
shell = bot.shell("Cannot Run Systemtap").activate();
@@ -126,6 +127,17 @@ public class TestCreateSystemtapScript {
//ignore
}
+ // Set SystemTap IDE perspective.
+ bot.perspectiveByLabel("SystemTap IDE").activate();
+ bot.sleep(500);
+ for (SWTBotShell sh : bot.shells()) {
+ if (sh.getText().startsWith("SystemTap IDE")) {
+ sh.activate();
+ bot.sleep(500);
+ break;
+ }
+ }
+
// Create a Systemtap project.
SWTBotMenu fileMenu = bot.menu("File");
SWTBotMenu newMenu = fileMenu.menu("New");
@@ -163,17 +175,15 @@ public class TestCreateSystemtapScript {
bot.button("Next >").click();
SWTBotText text = bot.textWithLabel("Script Name:").setText(scriptName);
- assert(text.getText().equals(scriptName));
- bot.button("Browse").click();
+ assertEquals(scriptName, text.getText());
- SWTBotTree tree = bot.tree().select(SYSTEMTAP_PROJECT_NAME);
- assertNotNull(tree);
+ text = bot.textWithLabel("Project:").setText(SYSTEMTAP_PROJECT_NAME);
+ assertEquals(SYSTEMTAP_PROJECT_NAME, text.getText());
- bot.button("OK").click();
bot.button("Finish").click();
bot.waitUntil(new ShellIsClosed(shell));
- assert(bot.activeEditor().getTitle().equals(scriptName));
+ assertEquals(scriptName, bot.activeEditor().getTitle());
}
@Test
@@ -184,7 +194,8 @@ public class TestCreateSystemtapScript {
// Write a script
SWTBotEclipseEditor editor = bot.editorByTitle(scriptName).toTextEditor();
editor.typeText(0, editor.getText().length(), "\nprobe begin{log(\"began");
- editor.typeText(0, editor.getText().length() - 1, "; exit(");
+ editor.typeText(0, editor.getText().length() - 1, "); exit(");
+ editor.typeText(0, editor.getText().length(), "}");
editor.save();
// Focus on project explorer view.
@@ -205,13 +216,18 @@ public class TestCreateSystemtapScript {
SWTBotTree runConfigurationsTree = bot.tree();
runConfigurationsTree.select("SystemTap").contextMenu("New").click();
- bot.button("Run").click();
- bot.waitUntil(new ShellIsClosed(shell));
-
- SWTBotView console = bot.viewByTitle("Console");
- console.setFocus();
- assert(console.bot().label().getText().contains(scriptName));
- bot.waitUntil(new StapHasExited(), 10000);
+ if (stapInstalled) {
+ bot.button("Run").click();
+ bot.waitUntil(new ShellIsClosed(shell));
+
+ SWTBotView console = bot.viewById("org.eclipse.ui.console.ConsoleView");
+ console.setFocus();
+ assertTrue(console.bot().label().getText().contains(scriptName));
+ bot.waitUntil(new StapHasExited(), 10000);
+ } else {
+ bot.button("Close").click();
+ bot.waitUntil(new ShellIsClosed(shell));
+ }
}
public static void click(final MenuItem menuItem) {