php / php/php-src

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

Aperta
#21,292 1 commento 2 reazioni 0 assegnatari Vedi su GitHub

Nessuno ha ancora preso questa issue.

Lingua principale
C
Stelle
40.4k
Fork
8.1k
Merge medio
2g 13h
PR unite (30g)
96

Descrizione

Description

On non-Windows systems, when a child process opened via proc_open() is killed by a signal, proc_close() returns the raw signal number (e.g. 11 for SIGSEGV) rather than following the Unix convention of 128 + signal (e.g. 139).

This makes it impossible for PHP userland code to distinguish between "process exited normally with code 11" and "process was killed by SIGSEGV".

Underlying cause

Internally, proc_close() calls waitpid() which returns an encoded status. The C macros WIFEXITED()/WEXITSTATUS() and WIFSIGNALED()/WTERMSIG() exist to decode this, but proc_close() does not use them to differentiate the two cases. It effectively passes back a value that loses the signal/exit distinction.

PHP's own pcntl_waitpid() + pcntl_wifexited() + pcntl_wtermsig() handle this correctly, but pcntl is not always available, and proc_close() is the standard way to get the exit status of a proc_open() process.

Reproduction
<?php

// Child script that triggers SIGSEGV
$child = '<?php posix_kill(posix_getpid(), 11);';

$process = proc_open(
    [PHP_BINARY, '-r', $child],
    [],
    $pipes
);

$exitCode = proc_close($process);

// Expected: 139 (128 + 11, following bash/Unix convention)
// Actual: 11 (raw signal number, same as a normal exit code)
echo "Exit code: $exitCode\n";
echo "Is this SIGSEGV or a normal exit(11)? Impossible to tell.\n";
Expected behavior

proc_close() should return 128 + signal_number when the child was killed by a signal, consistent with how bash and other Unix shells report signal termination via $?. This would allow userland code to detect crashes.

Alternatively, expose the signal information through a separate mechanism (e.g. an optional by-reference parameter, or a new proc_exit_status() function).

Real-world impact

This affects tools that use proc_open() to spawn child processes, notably composer/xdebug-handler which restarts PHP processes. When the child crashes (e.g. due to a PHP JIT bug triggering SIGSEGV), the parent receives exit code 11 with no way to detect it was a signal — leading to silent, misleading failures in tools like Psalm, PHPStan, and Composer.

PHP Version

Tested on PHP 8.4 and 8.5, but the behavior has existed since proc_open was introduced.

Operating System

Linux / macOS (any non-Windows POSIX system)

Guida per i contributori

Apri la guida per i contributori

Come iniziare

  1. Leggi tutta la issue e poi la guida ai contributi del progetto.
  2. Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
  3. Fai un fork del repository e lavora su un branch.
  4. Apri una pull request che faccia riferimento al numero della issue.

Direzione di ricerca

Traccia proc_close() sui sistemi non-Windows attraverso waitpid() e i casi WIFEXITED(), WEXITSTATUS(), WIFSIGNALED() e WTERMSIG() descritti nell’issue. Esegui la riproduzione fornita di proc_open() con un processo figlio SIGSEGV e verifica che la terminazione causata da un segnale sia distinguibile da un normale codice di uscita, preservando al contempo il comportamento previsto sulle altre piattaforme.

Scritto dal modello di indicizzazione a partire dal testo della issue.

Valutazione

Stack tecnologico
c, php
Ambito
backend, operating-systems
Tipo di issue
Bug
Difficoltà
4/5
Tempo stimato
3-5 giorni
Stato di attività
Ferma
Chiarezza
Abbastanza chiara
Idoneità per principianti
45/100

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.