Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJeff Johnston2017-08-22 00:01:10 +0000
committerJeff Johnston2017-08-22 02:32:36 +0000
commit2519e6966422bf0ff346ad02c1abf196f95e9bea (patch)
treed66f5fd3d584f9a0f0b87598b8c3d7d5ae71b8fe
parented0f26c313623f0b3dcf32c15bb9c2965e7ece8c (diff)
downloadorg.eclipse.linuxtools-2519e6966422bf0ff346ad02c1abf196f95e9bea.tar.gz
org.eclipse.linuxtools-2519e6966422bf0ff346ad02c1abf196f95e9bea.tar.xz
org.eclipse.linuxtools-2519e6966422bf0ff346ad02c1abf196f95e9bea.zip
Bug 521211 - Docker launch fails debugging some C/C++ programs
- using normal logging doesn't always work when debugging via gdbserver (e.g. a program that printfs without a newline and then uses an fflush of stdout) - add a new DockerConsoleOutputStream class to core that will accept listeners that will be notified whenever writes are made - change openTerminal method in DockerConnection to accept a DockerConsoleOutputStream as input parameter and to use this to echo stdout and stderr output of the terminal - change RunConsole.attachTerminal method to accept a DockerConsoleOutputStream argument - change ContainerLauncher launch method to determine when called to do a gdbserver launch from CDT (look at ContainerListener class name) - when it is determined that we are doing a gdbserver launch, set the TTY option on and pass a DockerConsoleOutput stream to RunConsole.attachTerminal which will pass this on to openTerminal - set up the DockerConsoleOutputStream to echo output to the normal RunConsole used for running and debugging - when the session is complete, remove any Terminal that was created on behalf of the session - change all callers of RunConsole.attachTerminal appropriately to pass null as last argument - remove ConsoleOutputStream from docker ui Change-Id: I17758f1ed9f0af6df754af88570cc4b7767c9638 Reviewed-on: https://git.eclipse.org/r/103419 Tested-by: Hudson CI Reviewed-by: Jeff Johnston <jjohnstn@redhat.com> (cherry picked from commit 659a766ff264ff53f8a72026fa753f39fc35f6f8) Reviewed-on: https://git.eclipse.org/r/103420
-rw-r--r--containers/org.eclipse.linuxtools.docker.core/src/org/eclipse/linuxtools/internal/docker/core/DockerConnection.java49
-rw-r--r--containers/org.eclipse.linuxtools.docker.core/src/org/eclipse/linuxtools/internal/docker/core/DockerConsoleOutputStream.java103
-rw-r--r--containers/org.eclipse.linuxtools.docker.core/src/org/eclipse/linuxtools/internal/docker/core/IConsoleListener.java23
-rw-r--r--containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/docker/ui/launch/ContainerLauncher.java251
-rw-r--r--containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/commands/CommandUtils.java2
-rw-r--r--containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/commands/DisplayContainerLogCommandHandler.java2
-rw-r--r--containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/consoles/RunConsole.java9
-rw-r--r--containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/launch/ContainerCommandProcess.java37
8 files changed, 397 insertions, 79 deletions
diff --git a/containers/org.eclipse.linuxtools.docker.core/src/org/eclipse/linuxtools/internal/docker/core/DockerConnection.java b/containers/org.eclipse.linuxtools.docker.core/src/org/eclipse/linuxtools/internal/docker/core/DockerConnection.java
index 4831fe9435..e8eaaae7eb 100644
--- a/containers/org.eclipse.linuxtools.docker.core/src/org/eclipse/linuxtools/internal/docker/core/DockerConnection.java
+++ b/containers/org.eclipse.linuxtools.docker.core/src/org/eclipse/linuxtools/internal/docker/core/DockerConnection.java
@@ -89,6 +89,7 @@ import org.eclipse.linuxtools.internal.docker.core.DockerImage.DockerImageQualif
import org.eclipse.osgi.util.NLS;
import org.eclipse.tm.terminal.view.core.TerminalServiceFactory;
import org.eclipse.tm.terminal.view.core.interfaces.ITerminalService;
+import org.eclipse.tm.terminal.view.core.interfaces.ITerminalServiceOutputStreamMonitorListener;
import org.eclipse.tm.terminal.view.core.interfaces.constants.ITerminalsConnectorConstants;
import com.google.common.collect.ImmutableMap;
@@ -581,6 +582,7 @@ public class DockerConnection
getContainers(force);
} catch (DockerException e) {
Activator.log(e);
+ return Collections.emptyList();
}
} else if (!isContainersLoaded() || force) {
@@ -984,6 +986,7 @@ public class DockerConnection
latestImages = getImages(force);
} catch (DockerException e) {
Activator.log(e);
+ return Collections.emptyList();
}
} else if (!isImagesLoaded() || force) {
try {
@@ -1933,7 +1936,6 @@ public class DockerConnection
Activator.log(e);
}
}
-
}
@Override
@@ -2007,7 +2009,7 @@ public class DockerConnection
}
public void attachCommand(final String id, final InputStream in,
- @SuppressWarnings("unused") final OutputStream out)
+ @SuppressWarnings("unused") final DockerConsoleOutputStream out)
throws DockerException {
final byte[] prevCmd = new byte[1024];
@@ -2021,7 +2023,7 @@ public class DockerConnection
final boolean isOpenStdin = info.config().openStdin();
if (isTtyEnabled) {
- openTerminal(pty_stream, info.name());
+ openTerminal(pty_stream, info.name(), out);
}
// Data from the given input stream
@@ -2130,16 +2132,43 @@ public class DockerConnection
final LogStream pty_stream = client.execStart(execId,
DockerClient.ExecStartParameter.TTY);
final IDockerContainerInfo info = getContainerInfo(id);
- openTerminal(pty_stream, info.name() + " [shell]"); //$NON-NLS-1$
+ openTerminal(pty_stream, info.name() + " [shell]", null); //$NON-NLS-1$
} catch (Exception e) {
throw new DockerException(e.getMessage(), e.getCause());
}
}
- private void openTerminal(LogStream pty_stream, String name) throws DockerException {
+ private class TerminalOutputMonitorListener
+ implements ITerminalServiceOutputStreamMonitorListener {
+
+ private DockerConsoleOutputStream consoleOutputStream;
+
+ public TerminalOutputMonitorListener(DockerConsoleOutputStream out) {
+ this.consoleOutputStream = out;
+ }
+
+ @Override
+ public void onContentReadFromStream(byte[] byteBuffer, int bytesRead) {
+ try {
+ if (consoleOutputStream != null) {
+ consoleOutputStream.write(byteBuffer, 0, bytesRead);
+ }
+ } catch (IOException e) {
+ Activator.log(e);
+ }
+ }
+
+ }
+
+ private void openTerminal(LogStream pty_stream, String name,
+ DockerConsoleOutputStream out) throws DockerException {
try {
- OutputStream tout = noBlockingOutputStream(HttpHijackWorkaround.getOutputStream(pty_stream, getUri()));
+ OutputStream tout = noBlockingOutputStream(
+ HttpHijackWorkaround.getOutputStream(pty_stream, getUri()));
InputStream tin = HttpHijackWorkaround.getInputStream(pty_stream);
+
+ TerminalOutputMonitorListener monitor = new TerminalOutputMonitorListener(out);
+
// org.eclipse.tm.terminal.connector.ssh.controls.SshWizardConfigurationPanel
Map<String, Object> properties = new HashMap<>();
properties.put(ITerminalsConnectorConstants.PROP_DELEGATE_ID,
@@ -2152,6 +2181,10 @@ public class DockerConnection
properties.put(ITerminalsConnectorConstants.PROP_FORCE_NEW, true);
properties.put(ITerminalsConnectorConstants.PROP_STREAMS_STDIN, tout);
properties.put(ITerminalsConnectorConstants.PROP_STREAMS_STDOUT, tin);
+ properties.put(ITerminalsConnectorConstants.PROP_STDERR_LISTENERS, new ITerminalServiceOutputStreamMonitorListener[] {monitor});
+ properties.put(ITerminalsConnectorConstants.PROP_STDOUT_LISTENERS,
+ new ITerminalServiceOutputStreamMonitorListener[] {
+ monitor });
properties.put(ITerminalsConnectorConstants.PROP_DATA, pty_stream);
/*
* The JVM will call finalize() on 'pty_stream' (LogStream)
@@ -2161,6 +2194,10 @@ public class DockerConnection
* used so we must preserve a reference to it.
*/
properties.put("PREVENT_JVM_GC_FINALIZE", pty_stream); //$NON-NLS-1$
+ // save properties to remove terminal later
+ if (out != null) {
+ out.setTerminalProperties(properties);
+ }
ITerminalService service = TerminalServiceFactory.getService();
service.openConsole(properties, null);
} catch (Exception e) {
diff --git a/containers/org.eclipse.linuxtools.docker.core/src/org/eclipse/linuxtools/internal/docker/core/DockerConsoleOutputStream.java b/containers/org.eclipse.linuxtools.docker.core/src/org/eclipse/linuxtools/internal/docker/core/DockerConsoleOutputStream.java
new file mode 100644
index 0000000000..e2c1d27f5d
--- /dev/null
+++ b/containers/org.eclipse.linuxtools.docker.core/src/org/eclipse/linuxtools/internal/docker/core/DockerConsoleOutputStream.java
@@ -0,0 +1,103 @@
+/*******************************************************************************
+ * Copyright (c) 2015, 2016 Red Hat.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Red Hat - Initial Contribution
+ *******************************************************************************/
+package org.eclipse.linuxtools.internal.docker.core;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.Map;
+
+import org.eclipse.core.runtime.ListenerList;
+
+// Special Console OutputStream which supports listeners.
+
+public class DockerConsoleOutputStream extends OutputStream {
+
+ private OutputStream stream;
+ private Map<String, Object> properties;
+
+ ListenerList<IConsoleListener> consoleListeners;
+
+ public DockerConsoleOutputStream(OutputStream stream) {
+ this.stream = stream;
+ }
+
+ public DockerConsoleOutputStream setOutputStream(OutputStream stream) {
+ this.stream = stream;
+ return this;
+ }
+
+ public void setTerminalProperties(Map<String, Object> properties) {
+ this.properties = properties;
+ }
+
+ public Map<String, Object> getTerminalProperties() {
+ return properties;
+ }
+
+ @Override
+ public void write(byte[] b) throws IOException {
+ if (stream != null) {
+ stream.write(b);
+ }
+ notifyConsoleListeners(b, 0, b.length);
+ }
+
+ @Override
+ public void write(byte[] b, int off, int len) throws IOException {
+ if (stream != null) {
+ stream.write(b, off, len);
+ }
+ notifyConsoleListeners(b, off, len);
+ }
+
+ @Override
+ public void write(int arg0) throws IOException {
+ byte[] b = new byte[1];
+ b[0] = (byte) arg0;
+ write(b);
+ }
+
+ @Override
+ public void close() throws IOException {
+ if (stream != null) {
+ stream.close();
+ }
+ }
+
+ @Override
+ public void flush() throws IOException {
+ if (stream != null) {
+ stream.flush();
+ }
+ }
+
+ public void addConsoleListener(IConsoleListener listener) {
+ if (consoleListeners == null)
+ consoleListeners = new ListenerList<>(ListenerList.IDENTITY);
+ consoleListeners.add(listener);
+ }
+
+ public void removeConsoleListener(IConsoleListener listener) {
+ if (consoleListeners != null)
+ consoleListeners.remove(listener);
+ }
+
+ public void notifyConsoleListeners(byte[] b, int off, int len) {
+ if (consoleListeners != null) {
+ String output = new String(b, off, len);
+ Object[] listeners = consoleListeners.getListeners();
+ for (int i = 0; i < listeners.length; ++i) {
+ ((IConsoleListener) listeners[i]).newOutput(output);
+ }
+ }
+ }
+
+}
diff --git a/containers/org.eclipse.linuxtools.docker.core/src/org/eclipse/linuxtools/internal/docker/core/IConsoleListener.java b/containers/org.eclipse.linuxtools.docker.core/src/org/eclipse/linuxtools/internal/docker/core/IConsoleListener.java
new file mode 100644
index 0000000000..2b3cff95d4
--- /dev/null
+++ b/containers/org.eclipse.linuxtools.docker.core/src/org/eclipse/linuxtools/internal/docker/core/IConsoleListener.java
@@ -0,0 +1,23 @@
+/*******************************************************************************
+ * Copyright (c) 2015, 2016 Red Hat.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Red Hat - Initial Contribution
+ *******************************************************************************/
+package org.eclipse.linuxtools.internal.docker.core;
+
+public interface IConsoleListener {
+
+ /**
+ * Listener receiver method called after output is written to Console.
+ *
+ * @param output
+ * string written to console
+ */
+ void newOutput(String output);
+
+}
diff --git a/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/docker/ui/launch/ContainerLauncher.java b/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/docker/ui/launch/ContainerLauncher.java
index c5ea7e0fff..cc745da3fe 100644
--- a/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/docker/ui/launch/ContainerLauncher.java
+++ b/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/docker/ui/launch/ContainerLauncher.java
@@ -48,7 +48,6 @@ import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.linuxtools.docker.core.DockerConnectionManager;
import org.eclipse.linuxtools.docker.core.DockerException;
-import org.eclipse.linuxtools.docker.core.EnumDockerLoggingStatus;
import org.eclipse.linuxtools.docker.core.IDockerConnection;
import org.eclipse.linuxtools.docker.core.IDockerContainerConfig;
import org.eclipse.linuxtools.docker.core.IDockerContainerExit;
@@ -59,16 +58,22 @@ import org.eclipse.linuxtools.docker.core.IDockerImageInfo;
import org.eclipse.linuxtools.docker.core.IDockerPortBinding;
import org.eclipse.linuxtools.docker.ui.Activator;
import org.eclipse.linuxtools.internal.docker.core.DockerConnection;
+import org.eclipse.linuxtools.internal.docker.core.DockerConsoleOutputStream;
import org.eclipse.linuxtools.internal.docker.core.DockerContainerConfig;
import org.eclipse.linuxtools.internal.docker.core.DockerHostConfig;
import org.eclipse.linuxtools.internal.docker.core.DockerPortBinding;
+import org.eclipse.linuxtools.internal.docker.core.IConsoleListener;
import org.eclipse.linuxtools.internal.docker.ui.consoles.ConsoleOutputStream;
import org.eclipse.linuxtools.internal.docker.ui.consoles.RunConsole;
import org.eclipse.linuxtools.internal.docker.ui.launch.ContainerCommandProcess;
import org.eclipse.linuxtools.internal.docker.ui.launch.LaunchConfigurationUtils;
import org.eclipse.linuxtools.internal.docker.ui.views.DVMessages;
import org.eclipse.linuxtools.internal.docker.ui.wizards.DataVolumeModel;
+import org.eclipse.swt.custom.CTabFolder;
+import org.eclipse.swt.custom.CTabItem;
import org.eclipse.swt.widgets.Display;
+import org.eclipse.ui.IViewPart;
+import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.PlatformUI;
public class ContainerLauncher {
@@ -545,6 +550,25 @@ public class ContainerLauncher {
}
+ // The following class allows us to use internal IConsoleListeners in
+ // docker.core
+ // but still use the public IRunConsoleListeners API here without requiring
+ // a minor release.
+ private class RunConsoleListenerBridge implements IConsoleListener {
+
+ private IRunConsoleListener listener;
+
+ public RunConsoleListenerBridge(IRunConsoleListener listener) {
+ this.listener = listener;
+ }
+
+ @Override
+ public void newOutput(String output) {
+ listener.newOutput(output);
+ }
+
+ }
+
/**
* Perform a launch of a command in a container and output stdout/stderr to
* console.
@@ -652,6 +676,17 @@ public class ContainerLauncher {
.cmd(cmdList)
.image(image)
.workingDir(workingDir);
+
+ // Ugly hack...we want CDT gdbserver to run in the terminal so we look
+ // for its
+ // ContainerListener class and set tty=true in that case...this avoids a
+ // minor release and we can later add a new launch method with the tty
+ // option
+ if (listener != null && listener.getClass().getName().equals(
+ "org.eclipse.cdt.internal.docker.launcher.ContainerLaunchConfigurationDelegate$StartGdbServerJob")) {
+ builder = builder.tty(true);
+ }
+
// add any exposed ports as needed
if (exposedPorts.size() > 0)
builder = builder.exposedPorts(exposedPorts);
@@ -776,77 +811,163 @@ public class ContainerLauncher {
return;
}
}
- OutputStream stream = null;
- RunConsole oldConsole = getConsole();
- final RunConsole rc = RunConsole.findConsole(containerId,
- consoleId);
- setConsole(rc);
- rc.clearConsole();
- if (oldConsole != null)
- RunConsole.removeConsole(oldConsole);
- Display.getDefault()
- .syncExec(() -> rc.setTitle(Messages.getFormattedString(
- LAUNCH_TITLE, new String[] { cmdList.get(0),
- imageName })));
- // if (!rc.isAttached()) {
- rc.attachToConsole(connection, containerId);
- // }
- if (rc != null) {
- stream = rc.getOutputStream();
+ if (config.tty()) {
+ // We need tty support to handle issue with Docker daemon
+ // not always outputting in time (e.g. we might get an
+ // output line after the process has exited which can be
+ // too late to show or it might get displayed in a wrong
+ // order in relation to other output. We also want the
+ // output to ultimately show up in the Console View.
+ OutputStream stream = null;
+ RunConsole oldConsole = getConsole();
+ final RunConsole rc = RunConsole.findConsole(containerId,
+ consoleId);
+ setConsole(rc);
+ rc.clearConsole();
+ if (oldConsole != null)
+ RunConsole.removeConsole(oldConsole);
+ Display.getDefault().syncExec(() -> rc.setTitle(Messages
+ .getFormattedString(LAUNCH_TITLE, new String[] {
+ cmdList.get(0), imageName })));
+ if (rc != null) {
+ stream = rc.getOutputStream();
+ }
+
+ // We want terminal support, but we want to output to the
+ // RunConsole.
+ // To do this, we create a DockerConsoleOutputStream which
+ // we
+ // hook into the TM Terminal via stdout and stderr output
+ // listeners.
+ // These listeners will output to the
+ // DockerConsoleOutputStream which
+ // will in turn output to the RunConsole. See
+ // DockerConnection.openTerminal().
+ DockerConsoleOutputStream out = new DockerConsoleOutputStream(
+ stream);
+ RunConsole.attachToTerminal(connection, containerId, out);
if (containerListener != null) {
- ((ConsoleOutputStream) stream)
- .addConsoleListener(containerListener);
+ out.addConsoleListener(new RunConsoleListenerBridge(
+ containerListener));
}
- }
- // Create a unique logging thread id which has container id
- // and console id
- String loggingId = containerId + "." + consoleId;
- ((DockerConnection) connection).startContainer(containerId,
- loggingId, stream);
- if (rc != null)
- rc.showConsole();
- if (containerListener != null) {
+ ((DockerConnection) connection).startContainer(containerId,
+ null, null);
IDockerContainerInfo info = ((DockerConnection) connection)
.getContainerInfo(containerId);
- containerListener.containerInfo(info);
- }
+ if (containerListener != null) {
+ containerListener.containerInfo(info);
+ }
+ // Wait for the container to finish
+ final IDockerContainerExit status = ((DockerConnection) connection)
+ .waitForContainer(containerId);
+ Display.getDefault().syncExec(() -> {
+ rc.setTitle(
+ Messages.getFormattedString(LAUNCH_EXITED_TITLE,
+ new String[] {
+ status.statusCode().toString(),
+ cmdList.get(0), imageName }));
+ rc.showConsole();
+ // We used a TM Terminal to receive the output of the
+ // session and
+ // then sent the output to the RunConsole. Remove the
+ // terminal
+ // tab that got created now that we are finished and all
+ // data is shown
+ // in Console View.
+ IWorkbenchPage page = PlatformUI.getWorkbench()
+ .getActiveWorkbenchWindow().getActivePage();
+ IViewPart terminalView = page.findView(
+ "org.eclipse.tm.terminal.view.ui.TerminalsView");
+ CTabFolder ctabfolder = terminalView
+ .getAdapter(CTabFolder.class);
+ if (ctabfolder != null) {
+ CTabItem[] items = ctabfolder.getItems();
+ for (CTabItem item : items) {
+ if (item.getText().endsWith(info.name())) {
+ item.dispose();
+ break;
+ }
+ }
+ }
+ });
+ // Let any container listener know that the container is
+ // finished
+ if (containerListener != null)
+ containerListener.done();
+
+ if (!keepContainer) {
+ ((DockerConnection) connection)
+ .removeContainer(containerId);
+ }
+ } else {
+ OutputStream stream = null;
+ RunConsole oldConsole = getConsole();
+ final RunConsole rc = RunConsole.findConsole(containerId,
+ consoleId);
+ setConsole(rc);
+ rc.clearConsole();
+ if (oldConsole != null)
+ RunConsole.removeConsole(oldConsole);
+ Display.getDefault().syncExec(() -> rc.setTitle(Messages
+ .getFormattedString(LAUNCH_TITLE, new String[] {
+ cmdList.get(0), imageName })));
+ // if (!rc.isAttached()) {
+ rc.attachToConsole(connection, containerId);
+ // }
+ if (rc != null) {
+ stream = rc.getOutputStream();
+ if (containerListener != null) {
+ ((ConsoleOutputStream) stream)
+ .addConsoleListener(containerListener);
+ }
+ }
+ // Create a unique logging thread id which has container id
+ // and console id
+ String loggingId = containerId + "." + consoleId;
+ ((DockerConnection) connection).startContainer(containerId,
+ loggingId, stream);
+ if (rc != null)
+ rc.showConsole();
+ if (containerListener != null) {
+ IDockerContainerInfo info = ((DockerConnection) connection)
+ .getContainerInfo(containerId);
+ containerListener.containerInfo(info);
+ }
- // Wait for the container to finish
- final IDockerContainerExit status = ((DockerConnection) connection)
- .waitForContainer(containerId);
- Display.getDefault().syncExec(() -> {
- rc.setTitle(
- Messages.getFormattedString(LAUNCH_EXITED_TITLE,
- new String[] {
- status.statusCode().toString(),
- cmdList.get(0), imageName }));
- rc.showConsole();
- });
-
- // Let any container listener know that the container is
- // finished
- if (containerListener != null)
- containerListener.done();
-
- if (!keepContainer) {
- // Drain the logging thread before we remove the
- // container (we need to use the logging id)
- ((DockerConnection) connection)
- .stopLoggingThread(loggingId);
- while (((DockerConnection) connection).loggingStatus(
- loggingId) == EnumDockerLoggingStatus.LOGGING_ACTIVE) {
+ // Wait for the container to finish
+ final IDockerContainerExit status = ((DockerConnection) connection)
+ .waitForContainer(containerId);
+ Display.getDefault().syncExec(() -> {
+ rc.setTitle(
+ Messages.getFormattedString(LAUNCH_EXITED_TITLE,
+ new String[] {
+ status.statusCode().toString(),
+ cmdList.get(0), imageName }));
+ rc.showConsole();
+ });
+
+ // Let any container listener know that the container is
+ // finished
+ if (containerListener != null)
+ containerListener.done();
+
+ if (!keepContainer) {
+ // Drain the logging thread before we remove the
+ // container (we need to use the logging id)
Thread.sleep(1000);
+ ((DockerConnection) connection)
+ .stopLoggingThread(loggingId);
+ // Look for any Display Log console that the user may
+ // have opened which would be
+ // separate and make sure it is removed as well
+ RunConsole rc2 = RunConsole
+ .findConsole(((DockerConnection) connection)
+ .getContainer(containerId));
+ if (rc2 != null)
+ RunConsole.removeConsole(rc2);
+ ((DockerConnection) connection)
+ .removeContainer(containerId);
}
- // Look for any Display Log console that the user may
- // have opened which would be
- // separate and make sure it is removed as well
- RunConsole rc2 = RunConsole
- .findConsole(((DockerConnection) connection)
- .getContainer(containerId));
- if (rc2 != null)
- RunConsole.removeConsole(rc2);
- ((DockerConnection) connection)
- .removeContainer(containerId);
}
} catch (final DockerException e2) {
diff --git a/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/commands/CommandUtils.java b/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/commands/CommandUtils.java
index d1e0f3a8cd..d1fcdc2a86 100644
--- a/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/commands/CommandUtils.java
+++ b/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/commands/CommandUtils.java
@@ -268,7 +268,7 @@ public class CommandUtils {
&& connection.getContainerInfo(container.id()) != null
&& connection.getContainerInfo(container.id()).config() != null
&& connection.getContainerInfo(container.id()).config().tty()) {
- RunConsole.attachToTerminal(connection, container.id());
+ RunConsole.attachToTerminal(connection, container.id(), null);
return null;
}
final boolean autoLogOnStart = Activator.getDefault().getPreferenceStore()
diff --git a/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/commands/DisplayContainerLogCommandHandler.java b/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/commands/DisplayContainerLogCommandHandler.java
index 0192e328eb..a8f9b2450b 100644
--- a/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/commands/DisplayContainerLogCommandHandler.java
+++ b/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/commands/DisplayContainerLogCommandHandler.java
@@ -49,7 +49,7 @@ public class DisplayContainerLogCommandHandler extends AbstractHandler {
final String name = container.name();
if (connection.getContainerInfo(id).config().tty()) {
- RunConsole.attachToTerminal(connection, id);
+ RunConsole.attachToTerminal(connection, id, null);
return null;
}
try {
diff --git a/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/consoles/RunConsole.java b/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/consoles/RunConsole.java
index 4a240483c0..116acaabcc 100644
--- a/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/consoles/RunConsole.java
+++ b/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/consoles/RunConsole.java
@@ -19,6 +19,7 @@ import org.eclipse.linuxtools.docker.core.IDockerConnection;
import org.eclipse.linuxtools.docker.core.IDockerContainer;
import org.eclipse.linuxtools.docker.core.IDockerContainerState;
import org.eclipse.linuxtools.internal.docker.core.DockerConnection;
+import org.eclipse.linuxtools.internal.docker.core.DockerConsoleOutputStream;
import org.eclipse.linuxtools.internal.docker.ui.views.DVMessages;
import org.eclipse.ui.console.ConsolePlugin;
import org.eclipse.ui.console.IConsole;
@@ -142,7 +143,6 @@ public class RunConsole extends IOConsole {
*/
public void attachToConsole(final IDockerConnection connection) {
final InputStream in = getInputStream();
- final OutputStream out = newOutputStream();
Thread t = new Thread(() -> {
try {
DockerConnection conn = (DockerConnection) connection;
@@ -155,7 +155,7 @@ public class RunConsole extends IOConsole {
}
state = conn.getContainerInfo(containerId).state();
} while (!state.running() && state.finishDate() == null);
- conn.attachCommand(containerId, in, out);
+ conn.attachCommand(containerId, in, null);
}
} catch (Exception e) {
}
@@ -164,7 +164,8 @@ public class RunConsole extends IOConsole {
attached = true;
}
- public static void attachToTerminal (final IDockerConnection connection, final String containerId) {
+ public static void attachToTerminal(final IDockerConnection connection,
+ final String containerId, final DockerConsoleOutputStream out) {
Thread t = new Thread(() -> {
try {
DockerConnection conn = (DockerConnection) connection;
@@ -176,7 +177,7 @@ public class RunConsole extends IOConsole {
}
state = conn.getContainerInfo(containerId).state();
} while (!state.running() && state.finishDate() == null);
- conn.attachCommand(containerId, null, null);
+ conn.attachCommand(containerId, null, out);
} catch (Exception e) {
}
});
diff --git a/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/launch/ContainerCommandProcess.java b/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/launch/ContainerCommandProcess.java
index 4797187576..f58778edb7 100644
--- a/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/launch/ContainerCommandProcess.java
+++ b/containers/org.eclipse.linuxtools.docker.ui/src/org/eclipse/linuxtools/internal/docker/ui/launch/ContainerCommandProcess.java
@@ -65,14 +65,32 @@ public class ContainerCommandProcess extends Process {
this.keepContainer = keepContainer;
// Lambda Runnable
Runnable logContainer = () -> {
+ PipedOutputStream pipedOut = null;
+ PipedOutputStream pipedErr = null;
try (PipedOutputStream pipedStdout = new PipedOutputStream(stdout);
PipedOutputStream pipedStderr = new PipedOutputStream(
stderr)) {
+ pipedOut = pipedStdout;
+ pipedErr = pipedStderr;
connection.attachLog(containerId, pipedStdout, pipedStderr);
pipedStdout.flush();
pipedStderr.flush();
} catch (DockerException | InterruptedException | IOException e) {
- // do nothing but close output streams
+ // do nothing but flush/close output streams
+ if (pipedOut != null) {
+ try {
+ pipedOut.flush();
+ } catch (IOException e1) {
+ // ignore
+ }
+ }
+ if (pipedErr != null) {
+ try {
+ pipedErr.flush();
+ } catch (IOException e1) {
+ // ignore
+ }
+ }
}
};
@@ -93,12 +111,19 @@ public class ContainerCommandProcess extends Process {
} catch (InterruptedException e1) {
// ignore
}
+ thread.interrupt();
+ while (thread.isAlive()) {
+ try {
+ Thread.sleep(500);
+ } catch (InterruptedException e) {
+ // ignore
+ }
+ }
this.stdout.close();
this.stderr.close();
} catch (IOException e) {
// ignore
}
- thread.interrupt();
}
@Override
@@ -262,6 +287,14 @@ public class ContainerCommandProcess extends Process {
try {
IDockerContainerExit exit = connection
.waitForContainer(containerId);
+ thread.interrupt();
+ while (thread.isAlive()) {
+ try {
+ Thread.sleep(500);
+ } catch (InterruptedException e) {
+ // ignore
+ }
+ }
connection.stopLoggingThread(containerId);
if (!keepContainer) {
connection.removeContainer(containerId);

Back to the top