diff --git a/rse/plugins/org.eclipse.rse.services/src/org/eclipse/rse/internal/services/terminals/AbstractTerminalShell.java b/rse/plugins/org.eclipse.rse.services/src/org/eclipse/rse/internal/services/terminals/AbstractTerminalShell.java index 44527624bdc..a6b7d4c7393 100644 --- a/rse/plugins/org.eclipse.rse.services/src/org/eclipse/rse/internal/services/terminals/AbstractTerminalShell.java +++ b/rse/plugins/org.eclipse.rse.services/src/org/eclipse/rse/internal/services/terminals/AbstractTerminalShell.java @@ -58,18 +58,49 @@ public abstract class AbstractTerminalShell extends PlatformObject implements IT public int exitValue() { // exit values are not supported by default, but we need to observe the // API by throwing IllegalThreadStateException - if (isActive()) + if (isActive()) { throw new IllegalThreadStateException(); + } return 0; } + /** + * Return the interval (in milliseconds) for polling the {@ink #isActive()} + * method during the {@link #waitFor(long)} method. Subclasses may override + * to return different poll intervals. + * + * The interval may be changed dynamically as appropriate for the current + * state of this shell. That way, wait polling mechanisms such as + * exponential backoff can be implemented. + * + * Or, a concrete implementation that supports a notification mechanism for + * knowing when the shell terminates, can use this to tweak the waitFor() + * method by returning Long.MAX_VALUE here (wait forever), but calling + * {@link #notifyAll()} when the shell is dead. + * + * @return interval (in milliseconds) for polling active state + */ + protected long getWaitForPollInterval() { + return 500L; + } + + /** + * Wait for the shell to terminate. This uses a polling mechanism by + * default, which can be tweaked by overriding + * {@link #getWaitForPollInterval()}. + * + * @see IBaseShell#waitFor(long) + */ public boolean waitFor(long timeout) throws InterruptedException { boolean active = isActive(); if (active) { - synchronized (this) { - wait(timeout); - } - active = isActive(); + long endTime = (timeout <= 0) ? Long.MAX_VALUE : System.currentTimeMillis() + timeout - getWaitForPollInterval(); + do { + synchronized (this) { + wait(getWaitForPollInterval()); + } + active = isActive(); + } while (active && (timeout <= 0 || System.currentTimeMillis() < endTime)); } return active; } diff --git a/rse/plugins/org.eclipse.rse.services/src/org/eclipse/rse/internal/services/terminals/ProcessBaseShell.java b/rse/plugins/org.eclipse.rse.services/src/org/eclipse/rse/internal/services/terminals/ProcessBaseShell.java index d569d7837ef..7464167f981 100644 --- a/rse/plugins/org.eclipse.rse.services/src/org/eclipse/rse/internal/services/terminals/ProcessBaseShell.java +++ b/rse/plugins/org.eclipse.rse.services/src/org/eclipse/rse/internal/services/terminals/ProcessBaseShell.java @@ -125,6 +125,8 @@ public class ProcessBaseShell extends PlatformObject implements IBaseShell { if (active) { Thread watchdog = null; if (timeout > 0) { + // TODO Check if using java.util.Timer would be more efficient + // than our own Watchdog watchdog = new Watchdog(Thread.currentThread(), timeout) { protected boolean conditionDone() { return !isActive();