php / php/php-src

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

Đang mở
#21,292 1 bình luận 2 reaction 0 người được giao Xem trên GitHub

Chưa có ai nhận issue này.

Ngôn ngữ chính
C
Star
40.4k
Fork
8.2k
Merge trung bình
2 ngày 13 giờ
Pull request đã merge (30 ngày)
96

Mô tả

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)

Hướng dẫn đóng góp

Mở hướng dẫn đóng góp

Bắt đầu từ đâu

  1. Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
  2. Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
  3. Fork repository và làm thay đổi trên một nhánh.
  4. Mở pull request có tham chiếu số hiệu của issue.

Hướng nghiên cứu

Theo dõi proc_close() trên các hệ thống không phải Windows qua waitpid() và các trường hợp WIFEXITED(), WEXITSTATUS(), WIFSIGNALED() và WTERMSIG() được mô tả trong issue. Chạy bản tái hiện proc_open() được cung cấp với một tiến trình con SIGSEGV và xác minh rằng việc kết thúc do tín hiệu có thể được phân biệt với mã thoát bình thường, đồng thời vẫn giữ nguyên hành vi mong đợi trên các nền tảng khác.

Do mô hình lập chỉ mục viết ra từ nội dung của issue.

Đánh giá

Công nghệ
c, php
Lĩnh vực
backend, operating-systems
Loại issue
Lỗi
Độ khó
4/5
Thời gian dự kiến
3-5 ngày
Mức độ hoạt động
Đình trệ
Độ rõ ràng
Khá rõ ràng
Mức phù hợp với người mới
45/100

Nhận issue mới trong hộp thư của bạn

Bản tóm tắt ngắn những issue GitHub phù hợp với người mới.