-
Notifications
You must be signed in to change notification settings - Fork 209
Fix foreach after the garbage collector is invoked #1850
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: v2.x
Are you sure you want to change the base?
Conversation
Fixed up everything! |
The codebase was successfully formatted using |
I can take a look at the clang-format issue. It looks like there is a memory leak in some tests:
Our tests on GHA don't use debug versions of PHP, so these leaks are not reported there. The offending line in Manager.c allocates the mongo-php-driver/src/MongoDB/Manager.c Line 253 in ae08bbc
I can see that in a number of classes, you have replaced the calls to zend_hash_destroy followed by FREE_HASHTABLE with a single call to zend_hash_release , but left just a single call to zend_hash_destroy in Manager.c.
If you are testing with a debug version of PHP locally, I recommend calling |
I simply compiled both php and the extension with ASAN/LSAN, which is even better than PHP's builtin leak detection, but the issue is that there are many unfixed leaks in PHP itself when dealing with fatal errors (such as the invalid class extension tests, etc), so I just focused on finding leaks in the GC/cycle tests, that's why I missed this one :) Re: the usage of zend_hash_release, I'd actually also replace the remaining places where zend_hash_destroy/HASH_RELEASE is used as it considers the refcount/immutability (not present in this case, but who knows in the future) and automatically frees the hashtable struct as well, though probably it would be better to do this in a separate PR... |
@danog the windows failure is unrelated, and the first impression from Evergreen is that the memory leak is no more. As for the remaining |
Fixes #1776, https://jira.mongodb.org/browse/PHPC-2505, and the equivalent bug triggered when assigning dynamic properties and then unsetting them again.
The underlying issue in both cases is the invocation of
zend_std_get_properties
, which populates theproperties
hashtable in the zend object (not in the interned mongo one).This, in turn, causes the iteration logic to completely skip iteration due to the
if (zend_hash_num_elements(properties) == 0) {
check in theZEND_FE_RESET_R_SPEC_CV_HANDLER
The fix adds custom handlers for
get_property
,write_property
,unset_property
,has_property
,get_property_ptr_ptr
which use a new interned php_properties hashtable, instead of the zend hashtable property.The
zend_gc
handler is also modified to invokeget_properties
instead ofzend_std_get_properties
.The overall implementation mostly works as expected, the only issue is some strange refcounting behavior within the garbage collector on the hashtable returned by get_gc, which sometimes increments the refcount without decrementing it again, leading to a leak of the interned
properties
hashtable (detectable using ASAN); I have asked clarifications regarding that, marking the PR as draft in the meantime.There's also a leftover issue with foreach loops not exiting for whatever reason, still looking into that.