Skip to content

Commit a22d029

Browse files
committed
Fix proc_close() to return 128+signal when child is killed by signal
proc_close() previously returned the raw waitpid status when a child process was killed by a signal, making it impossible to distinguish a signal death from a normal exit with the same code. Now follows the bash convention: return 128 + signal_number for signal-terminated processes (e.g. 139 for SIGSEGV, 143 for SIGTERM). Closes GH-21292
1 parent 5fc9d9d commit a22d029

File tree

2 files changed

+54
-4
lines changed

2 files changed

+54
-4
lines changed

ext/standard/proc_open.c

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -302,11 +302,13 @@ static void proc_open_rsrc_dtor(zend_resource *rsrc)
302302

303303
if (wait_pid <= 0) {
304304
FG(pclose_ret) = -1;
305+
} else if (WIFEXITED(wstatus)) {
306+
FG(pclose_ret) = WEXITSTATUS(wstatus);
307+
} else if (WIFSIGNALED(wstatus)) {
308+
/* Follow the bash/shell convention: 128 + signal number */
309+
FG(pclose_ret) = 128 + WTERMSIG(wstatus);
305310
} else {
306-
if (WIFEXITED(wstatus)) {
307-
wstatus = WEXITSTATUS(wstatus);
308-
}
309-
FG(pclose_ret) = wstatus;
311+
FG(pclose_ret) = -1;
310312
}
311313

312314
#else
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
--TEST--
2+
proc_close() returns 128+signal when child is killed by a signal
3+
--SKIPIF--
4+
<?php
5+
if (PHP_OS_FAMILY === 'Windows') die('skip Not for Windows');
6+
if (!function_exists('posix_kill') || !function_exists('posix_getpid')) die('skip posix extension required');
7+
?>
8+
--FILE--
9+
<?php
10+
11+
// Child that kills itself with SIGTERM (15)
12+
$child = '<?php posix_kill(posix_getpid(), 15);';
13+
14+
$process = proc_open(
15+
[PHP_BINARY, '-r', $child],
16+
[['pipe', 'r'], ['pipe', 'w'], ['pipe', 'w']],
17+
$pipes
18+
);
19+
20+
foreach ($pipes as $pipe) {
21+
fclose($pipe);
22+
}
23+
24+
$exitCode = proc_close($process);
25+
// Should be 128 + 15 = 143
26+
var_dump($exitCode);
27+
28+
// Child that exits normally with code 42
29+
$child2 = '<?php exit(42);';
30+
31+
$process2 = proc_open(
32+
[PHP_BINARY, '-r', $child2],
33+
[['pipe', 'r'], ['pipe', 'w'], ['pipe', 'w']],
34+
$pipes2
35+
);
36+
37+
foreach ($pipes2 as $pipe) {
38+
fclose($pipe);
39+
}
40+
41+
$exitCode2 = proc_close($process2);
42+
// Should be 42
43+
var_dump($exitCode2);
44+
45+
?>
46+
--EXPECT--
47+
int(143)
48+
int(42)

0 commit comments

Comments
 (0)