You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mina.apache.org by gn...@apache.org on 2012/05/19 14:35:28 UTC

svn commit: r1340435 - in /mina/sshd/trunk/sshd-core/src: main/java/org/apache/sshd/server/shell/ test/java/org/apache/sshd/common/channel/ test/java/org/apache/sshd/server/shell/ test/java/org/apache/sshd/util/

Author: gnodet
Date: Sat May 19 12:35:27 2012
New Revision: 1340435

URL: http://svn.apache.org/viewvc?rev=1340435&view=rev
Log:
[SSHD-145] InvertedShellWrapper may not send process output back if process exits too fast

Added:
    mina/sshd/trunk/sshd-core/src/test/java/org/apache/sshd/server/shell/
    mina/sshd/trunk/sshd-core/src/test/java/org/apache/sshd/server/shell/InvertedShellWrapperTest.java
    mina/sshd/trunk/sshd-core/src/test/java/org/apache/sshd/util/BogusEnvironment.java
    mina/sshd/trunk/sshd-core/src/test/java/org/apache/sshd/util/BogusExitCallback.java
    mina/sshd/trunk/sshd-core/src/test/java/org/apache/sshd/util/BogusInvertedShell.java
Modified:
    mina/sshd/trunk/sshd-core/src/main/java/org/apache/sshd/server/shell/InvertedShellWrapper.java
    mina/sshd/trunk/sshd-core/src/test/java/org/apache/sshd/common/channel/ChannelPipedInputStreamTest.java

