Skip to content

ext/opcache: Mark dl()-created persistent strings as thread-local - #24421

Closed
iliaal wants to merge 1 commit into
php:PHP-8.4from
iliaal:fix/opcache-dl-rc-debug-strings
Closed

iliaal wants to merge 1 commit into
php:PHP-8.4from
iliaal:fix/opcache-dl-rc-debug-strings

Conversation

@iliaal

@iliaal iliaal commented Oct 19, 2026 •

Copy link
Copy Markdown
Member

Fixes the nightly LINUX_X64_VARIATION_DEBUG_ZTS failures of frameless_temporary_opcache.phpt and, on 8.5+, frameless_temporary.phpt. Names that dl() registers during a request come back from opcache's interned-string handlers as plain persistent strings, so the first refcount change on one trips the ZEND_RC_DEBUG assertion. They belong to the request's temporary module, so they are now marked GC_PERSISTENT_LOCAL while zend_rc_debug is off, as during dl(); release builds are unaffected.

@Girgias

Girgias commented Oct 19, 2026

Copy link
Copy Markdown
Member

I think this is correct, but I always get confused about marking request strings as persistent, so if @arnaud-lb could double check that would be great.

@arnaud-lb

Copy link
Copy Markdown
Member

ZEND_RC_DEBUG forbids modifications of persistent strings during a request, because usually such strings can be accessed by other requests. GC_PERSISTENT_LOCAL signals that the string is actually not shared with other requests, so it's safe to modify.

@iliaal I think that doing it in accel_init_interned_string_for_php() weakens ZEND_RC_DEBUG because really we don't know if the string will be shared later.

There are a few dl()-only ZEND_RC_DEBUG workarounds already, I think that we should do that here again. dl() unsets zend_rc_debug, so we should add the flag only when zend_rc_debug is false, with a comment like

php-src/Zend/zend_string.c

Lines 315 to 316 in 8844427

/* PHP shouldn't create persistent interned string during request,
* but at least dl() may do this */

During a request, opcache's interned-string handlers return a plain
persistent string when the name is not already in shared memory. dl()
registers a temporary module's function, class and property names this
way, so under ZEND_RC_DEBUG the first refcount change on one of them
(building an argument TypeError, ReflectionFunction::getName(),
get_object_vars()) trips the persistent-string assertion. The strings
belong to the request's temporary module; mark them GC_PERSISTENT_LOCAL,
but only while zend_rc_debug is off, as dl() turns it off, so the check
keeps covering strings that may later be shared.
@iliaal
iliaal force-pushed the fix/opcache-dl-rc-debug-strings branch from 37bf0db to f5793e8 Compare October 19, 2026 15:45
@iliaal iliaal changed the title ext/opcache: Mark request-time persistent strings as thread-local ext/opcache: Mark dl()-created persistent strings as thread-local Oct 19, 2026
@iliaal

iliaal commented Oct 19, 2026

Copy link
Copy Markdown
Member Author

Good point, thanks, a little bit ugly of a work-around but it makes sense especially given other use-cases

@arnaud-lb arnaud-lb left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Looks good to me!

@iliaal iliaal closed this in 77dbc2c Oct 19, 2026
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.

3 participants