frankenphp icon indicating copy to clipboard operation
frankenphp copied to clipboard

SigQ eventually gets full

Open withinboredom opened this issue 2 years ago • 9 comments

Some signals appear to be getting held up somewhere, causing an eventual segfault.

cat /proc/5497/status | grep Sig                                                                                                                               23cfdd722a8d: Sun Dec 24 20:04:39 2023

SigQ:   48523/63519 <-- this should be 0-ish when idle
SigPnd: 0000000000000000
SigBlk: 0000000000000000
SigIgn: 0000000000000000
SigCgt: ffffffff7fc1feff

Once these are all used up, a segfault will be issued:

Could not create timer: Resource temporarily unavailable (11)

I haven't seen this in worker-mode, FWIW. Related to #366

withinboredom avatar Dec 24 '23 20:12 withinboredom

I suspect these signals come in after the request is completed (thus, PHP has shutdown) but still need to be handled.

withinboredom avatar Dec 24 '23 21:12 withinboredom

This is likely related to the memory leak. This means that the timer created by PHP to handle timeouts isn't cleaned properly. This code is quite new in PHP (I created it), I probably messed up something.

Would you be able to track where the code timer is created (eg using GDB) and why it isn't freed?

dunglas avatar Dec 24 '23 22:12 dunglas

The timer is both created and destroyed @dunglas, I suspect this is important:

timer_delete() deletes the timer whose ID is given in timerid. If the timer was armed at the time of this call, it is disarmed before being deleted. The treatment of any pending signal generated by the deleted timer is unspecified.

From the looks of things, pending signals do not seem to be cleaned up (at least in my kernel) after the clock is deleted.

withinboredom avatar Dec 25 '23 08:12 withinboredom

But what signals? Because calling timer_delete() should disarm the timer, so no signals should be send.

May https://github.com/php/php-src/pull/12539 help?

dunglas avatar Dec 25 '23 08:12 dunglas

The signals in /proc/${ID}/timers... The timer is disarmed and not fired. However, pending signals are left hanging around (yay unspecified behavior).

To clear the timers, the signal must be ignored after the timer is deleted.

Opening a PR https://github.com/php/php-src/compare/master...bottledcode:php-src:fix/timers?expand=1

Just need to figure out how to get it backported to 8.2 + 8.3 + master.

withinboredom avatar Dec 25 '23 10:12 withinboredom

So, I added some logic to that branch in php-src to detect if we create more than one timer per thread (because there was still a leak). It looks like ts_resource(0) creates a timer, as well as php_request_startup().

@dunglas any ideas on how we could fix this on the FrankenPHP side? Or perhaps in my branch, I just make it silently bail instead of emitting a warning?

withinboredom avatar Dec 25 '23 11:12 withinboredom

I've no idea yet, but I'll be glad to take a look when I get back from vacation if you don't manage to find a fix before that (but I'm sure you will :D). Anyway, thanks for your research and commitment to fixing these issues, this is very promising!!

dunglas avatar Dec 25 '23 12:12 dunglas

This is now fixed upstream and should be in the next patch release of 8.2 and 8.3.

withinboredom avatar Jan 05 '24 18:01 withinboredom

The patch will land in PHP 8.3.3 and 8.2.1 (it is already available in the betas).

dunglas avatar Feb 02 '24 23:02 dunglas