[KARAF-2456] Shutdown is stuck after wrapper:install
Project: http://git-wip-us.apache.org/repos/asf/karaf/repo Commit: http://git-wip-us.apache.org/repos/asf/karaf/commit/e2047825 Tree: http://git-wip-us.apache.org/repos/asf/karaf/tree/e2047825 Diff: http://git-wip-us.apache.org/repos/asf/karaf/diff/e2047825 Branch: refs/heads/karaf-2.x Commit: e20478254ca153e7daf2f7bb144283ef71d95b6a Parents: 4275e6d Author: Guillaume Nodet <[email protected]> Authored: Thu Feb 26 08:44:04 2015 +0100 Committer: Guillaume Nodet <[email protected]> Committed: Thu Feb 26 11:41:57 2015 +0100 ---------------------------------------------------------------------- .../karaf/shell/wrapper/InstallCommand.java | 8 +- .../karaf/shell/wrapper/PumpStreamHandler.java | 241 ------------------- .../karaf/shell/wrapper/StreamPumper.java | 191 --------------- 3 files changed, 1 insertion(+), 439 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/karaf/blob/e2047825/shell/wrapper/src/main/java/org/apache/karaf/shell/wrapper/InstallCommand.java ---------------------------------------------------------------------- diff --git a/shell/wrapper/src/main/java/org/apache/karaf/shell/wrapper/InstallCommand.java b/shell/wrapper/src/main/java/org/apache/karaf/shell/wrapper/InstallCommand.java index 99af6c9..94c2473 100644 --- a/shell/wrapper/src/main/java/org/apache/karaf/shell/wrapper/InstallCommand.java +++ b/shell/wrapper/src/main/java/org/apache/karaf/shell/wrapper/InstallCommand.java @@ -392,13 +392,7 @@ public class InstallCommand extends AbstractAction { ProcessBuilder builder = new ProcessBuilder(); builder.command("chmod", mode, serviceFile.getCanonicalPath()); Process p = builder.start(); - - PumpStreamHandler handler = new PumpStreamHandler(System.in, System.out, System.err); - handler.attach(p); - handler.start(); - int status = p.waitFor(); - handler.stop(); - return status; + return p.waitFor(); } private void createJar(File outFile, String resource) throws Exception { http://git-wip-us.apache.org/repos/asf/karaf/blob/e2047825/shell/wrapper/src/main/java/org/apache/karaf/shell/wrapper/PumpStreamHandler.java ---------------------------------------------------------------------- diff --git a/shell/wrapper/src/main/java/org/apache/karaf/shell/wrapper/PumpStreamHandler.java b/shell/wrapper/src/main/java/org/apache/karaf/shell/wrapper/PumpStreamHandler.java deleted file mode 100644 index 80e64e1..0000000 --- a/shell/wrapper/src/main/java/org/apache/karaf/shell/wrapper/PumpStreamHandler.java +++ /dev/null @@ -1,241 +0,0 @@ -/* - * 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.karaf.shell.wrapper; - -import java.io.InputStream; -import java.io.OutputStream; -import java.io.IOException; - -/** - * Copies standard output and error of children streams to standard output and error of the parent. - */ -public class PumpStreamHandler { - - private final InputStream in; - - private final OutputStream out; - - private final OutputStream err; - - private final String name; - - private StreamPumper outputPump; - - private StreamPumper errorPump; - - private StreamPumper inputPump; - - // - // NOTE: May want to use a ThreadPool here, 3 threads per/pair seems kinda expensive :-( - // - - public PumpStreamHandler(final InputStream in, final OutputStream out, final OutputStream err, String name) { - assert in != null; - assert out != null; - assert err != null; - assert name != null; - - this.in = in; - this.out = out; - this.err = err; - this.name = name; - } - - public PumpStreamHandler(final InputStream in, final OutputStream out, final OutputStream err) { - this(in, out, err, "<unknown>"); - } - - public PumpStreamHandler(final OutputStream out, final OutputStream err) { - this(null, out, err); - } - - public PumpStreamHandler(final OutputStream outAndErr) { - this(outAndErr, outAndErr); - } - - /** - * Set the input stream from which to read the standard output of the child. - */ - public void setChildOutputStream(final InputStream in) { - assert in != null; - - createChildOutputPump(in, out); - } - - /** - * Set the input stream from which to read the standard error of the child. - */ - public void setChildErrorStream(final InputStream in) { - assert in != null; - - if (err != null) { - createChildErrorPump(in, err); - } - } - - /** - * Set the output stream by means of which input can be sent to the child. - */ - public void setChildInputStream(final OutputStream out) { - assert out != null; - - if (in != null) { - inputPump = createInputPump(in, out, true); - } - else { - try { - out.close(); - } catch (IOException e) { } - } - } - - /** - * Attach to a child streams from the given process. - * - * @param p The process to attach to. - */ - public void attach(final Process p) { - assert p != null; - - setChildInputStream(p.getOutputStream()); - setChildOutputStream(p.getInputStream()); - setChildErrorStream(p.getErrorStream()); - } - /** - * Start pumping the streams. - */ - public void start() { - if (outputPump != null) { - Thread thread = new Thread(outputPump); - thread.setDaemon(true); - thread.setName("Output pump for " + this.name); - thread.start(); - } - - if (errorPump != null) { - Thread thread = new Thread(errorPump); - thread.setDaemon(true); - thread.setName("Error pump for " + this.name); - thread.start(); - } - - if (inputPump != null) { - Thread thread = new Thread(inputPump); - thread.setDaemon(true); - thread.setName("Input pump for " + this.name); - thread.start(); - } - } - - /** - * Stop pumping the streams. - */ - public void stop() { - if (outputPump != null) { - try { - outputPump.stop(); - outputPump.waitFor(); - } - catch (InterruptedException e) { - // ignore - } - } - - if (errorPump != null) { - try { - errorPump.stop(); - errorPump.waitFor(); - } - catch (InterruptedException e) { - // ignore - } - } - - if (inputPump != null) { - inputPump.stop(); - } - - try { - err.flush(); - } catch (IOException e) { } - try { - out.flush(); - } catch (IOException e) { } - } - - /** - * Create the pump to handle child output. - */ - protected void createChildOutputPump(final InputStream in, final OutputStream out) { - assert in != null; - assert out != null; - - outputPump = createPump(in, out); - } - - /** - * Create the pump to handle error output. - */ - protected void createChildErrorPump(final InputStream in, final OutputStream out) { - assert in != null; - assert out != null; - - errorPump = createPump(in, out); - } - - /** - * Creates a stream pumper to copy the given input stream to the given output stream. - */ - protected StreamPumper createPump(final InputStream in, final OutputStream out) { - assert in != null; - assert out != null; - - return createPump(in, out, false); - } - - /** - * Creates a stream pumper to copy the given input stream to the - * given output stream. - * - * @param in The input stream to copy from. - * @param out The output stream to copy to. - * @param closeWhenExhausted If true close the inputstream. - * @return A thread object that does the pumping. - */ - protected StreamPumper createPump(final InputStream in, final OutputStream out, final boolean closeWhenExhausted) { - assert in != null; - assert out != null; - - StreamPumper pumper = new StreamPumper(in, out, closeWhenExhausted); - return pumper; - } - - /** - * Creates a stream pumper to copy the given input stream to the - * given output stream. Used for standard input. - */ - protected StreamPumper createInputPump(final InputStream in, final OutputStream out, final boolean closeWhenExhausted) { - assert in != null; - assert out != null; - - StreamPumper pumper = new StreamPumper(in, out, closeWhenExhausted); - pumper.setAutoflush(true); - return pumper; - } -} http://git-wip-us.apache.org/repos/asf/karaf/blob/e2047825/shell/wrapper/src/main/java/org/apache/karaf/shell/wrapper/StreamPumper.java ---------------------------------------------------------------------- diff --git a/shell/wrapper/src/main/java/org/apache/karaf/shell/wrapper/StreamPumper.java b/shell/wrapper/src/main/java/org/apache/karaf/shell/wrapper/StreamPumper.java deleted file mode 100644 index e4e26a4..0000000 --- a/shell/wrapper/src/main/java/org/apache/karaf/shell/wrapper/StreamPumper.java +++ /dev/null @@ -1,191 +0,0 @@ -/* - * 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.karaf.shell.wrapper; - -import java.io.InputStream; -import java.io.OutputStream; -import java.io.IOException; - -/** - * Copies all data from an input stream to an output stream. - */ -public class StreamPumper implements Runnable { - - private InputStream in; - - private OutputStream out; - - private volatile boolean finish; - - private volatile boolean finished; - - private boolean closeWhenExhausted; - - private boolean autoflush; - - private Exception exception; - - private int bufferSize = 128; - - private boolean started; - - /** - * Create a new stream pumper. - * - * @param in Input stream to read data from - * @param out Output stream to write data to. - * @param closeWhenExhausted If true, the output stream will be closed when - * the input is exhausted. - */ - public StreamPumper(final InputStream in, final OutputStream out, final boolean closeWhenExhausted) { - assert in != null; - assert out != null; - - this.in = in; - this.out = out; - this.closeWhenExhausted = closeWhenExhausted; - } - - /** - * Create a new stream pumper. - * - * @param in Input stream to read data from - * @param out Output stream to write data to. - */ - public StreamPumper(final InputStream in, final OutputStream out) { - this(in, out, false); - } - - /** - * Set whether data should be flushed through to the output stream. - * - * @param autoflush If true, push through data; if false, let it be buffered - */ - public void setAutoflush(boolean autoflush) { - this.autoflush = autoflush; - } - - /** - * Copies data from the input stream to the output stream. - * - * Terminates as soon as the input stream is closed or an error occurs. - */ - public void run() { - synchronized (this) { - started = true; - } - finished = false; - finish = false; - - final byte[] buf = new byte[bufferSize]; - - int length; - try { - while ((length = in.read(buf)) > 0 && !finish) { - out.write(buf, 0, length); - if (autoflush) { - out.flush(); - } - } - out.flush(); - } - catch (Exception e) { - synchronized (this) { - exception = e; - } - } - finally { - if (closeWhenExhausted) { - try { - out.close(); - } catch (IOException e) { } - } - finished = true; - - synchronized (this) { - notifyAll(); - } - } - } - - /** - * Tells whether the end of the stream has been reached. - * - * @return true If the stream has been exhausted. - */ - public boolean isFinished() { - return finished; - } - - /** - * This method blocks until the stream pumper finishes. - * - * @see #isFinished() - */ - public synchronized void waitFor() throws InterruptedException { - while (!isFinished()) { - wait(); - } - } - - /** - * Set the size in bytes of the read buffer. - * - * @param bufferSize the buffer size to use. - * @throws IllegalStateException if the StreamPumper is already running. - */ - public synchronized void setBufferSize(final int bufferSize) { - if (started) { - throw new IllegalStateException("Cannot set buffer size on a running StreamPumper"); - } - - this.bufferSize = bufferSize; - } - - /** - * Get the size in bytes of the read buffer. - * - * @return The size of the read buffer. - */ - public synchronized int getBufferSize() { - return bufferSize; - } - - /** - * Get the exception encountered, if any. - * - * @return The Exception encountered; or null if there was none. - */ - public synchronized Exception getException() { - return exception; - } - - /** - * Stop the pumper as soon as possible. - * - * Note that it may continue to block on the input stream - * but it will really stop the thread as soon as it gets EOF - * or any byte, and it will be marked as finished. - */ - public synchronized void stop() { - finish = true; - - notifyAll(); - } -}
