@@ -226,6 +226,28 @@ static void _php_free_envp(php_process_env env)
226
226
}
227
227
/* }}} */
228
228
229
+ #if HAVE_SYS_WAIT_H
230
+ static pid_t waitpid_cached (php_process_handle * proc , int * wait_status , int options )
231
+ {
232
+ if (proc -> has_stored_exit_wait_status ) {
233
+ * wait_status = proc -> stored_exit_wait_status_value ;
234
+ return proc -> child ;
235
+ }
236
+
237
+ pid_t wait_pid = waitpid (proc -> child , wait_status , options );
238
+
239
+ /* The "exit" status is the final status of the process.
240
+ * If we were to store the status unconditionally,
241
+ * we would return stale statuses in the future after the process continues. */
242
+ if (wait_pid > 0 && WIFEXITED (* wait_status )) {
243
+ proc -> has_stored_exit_wait_status = true;
244
+ proc -> stored_exit_wait_status_value = * wait_status ;
245
+ }
246
+
247
+ return wait_pid ;
248
+ }
249
+ #endif
250
+
229
251
/* {{{ proc_open_rsrc_dtor
230
252
* Free `proc` resource, either because all references to it were dropped or because `pclose` or
231
253
* `proc_close` were called */
@@ -270,7 +292,7 @@ static void proc_open_rsrc_dtor(zend_resource *rsrc)
270
292
waitpid_options = WNOHANG ;
271
293
}
272
294
do {
273
- wait_pid = waitpid (proc -> child , & wstatus , waitpid_options );
295
+ wait_pid = waitpid_cached (proc , & wstatus , waitpid_options );
274
296
} while (wait_pid == -1 && errno == EINTR );
275
297
276
298
if (wait_pid <= 0 ) {
@@ -383,7 +405,7 @@ PHP_FUNCTION(proc_get_status)
383
405
exitcode = running ? -1 : wstatus ;
384
406
385
407
#elif HAVE_SYS_WAIT_H
386
- wait_pid = waitpid (proc -> child , & wstatus , WNOHANG |WUNTRACED );
408
+ wait_pid = waitpid_cached (proc , & wstatus , WNOHANG |WUNTRACED );
387
409
388
410
if (wait_pid == proc -> child ) {
389
411
if (WIFEXITED (wstatus )) {
@@ -1244,6 +1266,9 @@ PHP_FUNCTION(proc_open)
1244
1266
proc -> childHandle = childHandle ;
1245
1267
#endif
1246
1268
proc -> env = env ;
1269
+ #if HAVE_SYS_WAIT_H
1270
+ proc -> has_stored_exit_wait_status = false;
1271
+ #endif
1247
1272
1248
1273
/* Clean up all the child ends and then open streams on the parent
1249
1274
* ends, where appropriate */
0 commit comments