When creating a new LocalHostShell a new LocalHostThread is created, along side with two LocalShellOutputReaders (output and error). Both readers will receive a reference to one of the localhostThread's readers. When the thread finishes its task, the reader is closed. If any of the readers is "late" trying to read data, will through an error similar to "Ensure open stream" or "Pipe closed". Any reading done on the reader should be done atomically, such that no reader should be caught off-guard when the stream closes. Also, the readers should reference the thread's reader, otherwise nulling this reference will be useless.
Signed-off-by: Ioana Grigoropol <ioanax.grigoro...@intel.com> --- .../dstore/shells/DStoreShellOutputReader.java | 52 ++++++++++++-------- .../services/local/shells/LocalHostShell.java | 22 ++++----- .../local/shells/LocalShellOutputReader.java | 52 ++++++++++++++------ .../services/local/shells/LocalShellThread.java | 24 +++++++-- .../shells/TerminalServiceShellOutputReader.java | 25 +++++++--- 5 files changed, 116 insertions(+), 59 deletions(-) diff --git a/rse/plugins/org.eclipse.rse.services.dstore/src/org/eclipse/rse/internal/services/dstore/shells/DStoreShellOutputReader.java b/rse/plugins/org.eclipse.rse.services.dstore/src/org/eclipse/rse/internal/services/dstore/shells/DStoreShellOutputReader.java index 84c9bb9..3f3e476 100644 --- a/rse/plugins/org.eclipse.rse.services.dstore/src/org/eclipse/rse/internal/services/dstore/shells/DStoreShellOutputReader.java +++ b/rse/plugins/org.eclipse.rse.services.dstore/src/org/eclipse/rse/internal/services/dstore/shells/DStoreShellOutputReader.java @@ -7,16 +7,19 @@ * * Initial Contributors: * The following IBM employees contributed to the Remote System Explorer - * component that contains this file: David McKnight, Kushal Munir, - * Michael Berger, David Dykstal, Phil Coulthard, Don Yantzi, Eric Simpson, + * component that contains this file: David McKnight, Kushal Munir, + * Michael Berger, David Dykstal, Phil Coulthard, Don Yantzi, Eric Simpson, * Emily Bruner, Mazen Faraj, Adrian Storisteanu, Li Ding, and Kent Hawley. - * + * * Contributors: * David McKnight (IBM) - [286671] return null when status is null *******************************************************************************/ package org.eclipse.rse.internal.services.dstore.shells; +import java.io.BufferedReader; +import java.util.concurrent.locks.Lock; + import org.eclipse.dstore.core.model.DataElement; import org.eclipse.dstore.extra.DomainEvent; import org.eclipse.dstore.extra.IDomainListener; @@ -41,13 +44,13 @@ public class DStoreShellOutputReader extends AbstractHostShellOutputReader imple _status.getDataStore().getDomainNotifier().addDomainListener(this); } } - + public String getWorkingDirectory() { String pwd = _status.getSource(); return pwd; } - + protected IHostOutput internalReadLine() { if (_status != null && _keepRunning) @@ -57,9 +60,9 @@ public class DStoreShellOutputReader extends AbstractHostShellOutputReader imple while (newSize > _statusOffset) { DataElement line = _status.get(_statusOffset++); - - - + + + String type = line.getType(); boolean isError = type.equals("error") || type.equals("stderr"); //$NON-NLS-1$ //$NON-NLS-2$ if (_isErrorReader && isError) @@ -71,13 +74,13 @@ public class DStoreShellOutputReader extends AbstractHostShellOutputReader imple return new DStoreHostOutput(line); } } - - + + try { if (_hostShell.isActive()) { - waitForResponse(); + waitForResponse(); return internalReadLine(); } else @@ -86,7 +89,7 @@ public class DStoreShellOutputReader extends AbstractHostShellOutputReader imple } } catch (Exception e) - { + { e.printStackTrace(); } } @@ -128,7 +131,7 @@ public class DStoreShellOutputReader extends AbstractHostShellOutputReader imple // for now, this is pulled via internalReadLine() notifyResponse(); } - + } /** @@ -138,16 +141,16 @@ public class DStoreShellOutputReader extends AbstractHostShellOutputReader imple { try { - wait(); + wait(); } catch (InterruptedException e) { e.printStackTrace(); } } - + /** - * Causes all threads waiting for this + * Causes all threads waiting for this * to wake up. */ public synchronized void notifyResponse() @@ -161,13 +164,22 @@ public class DStoreShellOutputReader extends AbstractHostShellOutputReader imple e.printStackTrace(); } } - + public void finish() { super.finish(); notifyResponse(); } - + + public BufferedReader getReader() { + // TODO Auto-generated method stub + return null; + } + + public Lock getReaderLock() { + return null; + } + /* private void handleInput() { @@ -177,7 +189,7 @@ public class DStoreShellOutputReader extends AbstractHostShellOutputReader imple int currentSize = _linesOfOutput.size(); for (int loop = currentSize; loop < totalSize; loop++) - { + { DataElement result = (DataElement) results.get(loop); addLine(result.getName()); } @@ -185,4 +197,4 @@ public class DStoreShellOutputReader extends AbstractHostShellOutputReader imple */ } - + diff --git a/rse/plugins/org.eclipse.rse.services.local/src/org/eclipse/rse/internal/services/local/shells/LocalHostShell.java b/rse/plugins/org.eclipse.rse.services.local/src/org/eclipse/rse/internal/services/local/shells/LocalHostShell.java index 250a904..d272989 100644 --- a/rse/plugins/org.eclipse.rse.services.local/src/org/eclipse/rse/internal/services/local/shells/LocalHostShell.java +++ b/rse/plugins/org.eclipse.rse.services.local/src/org/eclipse/rse/internal/services/local/shells/LocalHostShell.java @@ -7,10 +7,10 @@ * * Initial Contributors: * The following IBM employees contributed to the Remote System Explorer - * component that contains this file: David McKnight, Kushal Munir, - * Michael Berger, David Dykstal, Phil Coulthard, Don Yantzi, Eric Simpson, + * component that contains this file: David McKnight, Kushal Munir, + * Michael Berger, David Dykstal, Phil Coulthard, Don Yantzi, Eric Simpson, * Emily Bruner, Mazen Faraj, Adrian Storisteanu, Li Ding, and Kent Hawley. - * + * * Contributors: * Martin Oberhuber (Wind River) - [161838] local shell reports isActive() wrong *******************************************************************************/ @@ -18,8 +18,6 @@ package org.eclipse.rse.internal.services.local.shells; import org.eclipse.core.runtime.IProgressMonitor; -import org.eclipse.rse.internal.services.local.shells.LocalShellOutputReader; -import org.eclipse.rse.internal.services.local.shells.LocalShellThread; import org.eclipse.rse.services.shells.AbstractHostShell; import org.eclipse.rse.services.shells.IHostShell; import org.eclipse.rse.services.shells.IHostShellOutputReader; @@ -33,19 +31,19 @@ public class LocalHostShell extends AbstractHostShell implements IHostShell private LocalShellThread _shellThread; private LocalShellOutputReader _stdoutHandler; private LocalShellOutputReader _stderrHandler; - + public LocalHostShell(String initialWorkingDirectory, String invocation, String encoding, String[] environment) { - _shellThread = new LocalShellThread(initialWorkingDirectory, invocation, encoding, environment); - _stdoutHandler = new LocalShellOutputReader(this, _shellThread.getOutputStream(), false); - _stderrHandler = new LocalShellOutputReader(this, _shellThread.getErrorStream(),true); + _shellThread = new LocalShellThread(initialWorkingDirectory, invocation, encoding, environment); + _stdoutHandler = new LocalShellOutputReader(this, _shellThread.getOutputStream(), _shellThread, false); + _stderrHandler = new LocalShellOutputReader(this, _shellThread.getErrorStream(), _shellThread, true); } - + protected void run(IProgressMonitor monitor) { _shellThread.start(); } - + /* (non-Javadoc) * @see org.eclipse.rse.services.shells.IHostShell#isActive() @@ -68,7 +66,7 @@ public class LocalHostShell extends AbstractHostShell implements IHostShell { _shellThread.sendInput(command); } - + public IHostShellOutputReader getStandardOutputReader() { return _stdoutHandler; diff --git a/rse/plugins/org.eclipse.rse.services.local/src/org/eclipse/rse/internal/services/local/shells/LocalShellOutputReader.java b/rse/plugins/org.eclipse.rse.services.local/src/org/eclipse/rse/internal/services/local/shells/LocalShellOutputReader.java index ab8ff5c..ad3fa86 100644 --- a/rse/plugins/org.eclipse.rse.services.local/src/org/eclipse/rse/internal/services/local/shells/LocalShellOutputReader.java +++ b/rse/plugins/org.eclipse.rse.services.local/src/org/eclipse/rse/internal/services/local/shells/LocalShellOutputReader.java @@ -7,10 +7,10 @@ * * Initial Contributors: * The following IBM employees contributed to the Remote System Explorer - * component that contains this file: David McKnight, Kushal Munir, - * Michael Berger, David Dykstal, Phil Coulthard, Don Yantzi, Eric Simpson, + * component that contains this file: David McKnight, Kushal Munir, + * Michael Berger, David Dykstal, Phil Coulthard, Don Yantzi, Eric Simpson, * Emily Bruner, Mazen Faraj, Adrian Storisteanu, Li Ding, and Kent Hawley. - * + * * Contributors: * {Name} (company) - description of contribution. *******************************************************************************/ @@ -19,6 +19,7 @@ package org.eclipse.rse.internal.services.local.shells; import java.io.BufferedReader; import java.io.IOException; +import java.util.concurrent.locks.Lock; import org.eclipse.rse.internal.services.local.Activator; import org.eclipse.rse.services.shells.AbstractHostShellOutputReader; @@ -33,14 +34,16 @@ import org.eclipse.rse.services.shells.SimpleHostOutput; */ public class LocalShellOutputReader extends AbstractHostShellOutputReader implements IHostShellOutputReader { - protected BufferedReader _reader; +// protected volatile BufferedReader _reader; + private LocalShellThread _shellThread; private String fPromptChars = ">$%#]"; //Characters we accept as the end of a prompt //$NON-NLS-1$; - - public LocalShellOutputReader(IHostShell hostShell, BufferedReader reader, boolean isErrorReader) + + public LocalShellOutputReader(IHostShell hostShell, BufferedReader reader, LocalShellThread shellThread, boolean isErrorReader) { super(hostShell, isErrorReader); - _reader = reader; +// _reader = reader; + _shellThread = shellThread; } /* protected Object internalReadLine() @@ -137,9 +140,11 @@ public class LocalShellOutputReader extends AbstractHostShellOutputReader implem } */ protected IHostOutput internalReadLine() { - if (_reader == null) { + getLock().lock(); + if (getReader() == null) { //Our workaround sets the stderr reader to null, so we never give any stderr output. //TODO Check if ssh supports some method of having separate stdout and stderr streams + getLock().unlock(); return null; } StringBuffer theLine = new StringBuffer(); @@ -149,12 +154,14 @@ public class LocalShellOutputReader extends AbstractHostShellOutputReader implem boolean done = false; while (!done && !isFinished()) { try { - ch = _reader.read(); + ch = getReader().read(); switch (ch) { case -1: case 65535: - if (theLine.length() == 0) // End of Reader + if (theLine.length() == 0) {// End of Reader + getLock().unlock(); return null; + } done = true; break; case '\b': //backspace @@ -185,13 +192,13 @@ public class LocalShellOutputReader extends AbstractHostShellOutputReader implem theLine.append(tch); // Any other character } else if (ch == 27) { // Escape: ignore next char too - int nch = _reader.read(); + int nch = getReader().read(); if (theDebugLine!=null) theDebugLine.append((char)nch); if (nch == 91) { //vt100 escape sequence: read until end-of-command (skip digits and semicolon) //e.g. \x1b;13;m --> ignore the entire command, including the trailing m do { - nch = _reader.read(); + nch = getReader().read(); if (theDebugLine!=null) theDebugLine.append((char)nch); } while (Character.isDigit((char)nch) || nch == ';'); } @@ -202,9 +209,9 @@ public class LocalShellOutputReader extends AbstractHostShellOutputReader implem // there are more characters // in the Buffer...If not, then we assume it is waiting for // input. - if (!done && !_reader.ready()) { - // wait to make sure -- max. 500 msec to wait for new chars - // if we are not at a CRLF seems to be appropriate for the + if (!done && !getReader().ready()) { + // wait to make sure -- max. 500 msec to wait for new chars + // if we are not at a CRLF seems to be appropriate for the // Pipes and Threads in ssh. long waitIncrement = 500; // Check if we think we are at a prompt @@ -219,7 +226,7 @@ public class LocalShellOutputReader extends AbstractHostShellOutputReader implem Thread.sleep(waitIncrement); } catch (InterruptedException e) { } - if (!_reader.ready()) { + if (!getReader().ready()) { done = true; } } @@ -228,6 +235,7 @@ public class LocalShellOutputReader extends AbstractHostShellOutputReader implem //our reader thread completely... the exception could just be //temporary, and we should keep running! Activator.getDefault().logException(e); + getLock().unlock(); return null; } } @@ -235,8 +243,20 @@ public class LocalShellOutputReader extends AbstractHostShellOutputReader implem String debugLine = theDebugLine.toString(); debugLine.compareTo(""); //$NON-NLS-1$ } + getLock().unlock(); return new SimpleHostOutput(theLine.toString()); } + private Lock getLock() { + return _shellThread.getLock(); + } + public BufferedReader getReader() { + if (isErrorReader()) + return _shellThread.getErrorStream(); + return _shellThread.getOutputStream(); + } + public Lock getReaderLock() { + return _shellThread.getLock(); + } } diff --git a/rse/plugins/org.eclipse.rse.services.local/src/org/eclipse/rse/internal/services/local/shells/LocalShellThread.java b/rse/plugins/org.eclipse.rse.services.local/src/org/eclipse/rse/internal/services/local/shells/LocalShellThread.java index 0a33ad4..7407f2e 100644 --- a/rse/plugins/org.eclipse.rse.services.local/src/org/eclipse/rse/internal/services/local/shells/LocalShellThread.java +++ b/rse/plugins/org.eclipse.rse.services.local/src/org/eclipse/rse/internal/services/local/shells/LocalShellThread.java @@ -16,7 +16,7 @@ * Lothar Werzinger (Tradescape) - [161838] Support terminating local shells * David McKnight (IBM) - [189387] Use specified encoding for shell output * Martin Oberhuber (Wind River) - [161838] local shell reports isActive() wrong - * Anna Dushistova (MontaVsita) - [249354] Incorrect behaviour of local shells subsystem runCommand method + * Anna Dushistova (MontaVsita) - [249354] Incorrect behaviour of local shells subsystem runCommand method *******************************************************************************/ package org.eclipse.rse.internal.services.local.shells; @@ -29,6 +29,8 @@ import java.io.InputStreamReader; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.net.URL; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; import org.eclipse.core.runtime.FileLocator; @@ -62,9 +64,10 @@ public class LocalShellThread extends Thread private BufferedReader _stdInput; private BufferedReader _stdError; + private Lock _lock; /** * constructor for local command shell monitor - * + * * @param cwd initial working directory * @param invocation launch shell command * @param encoding encoding to use or <code>null</code> for default @@ -192,7 +195,7 @@ public class LocalShellThread extends Thread args = new String[1]; args[0] = _invocation; _theProcess = Runtime.getRuntime().exec(args[0], envVars, theDirectory); - } else { + } else { args = new String[3]; args[0] = theShell; args[1] = "-c";//$NON-NLS-1$ @@ -260,6 +263,7 @@ public class LocalShellThread extends Thread _stdError = new BufferedReader(new InputStreamReader(_theProcess.getErrorStream())); + _lock = new ReentrantLock(); } catch (IOException e) { @@ -438,9 +442,14 @@ public class LocalShellThread extends Thread _isDone = true; try { + _lock.lock(); _stdInput.close(); _stdError.close(); + _stdInput = null; + _stdError = null; + + _lock.unlock(); if (_theProcess != null) { @@ -511,4 +520,13 @@ public class LocalShellThread extends Thread } + public Lock getLock() { + return _lock; + } + + + public void setLock(Lock _lock) { + this._lock = _lock; + } + } diff --git a/rse/plugins/org.eclipse.rse.services/src/org/eclipse/rse/internal/services/shells/TerminalServiceShellOutputReader.java b/rse/plugins/org.eclipse.rse.services/src/org/eclipse/rse/internal/services/shells/TerminalServiceShellOutputReader.java index 16364e1..fef0032 100644 --- a/rse/plugins/org.eclipse.rse.services/src/org/eclipse/rse/internal/services/shells/TerminalServiceShellOutputReader.java +++ b/rse/plugins/org.eclipse.rse.services/src/org/eclipse/rse/internal/services/shells/TerminalServiceShellOutputReader.java @@ -7,13 +7,13 @@ * * Initial Contributors: * The following IBM employees contributed to the Remote System Explorer - * component that contains this file: David McKnight, Kushal Munir, - * Michael Berger, David Dykstal, Phil Coulthard, Don Yantzi, Eric Simpson, + * component that contains this file: David McKnight, Kushal Munir, + * Michael Berger, David Dykstal, Phil Coulthard, Don Yantzi, Eric Simpson, * Emily Bruner, Mazen Faraj, Adrian Storisteanu, Li Ding, and Kent Hawley. - * + * * Contributors: - * Martin Oberhuber (Wind River) - Adapted from LocalShellOutputReader. - * Martin Oberhuber (Wind River) - Added vt100 escape sequence ignoring. + * Martin Oberhuber (Wind River) - Adapted from LocalShellOutputReader. + * Martin Oberhuber (Wind River) - Added vt100 escape sequence ignoring. * Anna Dushistova (MontaVista) - adapted from SshShellOutputReader * Anna Dushistova (MontaVista) - [240523] [rseterminals] Provide a generic adapter factory that adapts any ITerminalService to an IShellService * Rob Stryker (JBoss) - [335059] TerminalServiceShellOutputReader logs error when hostShell.exit() is called @@ -23,6 +23,7 @@ package org.eclipse.rse.internal.services.shells; import java.io.BufferedReader; import java.io.IOException; +import java.util.concurrent.locks.Lock; import org.eclipse.rse.internal.services.Activator; import org.eclipse.rse.services.shells.AbstractHostShellOutputReader; @@ -125,8 +126,8 @@ public class TerminalServiceShellOutputReader extends // in the Buffer...If not, then we assume it is waiting for // input. if (!done && !fReader.ready()) { - // wait to make sure -- max. 500 msec to wait for new chars - // if we are not at a CRLF seems to be appropriate for the + // wait to make sure -- max. 500 msec to wait for new chars + // if we are not at a CRLF seems to be appropriate for the // Pipes and Threads in ssh. long waitIncrement = 500; // Check if we think we are at a prompt @@ -163,7 +164,7 @@ public class TerminalServiceShellOutputReader extends } return new SimpleHostOutput(theLine.toString()); } - + /** * Stop the reader Thread, forcing internalReadLine() to return. * Does not close the Stream. @@ -174,4 +175,12 @@ public class TerminalServiceShellOutputReader extends fReaderThread.interrupt(); } } + + public BufferedReader getReader() { + return fReader; + } + + public Lock getReaderLock() { + return null; + } } -- 1.7.9.5 _______________________________________________ yocto mailing list yocto@yoctoproject.org https://lists.yoctoproject.org/listinfo/yocto