-
Notifications
You must be signed in to change notification settings - Fork 7.9k
Fix memory leak of function attribute hash table #8070
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
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you! Could you please add a regression test?
Also, shouldn't this target PHP-8.1? |
How would I write a test that checks for the absence of memory leaks? |
Probably PHP 8.0, as that's where attributes were introduced. Shall I cherry-pick the commit onto 8.0, force push and then change the target branch in GH's interface? |
Just write a test that triggers the code path; we run nightly builds with MSan/ASan enabled, which should catch this.
I usually rebase the local branch onto the new target branch (PHP-8.0, right), force-push, and then change the target branch in the GH UI. Otherwise, some CI get's confused (AppVeyor, and maybe some others). |
This is impossible to trigger as of right now, as there are no native functions with attributes (neither function-level, nor parameter level attributes). As mentioned in my initial message this was found during development of #7921 (which is currently in voting). |
Ah, right. Then it is okay without a test. :) |
Then just the rebase? Or shall this remain on |
Good point! I'm not sure whether there are any (PECL) extensions which use attributes; that memory leak might be relevant to them. Maybe @beberlei knows? |
https://github.com/php/php-src/blob/master/ext/zend_test/test.stub.php The |
looks correct to me |
@TysonAndre Thank you for the review and the hint regarding zend_test. @cmb69 Is this PR looking good to you, or would you like me to make changes? Which target branch should this use? I can integrate zend_test, if you think that would be good. |
@TimWolla, yes that looks good to me. Maybe it's best to target "master" for now; we can still back-port if actually relevant. Do you want to add a test right away? |
7289ce6
to
d15e9f7
Compare
@cmb69 I've rebased onto the current |
Okay, so Cirrus is happy, but Travis is unhappy about this. Probably good that I added a test. However I'm afraid that fixing this double free is above my pay grade. I can't do more than |
Okay, I was hoping that using I'm at my wits end here and frankly I can't spend any more time on this, because this is pure guesswork on my end. Someone more experienced than me will need to take this across the finish line. |
Ah, this is only reproducible with ZTS:
|
I'm only moderately familiar with this code and have gotten stuck and frustrated a lot, especially with opcache. Someone more familiar than me will probably have to take a look. Leaving more context for people looking at this later: https://github.com/php/php-src/tree/master/ext/opcache/jit#running-tests-of-the-jit running locally with
Some of these may help, in combination with
# Run PHPs run-tests.php
script:
- ./travis/test.sh -d opcache.jit_buffer_size=16M -d opcache.jit=tracing
- if [[ "$ARM64" == 1 ]]; then ./travis/test.sh -d opcache.jit_buffer_size=16M -d opcache.jit=function; fi
- if [[ "$ARM64" == 1 ]]; then ./travis/test.sh -d opcache.jit_buffer_size=16M -d opcache.jit=tracing --repeat 2; fi
- sapi/cli/php -d extension_dir=`pwd`/modules -r 'dl("zend_test");' |
@TysonAndre Thank you for taking the time to assist me, I appreciate it and the information are helpful. However I believe I figured it out: There was a second bug lurking in the code, there was a missing call to |
b52ed3c
to
db10b91
Compare
Additional tests may help detect if this is properly finished, e.g.
It seems like this should use the GC_TRY_ADDREF instead of GC_ADDREF macro because attributes can be an immutable array after adding it to opcache's shared memory (for methods, maybe copying from opcache?), not GC_ADDREF. static HashTable *zend_persist_attributes(HashTable *attributes)
{
// ...
HashTable *ptr = zend_shared_memdup_put_free(attributes, sizeof(HashTable));
GC_SET_REFCOUNT(ptr, 2);
GC_TYPE_INFO(ptr) = GC_ARRAY | ((IS_ARRAY_IMMUTABLE|GC_NOT_COLLECTABLE) << GC_FLAGS_SHIFT); static zend_always_inline uint32_t zend_gc_addref(zend_refcounted_h *p) {
ZEND_RC_MOD_CHECK(p);
return ++(p->refcount);
}
static zend_always_inline void zend_gc_try_addref(zend_refcounted_h *p) {
if (!(p->u.type_info & GC_IMMUTABLE)) {
ZEND_RC_MOD_CHECK(p);
++p->refcount;
}
} |
57e5436
to
a9e18d1
Compare
@TysonAndre You are correct: The code was not yet correct for class inheritance. I've now (hopefully) fixed those as well. |
Okay:
So I believe this is ready to go 😃 |
Tests look right and my previous review comments were addressed. ext/opcache/tests/jit/assign_dim_op_007.phpt for travis has nothing to do with attributes, and it's a new test. I don't see anything wrong with it but would (personally) like someone more familiar with opcache to take a look at this before merging it. |
a9e18d1
to
c8edd9c
Compare
Rebased onto the latest master to trigger the new GitHub Actions builds. PTAL 😃 |
c8edd9c
to
bbfdc17
Compare
==109253== 280 (56 direct, 224 indirect) bytes in 1 blocks are definitely lost in loss record 4 of 4 ==109253== at 0x483B7F3: malloc (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so) ==109253== by 0x6D9FA2: __zend_malloc (zend_alloc.c:3068) ==109253== by 0x745138: zend_add_attribute (zend_attributes.c:226) ==109253== by 0x6680D1: zend_add_parameter_attribute (zend_attributes.h:102) ==109253== by 0x66B787: zm_startup_zend_test (test.c:478) ==109253== by 0x7224CD: zend_startup_module_ex (zend_API.c:2202) ==109253== by 0x72252C: zend_startup_module_zval (zend_API.c:2217) ==109253== by 0x734288: zend_hash_apply (zend_hash.c:2011) ==109253== by 0x722C30: zend_startup_modules (zend_API.c:2328) ==109253== by 0x67409B: php_module_startup (main.c:2256) ==109253== by 0x88EDDE: php_cli_startup (php_cli.c:409) ==109253== by 0x890F61: main (php_cli.c:1334)
These tests verify the correct workings of the previous fixes: - Parameter attributes for native functions should not leak memory. - Parameter attributes for native functions should behave as expected.
dbb619d
to
fb7b2cf
Compare
@bwoebi Thanks for your assistance. As the CI was green I've rebased all the trial and error commits into a clean commit history. |
==109253== 280 (56 direct, 224 indirect) bytes in 1 blocks are definitely lost in loss record 4 of 4 ==109253== at 0x483B7F3: malloc (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so) ==109253== by 0x6D9FA2: __zend_malloc (zend_alloc.c:3068) ==109253== by 0x745138: zend_add_attribute (zend_attributes.c:226) ==109253== by 0x6680D1: zend_add_parameter_attribute (zend_attributes.h:102) ==109253== by 0x66B787: zm_startup_zend_test (test.c:478) ==109253== by 0x7224CD: zend_startup_module_ex (zend_API.c:2202) ==109253== by 0x72252C: zend_startup_module_zval (zend_API.c:2217) ==109253== by 0x734288: zend_hash_apply (zend_hash.c:2011) ==109253== by 0x722C30: zend_startup_modules (zend_API.c:2328) ==109253== by 0x67409B: php_module_startup (main.c:2256) ==109253== by 0x88EDDE: php_cli_startup (php_cli.c:409) ==109253== by 0x890F61: main (php_cli.c:1334)
Whoops. I wanted to remove the attributes from the stub file anyway, because they don't do anything. Apparently I missed see also: #7921 (comment) |
Found while implementing #7921: