Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 16 additions & 2 deletions ext/opcache/ZendAccelerator.c
Original file line number Diff line number Diff line change
Expand Up @@ -4877,10 +4877,24 @@ static zend_result accel_finish_startup(void)
exit(ret == SUCCESS ? 0 : 1);
} else { /* parent */
int status;
pid_t chld_pid;

/* Handle EINTR from reload signal storms during preload.
*
* Problem: Legacy deployment workflows or monitoring systems may send
* multiple SIGUSR1/SIGUSR2 signals before the previous reload finishes.
* Because some SAPIs register these handlers without SA_RESTART, system calls
* are interrupted (EINTR) rather than automatically restarted.
*
* Without this retry loop, repeated signals can cause waitpid() to fail
* non-deterministically, leading to premature master process exit. */
do {
chld_pid = waitpid(pid, &status, 0);
} while (chld_pid < 0 && errno == EINTR);
Comment on lines +4891 to +4893
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks right, except we probably have to check for a stronger signals (e.g. SIGQUIT).
Otherwise we may hung in this loop forever.
@arnaud-lb can you please take care about this.


if (waitpid(pid, &status, 0) < 0) {
if (chld_pid < 0) {
zend_shared_alloc_unlock();
zend_accel_error_noreturn(ACCEL_LOG_FATAL, "Preloading failed to waitpid(%d)", pid);
zend_accel_error_noreturn(ACCEL_LOG_FATAL, "Preloading failed to waitpid(%d) with errno=%s", pid, strerror(errno));
}

if (ZCSG(preload_script)) {
Expand Down