Skip to content

Fix proc_close() signal exit code handling#21293

Open
alies-dev wants to merge 2 commits intophp:masterfrom
alies-dev:fix-proc-close-signal-exit-code
Open

Fix proc_close() signal exit code handling#21293
alies-dev wants to merge 2 commits intophp:masterfrom
alies-dev:fix-proc-close-signal-exit-code

Conversation

@alies-dev
Copy link

@alies-dev alies-dev commented Feb 25, 2026

When a child process spawned via proc_open() is killed by a signal, proc_close() returns a raw/mangled waitpid status instead of a meaningful exit code. This makes it impossible to distinguish between "exited normally with code 11" and "killed by SIGSEGV".

The fix adds proper WIFSIGNALED()/WTERMSIG() handling in proc_open_rsrc_dtor() (which proc_close() calls internally), returning 128 + signal_number — the same convention used by bash and other shells.

proc_get_status() already handled this correctly via its signaled/termsig fields; only the proc_close() return value was broken.

Fixes GH-21292


The bug originally was found by using Psalm vimeo/psalm#11679 that uses composer/xdebug-handler: composer/xdebug-handler#161

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 phpGH-21292
PHP catches SIGTERM internally and does exit(255), so the child
process never actually dies from the signal. Use /bin/sh with
kill -9 (SIGKILL) which cannot be caught.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

proc_close() returns raw signal number, indistinguishable from normal exit code

1 participant