Bug #75351 [Com]: Segmentation fault on fatal error during Generator::send

From: Date: Mon, 11 Dec 2017 22:18:06 +0000
Subject: Bug #75351 [Com]: Segmentation fault on fatal error during Generator::send
References: 1  Groups: php.bugs 
Request: Send a blank email to php-bugs+get-213054@lists.php.net to get a copy of this message
Edit report at https://bugs.php.net/bug.php?id=75351&edit=1 ID: 75351 Comment by: tandre@php.net Reported by: bashofmann at gmail dot com Summary: Segmentation fault on fatal error during Generator::send Status: Open Type: Bug Package: Scripting Engine problem Operating System: Ubuntu 14.04.5 LTS (GNU/Linux 4. PHP Version: 7.1.10 Block user comment: N Private report: N New Comment: I'm encountering similar issues, also in Generator->send(). However, the issues I see are in zend_generator_get_gc instead It seems like garbage collection is getting triggered when Generator->send() is getting called, which may be an edge case that isn't handled properly, and may be related to why it's hard to reproduce. I'm using $retval = yield from, $retval = yield some_helper(), yield other_helper() in the code in question, but the bug happens so infrequently I'm not sure which part it is. I haven't checked how deeply nested yields are. I'm using PHP 7.1.9. The source of zend_generators.c is identical for 7.1.9 and 7.1.12 (latest). Stack trace: ``` ... Lines added by newrelic segfault stack trace dumper omitted /usr/local/php/modules/libphp7.so(+0x431748)[0x7ff795959748] /usr/local/php/modules/libphp7.so(+0x42d4fa)[0x7ff7959554fa] /usr/local/php/modules/libphp7.so(zend_gc_collect_cycles+0x78)[0x7ff795956478] /usr/local/php/modules/libphp7.so(gc_possible_root+0x9e)[0x7ff7959560ee] /usr/local/php/modules/libphp7.so(+0x43220c)[0x7ff79595a20c] /usr/local/php/modules/libphp7.so(zend_objects_store_del+0x271)[0x7ff79596c231] /usr/local/php/modules/libphp7.so(zend_generator_update_current+0x1f0)[0x7ff79595a9b0] /usr/local/php/modules/libphp7.so(zend_generator_resume+0x1dd)[0x7ff79595a4ad] /usr/local/php/modules/libphp7.so(+0x433bdf)[0x7ff79595bbdf] /usr/local/php/modules/libphp7.so(+0x4b70c6)[0x7ff7959df0c6] /usr/local/php/modules/libphp7.so(execute_ex+0x2b)[0x7ff79597738b] /usr/local/php/lib/php/20160303/newrelic.so(+0x231bb)[0x7ff78b0b61bb] /usr/local/php/lib/php/20160303/newrelic.so(+0x23802)[0x7ff78b0b6802] /usr/local/php/modules/libphp7.so(+0x4b6985)[0x7ff7959de985] /usr/local/php/modules/libphp7.so(execute_ex+0x2b)[0x7ff79597738b] /usr/local/php/lib/php/20160303/newrelic.so(+0x231bb)[0x7ff78b0b61bb] /usr/local/php/lib/php/20160303/newrelic.so(+0x23802)[0x7ff78b0b6802] ``` I added comments to parts of the code that showed up in my stack trace, and ``` --- a/Zend/zend_generators.c +++ b/Zend/zend_generators.c @@ -275,7 +275,7 @@ static uint32_t calc_gc_buffer_size(zend_generator *generator) /* {{{ */ /* Yield from root references */ if (generator->node.children == 0) { zend_generator *child = generator, *root = generator->node.ptr.root; - while (root != child) { + while (root != child && child != NULL) { // Not sure if checking for null would solve the underlying issue for the other bug reported, and I'm not familiar with how deep the chain goes. child = child->node.parent; size++; } @@ -340,8 +340,8 @@ static HashTable *zend_generator_get_gc(zval *object, zval **table, int *n) /* { if (generator->node.children == 0) { zend_generator *child = generator, *root = generator->node.ptr.root; - while (root != child) { - child = child->node.parent; + while (root != child && child != NULL) { // Not sure if checking for null would solve the underlying issue + child = child->node.parent; // child->node is somehow equal to null when the segfault occurs ZVAL_OBJ(gc_buffer++, &child->std); } } @@ -608,7 +608,7 @@ ZEND_API zend_generator *zend_generator_update_current(zend_generator *generator } while (!root->execute_data && root != generator) { - OBJ_RELEASE(&old_root->std); + OBJ_RELEASE(&old_root->std); // Not caused by this OBJ_RELEASE. It's caused by the below one. old_root = root; root = zend_generator_get_child(&root->node, leaf); @@ -638,10 +638,11 @@ ZEND_API zend_generator *zend_generator_update_current(zend_generator *generator EG(current_execute_data) = original_execute_data; if (!((old_root ? old_root : generator)->flags & ZEND_GENERATOR_CURRENTLY_RUNNING)) { - leaf->node.ptr.root = root; - root->node.parent = NULL; + leaf->node.ptr.root = root; // The root pointer and root->node pointer were changed. + root->node.parent = NULL; // And a parent gets set to null, which might interfere with zend_generator_get_gc + // What happens if there are nested yield froms, though? Would those still have (something)->node.ptr.root point to old_root? if (old_root) { - OBJ_RELEASE(&old_root->std); + OBJ_RELEASE(&old_root->std); // Disassembly shows that this triggers a garbage collection } zend_generator_resume(leaf); return leaf->node.ptr.root; /* this may be updated during zend_generator_resume! */ ``` Previous Comments: ------------------------------------------------------------------------ [2017-10-10 15:15:27] bashofmann at gmail dot com Description: ------------ We are experiencing segmentation faults related to probably fatal errors when using Generator::send. Unfortunately I was not able to create a simple script to reproduce this issue. gdb back trace: (gdb) bt #0 calc_gc_buffer_size (generator=0x7f64d68f4a80) at /build/php7.1-zUmk8m/php7.1-7.1.9/Zend/zend_generators.c:279 #1 zend_generator_get_gc (object=0x7ffe4c963eb0, table=0x7ffe4c963ea8, n=0x7ffe4c963ea4) at /build/php7.1-zUmk8m/php7.1-7.1.9/Zend/zend_generators.c:305 #2 0x00005576280aa23a in gc_mark_grey (ref=0x7f64d68f4a80) at /build/php7.1-zUmk8m/php7.1-7.1.9/Zend/zend_gc.c:499 #3 0x00005576280aa2b6 in gc_mark_grey (ref=<optimized out>) at /build/php7.1-zUmk8m/php7.1-7.1.9/Zend/zend_gc.c:511 #4 0x00005576280aa2b6 in gc_mark_grey (ref=<optimized out>) at /build/php7.1-zUmk8m/php7.1-7.1.9/Zend/zend_gc.c:511 #5 0x00005576280aa346 in gc_mark_grey (ref=<optimized out>) at /build/php7.1-zUmk8m/php7.1-7.1.9/Zend/zend_gc.c:572 #6 0x00005576280aa346 in gc_mark_grey (ref=<optimized out>) at /build/php7.1-zUmk8m/php7.1-7.1.9/Zend/zend_gc.c:572 #7 0x00005576280ab1e8 in gc_mark_roots () at /build/php7.1-zUmk8m/php7.1-7.1.9/Zend/zend_gc.c:598 #8 zend_gc_collect_cycles () at /build/php7.1-zUmk8m/php7.1-7.1.9/Zend/zend_gc.c:1072 #9 0x00005576280aae3e in gc_possible_root (ref=0x7ffe4c963eb0, ref@entry=0x7f64d68f5f80) at /build/php7.1-zUmk8m/php7.1-7.1.9/Zend/zend_gc.c:286 #10 0x00005576280af551 in zend_object_release (obj=0x7f64d68f5f80) at /build/php7.1-zUmk8m/php7.1-7.1.9/Zend/zend_objects_API.h:80 #11 zend_generator_update_current (generator=generator@entry=0x7f64d68f4a80, leaf=0x7f64d68f4a80) at /build/php7.1-zUmk8m/php7.1-7.1.9/Zend/zend_generators.c:667 #12 0x00005576280aefdd in zend_generator_get_current (generator=0x7f64d68f4a80) at /build/php7.1-zUmk8m/php7.1-7.1.9/Zend/zend_generators.h:133 #13 zend_generator_resume (orig_generator=orig_generator@entry=0x7f64d68f4a80) at /build/php7.1-zUmk8m/php7.1-7.1.9/Zend/zend_generators.c:845 #14 0x00005576280afe7f in zim_Generator_send (execute_data=0x7f6555a14070, return_value=0x7ffe4c964210) at /build/php7.1-zUmk8m/php7.1-7.1.9/Zend/zend_generators.c:1001 #15 0x000055762811a0cc in ZEND_DO_FCALL_SPEC_RETVAL_UNUSED_HANDLER () at /build/php7.1-zUmk8m/php7.1-7.1.9/Zend/zend_vm_execute.h:972 #16 0x00005576280c8edb in execute_ex (ex=<optimized out>) at /build/php7.1-zUmk8m/php7.1-7.1.9/Zend/zend_vm_execute.h:429 #17 0x0000557628119f65 in ZEND_DO_FCALL_SPEC_RETVAL_UNUSED_HANDLER () at /build/php7.1-zUmk8m/php7.1-7.1.9/Zend/zend_vm_execute.h:949 #18 0x00005576280c8edb in execute_ex (ex=<optimized out>) at /build/php7.1-zUmk8m/php7.1-7.1.9/Zend/zend_vm_execute.h:429 #19 0x0000557628119f65 in ZEND_DO_FCALL_SPEC_RETVAL_UNUSED_HANDLER () at /build/php7.1-zUmk8m/php7.1-7.1.9/Zend/zend_vm_execute.h:949 #20 0x00005576280c8edb in execute_ex (ex=<optimized out>) at /build/php7.1-zUmk8m/php7.1-7.1.9/Zend/zend_vm_execute.h:429 #21 0x0000557628119f65 in ZEND_DO_FCALL_SPEC_RETVAL_UNUSED_HANDLER () at /build/php7.1-zUmk8m/php7.1-7.1.9/Zend/zend_vm_execute.h:949 #22 0x00005576280c8edb in execute_ex (ex=<optimized out>) at /build/php7.1-zUmk8m/php7.1-7.1.9/Zend/zend_vm_execute.h:429 #23 0x0000557628119f65 in ZEND_DO_FCALL_SPEC_RETVAL_UNUSED_HANDLER () at /build/php7.1-zUmk8m/php7.1-7.1.9/Zend/zend_vm_execute.h:949 #24 0x00005576280c8edb in execute_ex (ex=<optimized out>) at /build/php7.1-zUmk8m/php7.1-7.1.9/Zend/zend_vm_execute.h:429 #25 0x0000557628119ae5 in ZEND_DO_FCALL_SPEC_RETVAL_USED_HANDLER () at /build/php7.1-zUmk8m/php7.1-7.1.9/Zend/zend_vm_execute.h:1076 #26 0x00005576280c8edb in execute_ex (ex=<optimized out>) at /build/php7.1-zUmk8m/php7.1-7.1.9/Zend/zend_vm_execute.h:429 #27 0x0000557628119ae5 in ZEND_DO_FCALL_SPEC_RETVAL_USED_HANDLER () at /build/php7.1-zUmk8m/php7.1-7.1.9/Zend/zend_vm_execute.h:1076 #28 0x00005576280c8edb in execute_ex (ex=<optimized out>) at /build/php7.1-zUmk8m/php7.1-7.1.9/Zend/zend_vm_execute.h:429 #29 0x0000557628119f65 in ZEND_DO_FCALL_SPEC_RETVAL_UNUSED_HANDLER () at /build/php7.1-zUmk8m/php7.1-7.1.9/Zend/zend_vm_execute.h:949 #30 0x00005576280c8edb in execute_ex (ex=<optimized out>) at /build/php7.1-zUmk8m/php7.1-7.1.9/Zend/zend_vm_execute.h:429 #31 0x00005576280aeede in zend_generator_resume (orig_generator=0x7f64de060780) at /build/php7.1-zUmk8m/php7.1-7.1.9/Zend/zend_generators.c:815 #32 0x000055762811a0cc in ZEND_DO_FCALL_SPEC_RETVAL_UNUSED_HANDLER () at /build/php7.1-zUmk8m/php7.1-7.1.9/Zend/zend_vm_execute.h:972 #33 0x00005576280c8edb in execute_ex (ex=<optimized out>) at /build/php7.1-zUmk8m/php7.1-7.1.9/Zend/zend_vm_execute.h:429 #34 0x0000557628119f65 in ZEND_DO_FCALL_SPEC_RETVAL_UNUSED_HANDLER () at /build/php7.1-zUmk8m/php7.1-7.1.9/Zend/zend_vm_execute.h:949 #35 0x00005576280c8edb in execute_ex (ex=<optimized out>) at /build/php7.1-zUmk8m/php7.1-7.1.9/Zend/zend_vm_execute.h:429 #36 0x0000557628119ae5 in ZEND_DO_FCALL_SPEC_RETVAL_USED_HANDLER () at /build/php7.1-zUmk8m/php7.1-7.1.9/Zend/zend_vm_execute.h:1076 #37 0x00005576280c8edb in execute_ex (ex=<optimized out>) at /build/php7.1-zUmk8m/php7.1-7.1.9/Zend/zend_vm_execute.h:429 #38 0x00005576280747e1 in zend_call_function (fci=fci@entry=0x7ffe4c964810, fci_cache=fci_cache@entry=0x7ffe4c9647e0) at /build/php7.1-zUmk8m/php7.1-7.1.9/Zend/zend_execute_API.c:855 #39 0x0000557627f762ad in reflection_method_invoke (execute_data=<optimized out>, return_value=0x7f6555a13610, variadic=0) at /build/php7.1-zUmk8m/php7.1-7.1.9/ext/reflection/php_reflection.c:3342 #40 0x0000557628119c50 in ZEND_DO_FCALL_SPEC_RETVAL_USED_HANDLER () at /build/php7.1-zUmk8m/php7.1-7.1.9/Zend/zend_vm_execute.h:1099 #41 0x00005576280c8edb in execute_ex (ex=<optimized out>) at /build/php7.1-zUmk8m/php7.1-7.1.9/Zend/zend_vm_execute.h:429 #42 0x0000557628119ae5 in ZEND_DO_FCALL_SPEC_RETVAL_USED_HANDLER () at /build/php7.1-zUmk8m/php7.1-7.1.9/Zend/zend_vm_execute.h:1076 #43 0x00005576280c8edb in execute_ex (ex=<optimized out>) at /build/php7.1-zUmk8m/php7.1-7.1.9/Zend/zend_vm_execute.h:429 #44 0x0000557628119f65 in ZEND_DO_FCALL_SPEC_RETVAL_UNUSED_HANDLER () at /build/php7.1-zUmk8m/php7.1-7.1.9/Zend/zend_vm_execute.h:949 #45 0x00005576280c8edb in execute_ex (ex=<optimized out>) at /build/php7.1-zUmk8m/php7.1-7.1.9/Zend/zend_vm_execute.h:429 #46 0x0000557628119f65 in ZEND_DO_FCALL_SPEC_RETVAL_UNUSED_HANDLER () at /build/php7.1-zUmk8m/php7.1-7.1.9/Zend/zend_vm_execute.h:949 #47 0x00005576280c8edb in execute_ex (ex=<optimized out>) at /build/php7.1-zUmk8m/php7.1-7.1.9/Zend/zend_vm_execute.h:429 #48 0x0000557628119f65 in ZEND_DO_FCALL_SPEC_RETVAL_UNUSED_HANDLER () at /build/php7.1-zUmk8m/php7.1-7.1.9/Zend/zend_vm_execute.h:949 #49 0x00005576280c8edb in execute_ex (ex=<optimized out>) at /build/php7.1-zUmk8m/php7.1-7.1.9/Zend/zend_vm_execute.h:429 #50 0x0000557628119f65 in ZEND_DO_FCALL_SPEC_RETVAL_UNUSED_HANDLER () at /build/php7.1-zUmk8m/php7.1-7.1.9/Zend/zend_vm_execute.h:949 #51 0x00005576280c8edb in execute_ex (ex=<optimized out>) at /build/php7.1-zUmk8m/php7.1-7.1.9/Zend/zend_vm_execute.h:429 #52 0x0000557628119f65 in ZEND_DO_FCALL_SPEC_RETVAL_UNUSED_HANDLER () at /build/php7.1-zUmk8m/php7.1-7.1.9/Zend/zend_vm_execute.h:949 #53 0x00005576280c8edb in execute_ex (ex=<optimized out>) at /build/php7.1-zUmk8m/php7.1-7.1.9/Zend/zend_vm_execute.h:429 #54 0x000055762811bf74 in zend_execute (op_array=0x7f6555a67000, op_array@entry=0x7f64f0edbe88, return_value=return_value@entry=0x7f6555a13550) at /build/php7.1-zUmk8m/php7.1-7.1.9/Zend/zend_vm_execute.h:474 #55 0x0000557628083e44 in zend_execute_scripts (type=type@entry=8, retval=0x7f6555a13550, retval@entry=0x0, file_count=file_count@entry=3) at /build/php7.1-zUmk8m/php7.1-7.1.9/Zend/zend.c:1480 #56 0x00005576280234a8 in php_execute_script (primary_file=0x7ffe4c966f90) at /build/php7.1-zUmk8m/php7.1-7.1.9/main/main.c:2552 #57 0x0000557627f0c4ac in main (argc=<optimized out>, argv=<optimized out>) at /build/php7.1-zUmk8m/php7.1-7.1.9/sapi/fpm/fpm/fpm_main.c:1966 Excerpt of zbacktrace (gdb) zbacktrace [0x7f6555a14070] Generator->send(object[0x7f6555a140c0]) [internal function] [0x7f6555a13fd0] rg\core\pow\preparer\handler\GeneratorHandler->returnResponse(object[0x7f6555a14020], object[0x7f6555a14030], reference) /home/researchgate/community/tor_prd/blue/src/core/pow/preparer/handler/GeneratorHandler.php:60 [0x7f6555a13f40] rg\core\pow\preparer\handler\PreparableHandler->returnResponse(object[0x7f6555a13f90], object[0x7f6555a13fa0], array(1)[0x7f6555a13fb0]) /home/researchgate/community/tor_prd/blue/src/core/pow/preparer/handler/PreparableHandler.php:82 ... the code of returnResponse in GeneratorHandler looks rather innocent: public function returnResponse($preparable, \Traversable $iterator, array $data) { if (!is_array($iterator->rawCurrent()) && count($data) === 1) { $data = reset($data); } $preparable->send($data); } The reason why I'm suspecting it has something to do with a fatal error is that it seems to go through this line https://github.com/php/php-src/blob/PHP-7.1.9/Zend/zend_generators.c#L133 in the bt ------------------------------------------------------------------------ -- Edit this bug report at https://bugs.php.net/bug.php?id=75351&edit=1

« previous php.bugs (#213054) next »