Skip to content

Comments

Fix releasing of ref_count in apc_cache_store()#587

Merged
nikic merged 1 commit intokrakjoe:masterfrom
madmajestro:fix-ref_count-race
Aug 14, 2025
Merged

Fix releasing of ref_count in apc_cache_store()#587
nikic merged 1 commit intokrakjoe:masterfrom
madmajestro:fix-ref_count-race

Conversation

@madmajestro
Copy link
Contributor

In apc_cache_store(), the ref_count was decremented even when the entry needed to be deleted. This allowed the entry to be moved by defragmentation (by another process) before deletion. As a result, the pointer no longer pointed to the desired entry during deletion, causing segmentation faults.

In apc_cache_store(), the ref_count was decremented even when the entry
needed to be deleted. This allowed the entry to be moved by
defragmentation (by another process) before deletion. As a result, the
pointer no longer pointed to the desired entry during deletion, causing
segmentation faults.
@madmajestro
Copy link
Contributor Author

@nikic
This should hopefully finally fix #582. Its hard to reproduce. I was able to reproduce it by putting an usleep(10000); before the line apc_cache.c:582 (free_entry(cache, entry);) and then used a modified version of your stress-test.

This time, I repeatedly went through the code and examined all the places after locks or the ref_count were released. This was the only place I found where the pointer to the entry was still being used after a release. Unfortunately, I seem to have overlooked this in my last fix.

apc_cache_entry_release(cache, entry);
} else {
/* the entry mustn't be released before it is freed to prevent defragmentation from moving the entry */
free_entry(cache, entry);
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Was there a reason why free_entry() was previously below php_apc_end_try()?

@madmajestro
Copy link
Contributor Author

madmajestro commented Aug 14, 2025

@nikic
I just noticed that the APCu Debian package 5.1.25-2 (packages.sury.org) is based on my proof-of-concept fix, which also fixed this issue. Unfortunately, 5.1.26 doesn't fix this issue. When 5.1.26 is released on packages.sury.org, there may be more issues out there than there are now, as many servers are running Debian derivatives. Therefore, we should consider releasing 5.1.27 before the next PHP minor release and all packages are re-released with the latest versions.

Additionally, I would like to provide a PR as soon as possible that adds size binning to the SMA. This has superior performance in many scenarios and significantly reduces SMA lock contention. It's been passing the stress test and CI for days without any issues. I just want to do more testing and fine-tuning...

@nikic nikic merged commit fe599cd into krakjoe:master Aug 14, 2025
22 checks passed
@madmajestro madmajestro deleted the fix-ref_count-race branch August 15, 2025 09:02
@madmajestro
Copy link
Contributor Author

@nikic
Do you plan to release version 5.1.27 today or tomorrow? As far as I know, a new PHP point release will probably be released tomorrow, and I'm afraid there might be problems again when the current version 5.1.26 is packaged and made available as a Debian package on packages.sury.org.

Also, #588 and #589 could significantly improve performance. I've tested both PRs for hours with various stress tests and haven't found any issues...

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.

2 participants