Skip to content

Commit 2da8e27

Browse files
authored
Merge pull request #1366 from salemove/fix-null-pointer-exception
2 parents e41422f + 0bc0aad commit 2da8e27

File tree

2 files changed

+44
-12
lines changed

2 files changed

+44
-12
lines changed

src/main/java/org/csanchez/jenkins/plugins/kubernetes/pipeline/ContainerExecDecorator.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -564,7 +564,7 @@ public void onClose(int i, String s) {
564564

565565
LOGGER.log(Level.INFO, "Created process inside pod: [" + getPodName() + "], container: ["
566566
+ containerName + "]" + "[" + TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - startMethod) + " ms]");
567-
ContainerExecProc proc = new ContainerExecProc(watch, alive, finished, stdin);
567+
ContainerExecProc proc = new ContainerExecProc(watch, alive, finished, stdin, printStream);
568568
closables.add(proc);
569569
return proc;
570570
} catch (InterruptedException ie) {

src/main/java/org/csanchez/jenkins/plugins/kubernetes/pipeline/ContainerExecProc.java

Lines changed: 43 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,28 @@
11
package org.csanchez.jenkins.plugins.kubernetes.pipeline;
22

33

4+
import hudson.Proc;
5+
import io.fabric8.kubernetes.client.dsl.ExecWatch;
6+
import org.apache.commons.io.output.NullPrintStream;
7+
import jenkins.util.Timer;
8+
49
import java.io.ByteArrayOutputStream;
510
import java.io.Closeable;
611
import java.io.IOException;
712
import java.io.InputStream;
813
import java.io.OutputStream;
14+
import java.io.PrintStream;
915
import java.nio.charset.StandardCharsets;
1016
import java.util.concurrent.Callable;
17+
import java.util.concurrent.CompletableFuture;
1118
import java.util.concurrent.CountDownLatch;
19+
import java.util.concurrent.ExecutionException;
1220
import java.util.concurrent.TimeUnit;
1321
import java.util.concurrent.atomic.AtomicBoolean;
1422
import java.util.logging.Level;
1523
import java.util.logging.Logger;
1624

17-
import hudson.Proc;
18-
import io.fabric8.kubernetes.client.dsl.ExecWatch;
19-
import jenkins.util.Timer;
20-
import static org.csanchez.jenkins.plugins.kubernetes.pipeline.Constants.CTRL_C;
21-
import static org.csanchez.jenkins.plugins.kubernetes.pipeline.Constants.EXIT;
22-
import static org.csanchez.jenkins.plugins.kubernetes.pipeline.Constants.NEWLINE;
25+
import static org.csanchez.jenkins.plugins.kubernetes.pipeline.Constants.*;
2326

2427
/**
2528
* Handle the liveness of the processes executed in containers, wait for them to finish and process exit codes.
@@ -34,29 +37,32 @@ public class ContainerExecProc extends Proc implements Closeable, Runnable {
3437
private final ExecWatch watch;
3538
private final OutputStream stdin;
3639

40+
private final PrintStream printStream;
41+
3742
@Deprecated
3843
public ContainerExecProc(ExecWatch watch, AtomicBoolean alive, CountDownLatch finished,
3944
Callable<Integer> exitCode) {
40-
this(watch, alive, finished, (OutputStream) null);
45+
this(watch, alive, finished, (OutputStream) null, (PrintStream) null);
4146
}
4247

4348
@Deprecated
4449
public ContainerExecProc(ExecWatch watch, AtomicBoolean alive, CountDownLatch finished,
4550
ByteArrayOutputStream error) {
46-
this(watch, alive, finished, (OutputStream) null);
51+
this(watch, alive, finished, (OutputStream) null, (PrintStream) null);
4752
}
4853

4954
@Deprecated
5055
public ContainerExecProc(ExecWatch watch, AtomicBoolean alive, CountDownLatch finished, OutputStream stdin,
5156
ByteArrayOutputStream error) {
52-
this(watch, alive, finished, stdin);
57+
this(watch, alive, finished, stdin, (PrintStream) null);
5358
}
5459

55-
public ContainerExecProc(ExecWatch watch, AtomicBoolean alive, CountDownLatch finished, OutputStream stdin) {
60+
public ContainerExecProc(ExecWatch watch, AtomicBoolean alive, CountDownLatch finished, OutputStream stdin, PrintStream printStream) {
5661
this.watch = watch;
5762
this.stdin = stdin == null ? watch.getInput() : stdin;
5863
this.alive = alive;
5964
this.finished = finished;
65+
this.printStream = printStream == null ? NullPrintStream.NULL_PRINT_STREAM : printStream;
6066
Timer.get().schedule(this, 1, TimeUnit.MINUTES);
6167
}
6268

@@ -86,7 +92,33 @@ public int join() throws IOException, InterruptedException {
8692
LOGGER.log(Level.FINEST, "Waiting for websocket to close on command finish ({0})", finished);
8793
finished.await();
8894
LOGGER.log(Level.FINEST, "Command is finished ({0})", finished);
89-
return watch.exitCode().join();
95+
96+
CompletableFuture<Integer> exitCodeFuture = watch.exitCode();
97+
98+
if (exitCodeFuture == null) {
99+
LOGGER.log(Level.FINEST, "exitCodeFuture is null.");
100+
printStream.print("exitCodeFuture is null.");
101+
return -1;
102+
}
103+
104+
Integer exitCode = exitCodeFuture.get();
105+
106+
if (exitCode == null) {
107+
LOGGER.log(Level.FINEST, "The container exec watch was closed before it could obtain an exit code from the process.");
108+
printStream.print("The container exec watch was closed before it could obtain an exit code from the process.");
109+
return -1;
110+
}
111+
return exitCode;
112+
} catch (ExecutionException e) {
113+
Throwable cause = e.getCause();
114+
if (cause != null) {
115+
LOGGER.log(Level.FINEST, "ExecutionException occurred while waiting for exit code", cause);
116+
printStream.printf("ExecutionException occurred while waiting for exit code: %s%n", cause);
117+
} else {
118+
LOGGER.log(Level.FINEST, "ExecutionException occurred while waiting for exit code", e);
119+
printStream.printf("ExecutionException occurred while waiting for exit code: %s%n", e);
120+
}
121+
return -1;
90122
} finally {
91123
close();
92124
}

0 commit comments

Comments
 (0)