[WIP] Attempt to fix opcache_reset() races #14803
Open
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
This is related to both #8739 and #14471. In particular to the latter.
I observe that there are data races possible against
&ZCSG(hash)
betweenzend_accel_hash_find_entry
andzend_accel_add_key
. We use the bucket return value fromzend_accel_hash_find_entry
and use it as a data pointer forzend_accel_add_key
. However, if the&ZCSG(hash)
table is modified in between those calls, then we end up with inconsistent data in the hash table. This is possible for example with opcache_reset().We can observe this is the case by adding
memset(accel_hash->hash_entries, 0xf0, sizeof(zend_accel_hash_entry )*accel_hash->max_num_entries);
at the bottom ofzend_accel_hash_clean
which causes a dereference at address0xf0f0f0f0f0f0f110
when walking the bucket chain inzend_accel_hash_find_entry
.I ran the test from GH-14471 with
opcache.interned_strings_buffer=0
and it is much more stable. Prior to this patch it would constantly crash after a while. With the interned strings buffer not zero I still observe crashes. Even with the buffer size 0, not all issues are fixed yet, see #8739 (comment) for example. I would need some feedback or guidance.One problem I think is still there is when returning a string from the hash table with
zend_string *str = zend_string_copy(persistent_script->script.filename);
, if that string is in the interned hash table then nothing is preventing a restart from clearing out the filename string.