Skip to content

fix: log opcache restarts - #2634

Open
nicolas-grekas wants to merge 1 commit into
php:mainfrom
nicolas-grekas:opcache-restart-log
Open

fix: log opcache restarts#2634
nicolas-grekas wants to merge 1 commit into
php:mainfrom
nicolas-grekas:opcache-restart-log

Conversation

@nicolas-grekas

Copy link
Copy Markdown
Contributor

Split out of #2621, which is closed: this keeps only the log line, not the thread reboot.

opcache schedules a restart of its shared memory on exhaustion or hash overflow, then carries it out at the next request init on any thread. Under ZTS that happens while other threads are still running: the deferral gate accel_is_inactive() probes for a conflicting lock with fcntl F_GETLK, and POSIX fcntl locks belong to the process, so the probe never sees the threads of the process holding them. Workers are the worst case, they hold shared memory references for their whole life instead of for one request.

What an operator sees today is a segfault or a sudden slowdown with nothing in the logs pointing at opcache. opcache does report the event, but only at opcache.log_verbosity_level=4 and in its own log.

This PR makes the event visible and does nothing else:

WARN opcache restart scheduled, running PHP threads may hold stale references to its shared memory: raise opcache.memory_consumption and opcache.max_accelerated_files to make restarts less likely  reason="hash overflow"

zend_accel_schedule_restart_hook is the only in-process signal for this, so it is set again, but this time it only logs. No thread reboot, so nothing here can loop the way #2564 was worried about.

Same #if defined(ZTS) && PHP_VERSION_ID >= 80400 guard as before. reason comes from zend_accel_restart_reason: out of memory, hash overflow, user. user should be unreachable since opcache_reset() is overridden, so seeing it means the override did not take, which is worth knowing too.

No test: forcing a real restart is exactly what takes the process down, so a test for this would be a test that crashes.

opcache schedules a restart of its shared memory on exhaustion or hash
overflow, then carries it out at the next request init on any thread.
Under ZTS it does that while other threads are still running, because
the deferral gate (accel_is_inactive()) probes for a conflicting lock
with fcntl F_GETLK, and POSIX fcntl locks belong to the process, so the
probe never sees the threads of the process holding them. Workers are
the worst case: they hold shared memory references for their whole life
rather than for a single request.

The result is a crash or a slowdown with nothing in the logs pointing at
opcache. opcache does report it, but only at
opcache.log_verbosity_level=4 and in its own log.

zend_accel_schedule_restart_hook is the only in-process signal for this,
so it is used to emit one warning naming the restart reason and the two
settings that make restarts less likely. Nothing else is done with it:
the threads are not rebooted, which is what php#2564 removed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant