On 21/10/22 01:11, Kévin Dunglas wrote:
Here is the plan:

1. Switch to timer_create() for timeouts, but only on Linux (it's not
supported on other platforms yet), when ZTS is enabled and Zend Signals is
disabled. As the feature is currently entirely broken when ZTS is on, this
can be considered a bug fix and cannot be worse than it currently is.
1bis. Can be done independently of 1., and even in parallel, optional as
long as we keep the --disable-zend-signals flag: Remove Zend Signals
entirely, because even if it can be partially fixed (I proposed a patch
fixing segfaults: https://github.com/php/php-src/pull/9766), it seems now
useless and causes unfixable issues with some signals such as SIGINT (
https://github.com/php/php-src/issues/9649#issuecomment-1265811930)
2. Switch to Grand Central Dispatch on macOS and FreeBSD when ZTS is
enabled and Zend Signals is disabled (if not removed at this point), which
provides a feature similar to timer_create() for these platforms.
3. Probably in a future major version, optional: switch to
timer_create()/GCD even for non-ZTS builds to uniformize and simplify the
code.


Sounds good to me, for what it's worth.

I spent some time studying PR #5591 since it feels like I should have some expertise in this area by now. Timeout handling in PHP 5 was a joke. The list of library functions which can be safely re-entered from a signal handler is listed on man signal-safety(7). Most notably it does not include malloc(). You cannot just longjmp() out of a signal handler and re-enter userspace code, as PHP 5 was doing.

I partly solved this problem just for Wikimedia in 2011 in a hilariously hacky custom extension (wmerrors). It defensively produced an error page, guarded by a second timer, then killed the process with abort(). This helped to reduce the rate of deadlocks and segfaults in Wikimedia production.

So I was pretty happy when the new system for signal and timeout handling was introduced in PHP 7.1. I extended that system by writing the Excimer extension, which provides userspace timer facilities with timer_create() and vm_interrupt. We're using Excimer in production to implement timeouts.

My understanding of PR #5591 is that it is removing the remnants of the old signal handling system. There is a lot of discussion of the correct implementation of HANDLE_BLOCK_INTERRUPTIONS(), but that macro was from the outset an inadequate approach to signal safety. Maybe it helped to reduce the rate of segfaults, but at Wikimedia's scale it was still a segfault firehose. If your signal handler calls malloc(), then obviously every malloc() call and every call of a library function that may call malloc() becomes a critical section.

So in my view, the critical sections should all be removed and all signal handlers should be implemented safely, by setting a flag that is checked from a safe context. The same recommendation applies whether you use timer_create() or setitimer().

In Excimer we are using timer_create() with SIGEV_THREAD. PHP request threads are registered in a global hashtable with long-lived integer handles, because there is no way to prevent events from being delivered after the relevant request has terminated. You can't store a pointer in sival_ptr if it will be freed at request shutdown. SIGEV_THREAD is less intrusive than SIGEV_SIGNAL or SIGEV_THREAD_ID since it doesn't interrupt syscalls.


What do you think about this plan? Apart from the technical aspects, what's
the best way forward? Submit patches? Propose an RFC? Do both? (pardon my
ignorance of internals processes).
Submit PRs I guess. I've only submitted a handful of PRs to PHP, and I haven't got push access, so I'm not an expert. But I think the usual strategies apply. Answer the nitpickers, get to know people, nag, escalate, etc.

(I did have Subversion write access, which I got by taking over maintainership of a PEAR package, but I was never brave enough to push things to the PHP core.)

-- Tim Starling

--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: https://www.php.net/unsub.php

Reply via email to