@@ -229,6 +229,28 @@ static void _php_free_envp(php_process_env env)
229
229
}
230
230
/* }}} */
231
231
232
+ #if HAVE_SYS_WAIT_H
233
+ static pid_t waitpid_cached (php_process_handle * proc , int * wait_status , int options )
234
+ {
235
+ if (proc -> has_stored_exit_wait_status ) {
236
+ * wait_status = proc -> stored_exit_wait_status_value ;
237
+ return proc -> child ;
238
+ }
239
+
240
+ pid_t wait_pid = waitpid (proc -> child , wait_status , options );
241
+
242
+ /* The "exit" status is the final status of the process.
243
+ * If we were to store the status unconditionally,
244
+ * we would return stale statuses in the future after the process continues. */
245
+ if (wait_pid > 0 && WIFEXITED (* wait_status )) {
246
+ proc -> has_stored_exit_wait_status = true;
247
+ proc -> stored_exit_wait_status_value = * wait_status ;
248
+ }
249
+
250
+ return wait_pid ;
251
+ }
252
+ #endif
253
+
232
254
/* {{{ proc_open_rsrc_dtor
233
255
* Free `proc` resource, either because all references to it were dropped or because `pclose` or
234
256
* `proc_close` were called */
@@ -273,7 +295,7 @@ static void proc_open_rsrc_dtor(zend_resource *rsrc)
273
295
waitpid_options = WNOHANG ;
274
296
}
275
297
do {
276
- wait_pid = waitpid (proc -> child , & wstatus , waitpid_options );
298
+ wait_pid = waitpid_cached (proc , & wstatus , waitpid_options );
277
299
} while (wait_pid == -1 && errno == EINTR );
278
300
279
301
if (wait_pid <= 0 ) {
@@ -386,7 +408,7 @@ PHP_FUNCTION(proc_get_status)
386
408
exitcode = running ? -1 : wstatus ;
387
409
388
410
#elif HAVE_SYS_WAIT_H
389
- wait_pid = waitpid (proc -> child , & wstatus , WNOHANG |WUNTRACED );
411
+ wait_pid = waitpid_cached (proc , & wstatus , WNOHANG |WUNTRACED );
390
412
391
413
if (wait_pid == proc -> child ) {
392
414
if (WIFEXITED (wstatus )) {
@@ -1247,6 +1269,9 @@ PHP_FUNCTION(proc_open)
1247
1269
proc -> childHandle = childHandle ;
1248
1270
#endif
1249
1271
proc -> env = env ;
1272
+ #if HAVE_SYS_WAIT_H
1273
+ proc -> has_stored_exit_wait_status = false;
1274
+ #endif
1250
1275
1251
1276
/* Clean up all the child ends and then open streams on the parent
1252
1277
* ends, where appropriate */
0 commit comments