Skip to content

Execute signal handlers before restarting syscalls#22538

Draft
arnaud-lb wants to merge 1 commit into
php:masterfrom
arnaud-lb:signal-restart
Draft

Execute signal handlers before restarting syscalls#22538
arnaud-lb wants to merge 1 commit into
php:masterfrom
arnaud-lb:signal-restart

Conversation

@arnaud-lb

@arnaud-lb arnaud-lb commented Jul 1, 2026

Copy link
Copy Markdown
Member

This PoCs the ideas discussed in #5521:

First and foremost, the whole concept of "restart syscalls" IMHO doesn't really work in PHP right now. The idea behind SA_RESTART is that the signal handler gets executed and then the syscall is restarted. However, because in PHP (at least as far as pcntl signals are concerned) the signal handler only sets a flag and the actual PHP-level callback is only executed on VM reentry, this means that "restart syscalls" really means "delay syscalls until the end of I/O operations", which is pretty useless. To use something like SIGALARM this effectively means that you need to disable syscall restarting, which also means that you need to handle this all over the place, which most code is not prepared to do.

The correct approach to handle that is (as the PEP outlines) disable SA_RESTART and manually implement restart on EINTR, but with an explicit call to the interrupt handler. This implements how C-level SA_RESTART behaves in PHP.

Syscalls are interrupted when:

  • Any signal handler returns SignalResult::Interrupt
  • Any signal handler returns SignalResult::Default or no value, and was registered with $restart_syscall=false
  • Any signal handler throws an exception
  • EG(timed_out) is set

Otherwise, syscalls are restarted.

Implemented only in php_sockop_read for now, but the goal would be to implement this for all syscalls eventually, and at least for existing EINTR loops.

Some considerations:

  • Some signal handlers may already be pending before performing a syscall, so we have to check the queue before that
  • Operations with a timeout should use a deadline, as restarting will extend the total time (not implemented)
  • Syscalls executed by a signal handler may need to execute other signal handlers, if new signals are delivered (not implemented)

Exceptions vs return value:

Returning a value is more PHP-ish than throwing an exception, but exceptions have some benefits in this context:

  • Returning SignalResult::Interrupt from a handler does nothing outside of syscalls
  • Exceptions will propagate to parent signal handlers by default (see above)

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.

1 participant