public Integer create()

in core/src/main/java/org/apache/brooklyn/util/core/internal/ssh/sshj/SshjTool.java [973:1086]


        public Integer create() throws Exception {
            try {
                session = acquire(newSessionAction());

                shell = session.startShell();

                if (out != null) {
                    InputStream outstream = shell.getInputStream();
                    outgobbler = new StreamGobbler(outstream, out, (Logger)null);
                    outgobbler.start();
                }
                if (err != null) {
                    InputStream errstream = shell.getErrorStream();
                    errgobbler = new StreamGobbler(errstream, err, (Logger)null);
                    errgobbler.start();
                }

                OutputStream shellStdin = shell.getOutputStream();

                for (CharSequence cmd : commands) {
                    try {
                        shellStdin.write(toUTF8ByteArray(cmd+"\n"));
                        shellStdin.flush();
                    } catch (ConnectionException e) {
                        if (checkInterrupted(e)) {
                            throw e;
                        }
                        if (!shell.isOpen()) {
                            // shell is closed; presumably the user command did `exit`
                            if (LOG.isDebugEnabled()) LOG.debug("Shell closed to {} when executing {}", SshjTool.this.toString(), commands);
                            break;
                        } else {
                            throw e;
                        }
                    }
                }
                if (inCallback != null) {
                    inCallback.set(shellStdin);
                    synchronized (inCallback) { inCallback.notifyAll(); }
                } else {
                    closeWhispering(shellStdin, this);
                }

                boolean timedOut = false;
                Exception last = null;
                try {
                    long timeoutMillis = Math.min(timeout.toMilliseconds(), Integer.MAX_VALUE);
                    long timeoutEnd = System.currentTimeMillis() + timeoutMillis;
                    do {
                        if (!shell.isOpen() && ((SessionChannel)session).getExitStatus()!=null)
                            // shell closed, and exit status returned
                            break;
                        boolean endBecauseReturned =
                                // if either condition is satisfied, then wait 1s in hopes the other does, then return
                                (!shell.isOpen() || ((SessionChannel)session).getExitStatus()!=null);
                        try {
                            shell.join(1000, TimeUnit.MILLISECONDS);
                        } catch (ConnectionException e) {
                            if (Throwables.getRootCause(e) instanceof TimeoutException) {
                                // normal, do nothing
                            } else {
                                LOG.debug("SshjTool exception joining shell", e);
                                if (isNonRetryableException(e)) {
                                    throw e;
                                }
                                // don't automatically give up here, it might be a transient network failure
                                last = e;
                            }
                            LOG.trace("SshjTool threw exception joining shell (timeouts are normal)", e);
                        }
                        if (endBecauseReturned) {
                            // shell is still open, ie some process is running
                            // but we have a result code, so main shell is finished
                            // we waited one second extra to allow any background process
                            // which is nohupped to really be in the background (#162)
                            // now let's bail out
                            break;
                        }
                    } while (System.currentTimeMillis() < timeoutEnd);
                    if (shell.isOpen() && ((SessionChannel)session).getExitStatus()==null) {
                        LOG.debug("Timeout ({}) in SSH shell to {}", timeout, this);
                        // we timed out, or other problem -- reproduce the error.
                        // The shell.join should always have thrown ConnectionExceptoin (looking at code of
                        // AbstractChannel), but javadoc of Channel doesn't explicity say that so play it safe.
                        timedOut = true;
                        throw (last != null) ? last : new TimeoutException("Timeout after "+timeout+" executing "+this);
                    }
                    return ((SessionChannel)session).getExitStatus();
                } finally {
                    LOG.trace("SshjTool shell join completed", last);
                    // wait for all stdout/stderr to have been re-directed
                    closeWhispering(shell, this);
                    shell = null;
                    try {
                        // Don't use forever (i.e. 0) because BROOKLYN-106: ssh hangs
                        long joinTimeout = (timedOut) ? 1000 : 10*1000;
                        if (outgobbler != null) {
                            outgobbler.join(joinTimeout);
                            outgobbler.close();
                        }
                        if (errgobbler != null) {
                            errgobbler.join(joinTimeout);
                            errgobbler.close();
                        }
                    } catch (InterruptedException e) {
                        LOG.warn("Interrupted gobbling streams from ssh: "+commands, e);
                        throw Exceptions.propagate(e);
                    }
                }

            } finally {
                clear();
            }
        }