Skip to content

Commit 0b98883

Browse files
committed
Handle cross-platform timeout
1 parent ea5297e commit 0b98883

3 files changed

Lines changed: 24 additions & 9 deletions

File tree

lib/java-caller.js

Lines changed: 24 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -100,10 +100,12 @@ class JavaCaller {
100100

101101
const javaExeToUse = this.javaExecutableFromNodeJavaCaller ?? javaExe;
102102
const classPathStr = this.buildClasspathStr();
103-
const javaArgs = this.buildArguments(classPathStr, (userArguments || []).concat(this.commandJavaArgs));
103+
const javaArgs = this.buildArguments(classPathStr, (userArguments || []).concat(this.commandJavaArgs), runOptions.windowsVerbatimArguments);
104104
let stdout = "";
105105
let stderr = "";
106106
let child;
107+
let timeoutId;
108+
let killedByTimeout = false;
107109
const prom = new Promise((resolve) => {
108110
// Spawn java command line
109111
debug(`Java command: ${javaExeToUse} ${javaArgs.join(" ")}`);
@@ -122,6 +124,19 @@ class JavaCaller {
122124
}
123125
child = spawn(javaExeToUse, javaArgs, spawnOptions);
124126

127+
if (runOptions.timeout) {
128+
timeoutId = setTimeout(() => {
129+
if (!child.killed) {
130+
killedByTimeout = true;
131+
try {
132+
child.kill(runOptions.killSignal);
133+
} catch (err) {
134+
stderr += `Failed to kill process after ${runOptions.timeout}ms: ${err.message}`;
135+
}
136+
}
137+
}, runOptions.timeout);
138+
}
139+
125140
// Gather stdout and stderr if they must be returned
126141
if (spawnOptions.stdio === "pipe") {
127142
child.stdout.setEncoding(`${runOptions.stdoutEncoding}`);
@@ -142,20 +157,20 @@ class JavaCaller {
142157

143158
// Catch status code
144159
child.on("close", (code, signal) => {
145-
console.log({code, signal});
146-
147-
if (runOptions.timeout && signal === runOptions.killSignal) {
148-
// Process was _likely_ terminated because of a timeout
149-
// There is no way to determine if a timeout occurred or if another process sent killSignal
150-
// See https://github.com/nodejs/node/issues/51561
160+
if (timeoutId) {
161+
clearTimeout(timeoutId);
162+
}
163+
164+
if (killedByTimeout || (runOptions.timeout && signal === runOptions.killSignal)) {
165+
// Process was terminated because of the timeout, either via our fallback timer or the built-in spawn timeout
151166
this.status = 666;
152167
stderr += `Process timed out with ${runOptions.killSignal} after ${runOptions.timeout}ms.`;
153168
} else {
154169
this.status = code;
155170
}
156171

157-
resolve();
158-
});
172+
resolve();
173+
});
159174

160175
// Detach from main process in case detached === true
161176
if (runOptions.detached) {

test/java/jar/JavaCallerTester.jar

18 Bytes
Binary file not shown.
18 Bytes
Binary file not shown.

0 commit comments

Comments
 (0)