Modified: mina/sshd/trunk/sshd-core/src/main/java/org/apache/sshd/server/shell/InvertedShellWrapper.java
URL: http://svn.apache.org/viewvc/mina/sshd/trunk/sshd-core/src/main/java/org/apache/sshd/server/shell/InvertedShellWrapper.java?rev=1340435&r1=1340434&r2=1340435&view=diff
==============================================================================
--- mina/sshd/trunk/sshd-core/src/main/java/org/apache/sshd/server/shell/InvertedShellWrapper.java (original)
+++ mina/sshd/trunk/sshd-core/src/main/java/org/apache/sshd/server/shell/InvertedShellWrapper.java Sat May 19 12:35:27 2012
@@ -120,10 +120,6 @@ public class InvertedShellWrapper implem
             // check the error stream, or wait until more data is available.
             byte[] buffer = new byte[bufferSize];
             for (;;) {
-                if (!shell.isAlive()) {
-                    callback.onExit(shell.exitValue());
-                    return;
-                }
                 if (pumpStream(in, shellIn, buffer)) {
                     continue;
                 }
@@ -133,6 +129,10 @@ public class InvertedShellWrapper implem
                 if (pumpStream(shellErr, err, buffer)) {
                     continue;
                 }
+                if (!shell.isAlive()) {
+                    callback.onExit(shell.exitValue());
+                    return;
+                }
                 // Sleep a bit.  This is not very good, as it consumes CPU, but the
                 // input streams are not selectable for nio, and any other blocking
                 // method would consume at least two threads

Modified: mina/sshd/trunk/sshd-core/src/test/java/org/apache/sshd/common/channel/ChannelPipedInputStreamTest.java
URL: http://svn.apache.org/viewvc/mina/sshd/trunk/sshd-core/src/test/java/org/apache/sshd/common/channel/ChannelPipedInputStreamTest.java?rev=1340435&r1=1340434&r2=1340435&view=diff
==============================================================================
--- mina/sshd/trunk/sshd-core/src/test/java/org/apache/sshd/common/channel/ChannelPipedInputStreamTest.java (original)
+++ mina/sshd/trunk/sshd-core/src/test/java/org/apache/sshd/common/channel/ChannelPipedInputStreamTest.java Sat May 19 12:35:27 2012
@@ -1,11 +1,31 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
 package org.apache.sshd.common.channel;
 
+import java.util.Arrays;
+
 import org.apache.sshd.util.BogusChannel;
 import org.junit.Test;
 
-import java.util.Arrays;
-
-import static org.junit.Assert.*;
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
 
 public class ChannelPipedInputStreamTest {
 

Added: mina/sshd/trunk/sshd-core/src/test/java/org/apache/sshd/server/shell/InvertedShellWrapperTest.java
URL: http://svn.apache.org/viewvc/mina/sshd/trunk/sshd-core/src/test/java/org/apache/sshd/server/shell/InvertedShellWrapperTest.java?rev=1340435&view=auto
==============================================================================
--- mina/sshd/trunk/sshd-core/src/test/java/org/apache/sshd/server/shell/InvertedShellWrapperTest.java (added)
+++ mina/sshd/trunk/sshd-core/src/test/java/org/apache/sshd/server/shell/InvertedShellWrapperTest.java Sat May 19 12:35:27 2012
@@ -0,0 +1,63 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.sshd.server.shell;
+
+import org.apache.sshd.util.BogusEnvironment;
+import org.apache.sshd.util.BogusExitCallback;
+import org.apache.sshd.util.BogusInvertedShell;
+import org.junit.Test;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+
+import static junit.framework.Assert.assertEquals;
+
+public class InvertedShellWrapperTest {
+
+    @Test
+    public void testStreamsAreFlushedBeforeClosing() throws Exception {
+        BogusInvertedShell shell = newShell("out", "err");
+        shell.setAlive(false);
+        ByteArrayInputStream in = new ByteArrayInputStream("in".getBytes());
+        ByteArrayOutputStream out = new ByteArrayOutputStream(50);
+        ByteArrayOutputStream err = new ByteArrayOutputStream();
+
+        InvertedShellWrapper wrapper = new InvertedShellWrapper(shell);
+        wrapper.setInputStream(in);
+        wrapper.setOutputStream(out);
+        wrapper.setErrorStream(err);
+        wrapper.setExitCallback(new BogusExitCallback());
+        wrapper.start(new BogusEnvironment());
+
+        wrapper.pumpStreams();
+
+        // check the streams were flushed before exiting
+        assertEquals("in", shell.getInputStream().toString());
+        assertEquals("out", out.toString());
+        assertEquals("err", err.toString());
+    }
+
+    private BogusInvertedShell newShell(String contentOut, String contentErr) {
+        ByteArrayOutputStream in = new ByteArrayOutputStream(20);
+        ByteArrayInputStream out = new ByteArrayInputStream(contentOut.getBytes());
+        ByteArrayInputStream err = new ByteArrayInputStream(contentErr.getBytes());
+        return new BogusInvertedShell(in, out, err);
+    }
+
+}

Added: mina/sshd/trunk/sshd-core/src/test/java/org/apache/sshd/util/BogusEnvironment.java
URL: http://svn.apache.org/viewvc/mina/sshd/trunk/sshd-core/src/test/java/org/apache/sshd/util/BogusEnvironment.java?rev=1340435&view=auto
==============================================================================
--- mina/sshd/trunk/sshd-core/src/test/java/org/apache/sshd/util/BogusEnvironment.java (added)
+++ mina/sshd/trunk/sshd-core/src/test/java/org/apache/sshd/util/BogusEnvironment.java Sat May 19 12:35:27 2012
@@ -0,0 +1,52 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.sshd.util;
+
+import java.util.Collections;
+import java.util.EnumSet;
+import java.util.Map;
+
+import org.apache.sshd.common.PtyMode;
+import org.apache.sshd.server.Environment;
+import org.apache.sshd.server.Signal;
+import org.apache.sshd.server.SignalListener;
+
+public class BogusEnvironment implements Environment {
+
+    public Map<String, String> getEnv() {
+        return Collections.emptyMap();
+    }
+
+    public Map<PtyMode, Integer> getPtyModes() {
+        return Collections.emptyMap();
+    }
+
+    public void addSignalListener(SignalListener listener, Signal... signal) {
+    }
+
+    public void addSignalListener(SignalListener listener, EnumSet<Signal> signals) {
+    }
+
+    public void addSignalListener(SignalListener listener) {
+    }
+
+    public void removeSignalListener(SignalListener listener) {
+    }
+
+}

Added: mina/sshd/trunk/sshd-core/src/test/java/org/apache/sshd/util/BogusExitCallback.java
URL: http://svn.apache.org/viewvc/mina/sshd/trunk/sshd-core/src/test/java/org/apache/sshd/util/BogusExitCallback.java?rev=1340435&view=auto
==============================================================================
--- mina/sshd/trunk/sshd-core/src/test/java/org/apache/sshd/util/BogusExitCallback.java (added)
+++ mina/sshd/trunk/sshd-core/src/test/java/org/apache/sshd/util/BogusExitCallback.java Sat May 19 12:35:27 2012
@@ -0,0 +1,39 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.sshd.util;
+
+import org.apache.sshd.server.ExitCallback;
+
+public class BogusExitCallback implements ExitCallback {
+
+    private boolean exited;
+
+    public void onExit(int exitValue) {
+        this.exited = true;
+    }
+
+    public void onExit(int exitValue, String exitMessage) {
+        this.exited = true;
+    }
+
+    public boolean isExited() {
+        return exited;
+    }
+
+}

Added: mina/sshd/trunk/sshd-core/src/test/java/org/apache/sshd/util/BogusInvertedShell.java
URL: http://svn.apache.org/viewvc/mina/sshd/trunk/sshd-core/src/test/java/org/apache/sshd/util/BogusInvertedShell.java?rev=1340435&view=auto
==============================================================================
--- mina/sshd/trunk/sshd-core/src/test/java/org/apache/sshd/util/BogusInvertedShell.java (added)
+++ mina/sshd/trunk/sshd-core/src/test/java/org/apache/sshd/util/BogusInvertedShell.java Sat May 19 12:35:27 2012
@@ -0,0 +1,89 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.sshd.util;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.Collections;
+import java.util.Map;
+
+import org.apache.sshd.common.util.IoUtils;
+import org.apache.sshd.server.shell.InvertedShell;
+
+public class BogusInvertedShell implements InvertedShell {
+
+    private final OutputStream in;
+    private final InputStream out;
+    private final InputStream err;
+
+    // for test assertions
+    private boolean started = false;
+    private boolean alive = true;
+    private Map<String, String> env = null;
+
+    public BogusInvertedShell(OutputStream in, InputStream out, InputStream err) {
+        this.in = in;
+        this.out = out;
+        this.err = err;
+    }
+
+    public void start(Map<String, String> env) throws IOException {
+        this.started = true;
+        this.env = Collections.unmodifiableMap(env);
+    }
+
+    public OutputStream getInputStream() {
+        return in;
+    }
+
+    public InputStream getOutputStream() {
+        return out;
+    }
+
+    public InputStream getErrorStream() {
+        return err;
+    }
+
+    public boolean isAlive() {
+        return alive;
+    }
+
+    public int exitValue() {
+        return 0;
+    }
+
+    public void destroy() {
+        IoUtils.closeQuietly(in);
+        IoUtils.closeQuietly(out);
+        IoUtils.closeQuietly(err);
+    }
+
+    public boolean isStarted() {
+        return started;
+    }
+
+    public Map<String, String> getEnv() {
+        return env;
+    }
+
+    public void setAlive(boolean alive) {
+        this.alive = alive;
+    }
+}