spotify/docker-client

Execution of detached programs

Open

#421 opened on Apr 28, 2016

View on GitHub
 (2 comments) (3 reactions) (0 assignees)Java (1,430 stars) (551 forks)batch import
help wantedpinnedquestion

Description

Description

The LogStream::readFully() associated with a detached exec seems to return an empty String.

Background: We would like to run a detached program that may take a while to finish, and so we would like to abort waiting for it under certain circumstances (we're shutting down, or a timeout has been reached). So we have code similar to what's shown below. Unfortunately, stream.readFully() unexpectedly returns an empty String when !running, which is strange because if we use a non-detached version, we can confirm the output is non-empty as it should be.

Our hypothesis is that stream.readFully() returns an empty String, always, on a detached exec instance. Is this true? As mentioned above, we would like to be able to terminate the waiting of the completion of the command, how can this be accomplished? The API suggests it may be possible to interrupt the thread, however we would strongly prefer to avoid interrupting threads (for many reasons).

String execId = docker.execCreate(name, args,
        DockerClient.ExecCreateParam.attachStdout(),
        DockerClient.ExecCreateParam.attachStderr());
try (LogStream streamTmp =  docker.execStart(execId, DockerClient.ExecStartParameter.DETACH)) {
    long startNanoTime = System.nanoTime();
    long sleepMillis = 10;
    while (!condition.shouldAbort()) {
        try {
            ExecState state = docker.execInspect(execId);

            if (!state.running()) {
                return new ProcessResult(state.exitCode(), stream.readFully());
            }
        if (System.nanoTime() - startNanoTime > timeout.toNanos()) {
            // TODO: Would be great if we could attach stdout/stderr
            // ... unfortunately LogStream.readFully() blocks.
            throw new TimeoutException("Command " + args + " for container " + containerName
                    + " timed out after " + timeout.toMillis() + " ms");
        }

        sleepMillis = Math.min(2 * sleepMillis, 1_000);
        try { Thread.sleep(sleepMillis); } catch (InterruptedException e) { }
    }
}

How to reproduce

See above

What do you expect

I would have expected the LogStream to be connected to the stdout/stderr as defined by our DockerClient.ExecCreateParam to execCreate(), and LogStream::readFully() after the program has completed should return the full stdout/stderr (depending on the DockerClient.ExecCreateParam).

What happened instead

An empty string is returned.

Software:

Client: Version: 1.9.1 API version: 1.21 Go version: go1.4.2 Git commit: a34a1d5 Built: Fri Nov 20 13:29:22 UTC 2015 OS/Arch: linux/amd64

Server: Version: 1.9.1 API version: 1.21 Go version: go1.4.2 Git commit: a34a1d5 Built: Fri Nov 20 13:29:22 UTC 2015 OS/Arch: linux/amd64

  • docker version: [Add docker version here, client and server]
  • docker-client version: 3.5.12

Contributor guide