@@ -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 ) {
0 commit comments