php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #64827 Segfault in zval_mark_grey (zend_gc.c)
Submitted: 2013-05-13 15:17 UTC Modified: 2014-02-10 15:47 UTC
Votes:1
Avg. Score:5.0 ± 0.0
Reproduced:1 of 1 (100.0%)
Same Version:1 (100.0%)
Same OS:1 (100.0%)
From: odoucet@php.net Assigned: laruence
Status: Assigned Package: optimizer (PECL)
PHP Version: 5.4.15 OS: Linux
Private report: No CVE-ID:
Have you experienced this issue?
Rate the importance of this bug to you:

 [2013-05-13 15:17 UTC] odoucet@php.net
Description:
------------
Bug cannot be reproduced easily, as it requires a Magento install with many 
products in it.
Bug can be reproduced on PHP 5.4.15 and 5.3.25
It does not happen when using cgi mode (only on FastCGI). I assume memory 
management is not handled equally between these 
modes.

Running a specific page on Magento, page is rendered correctly, but at the end a 
SIGSEGV happens on PHP process.

Program received signal SIGSEGV, Segmentation fault.
zval_mark_grey (pz=0x272afb8) at /usr/src/build/php-5.4.15/Zend/zend_gc.c:388

(if needed, you can check source code here : http://svn.php.net/viewvc/php/php-
src/trunk/Zend/zend_gc.c?view=markup)

Tell me how I can help debug this error, as I cannot provide a reproducible 
code.

Expected result:
----------------
result page complete with no error

Actual result:
--------------
result page complete + SIGSEGV of the process after, which leads to streange 
behaviour depending on server used (nginx hides 
the segfault, Apache concatenates a 500 error page if used with mod_fcgid).

(gdb) bt
#0  zval_mark_grey (pz=0x272afb8) at /usr/src/build/php-
5.4.15/Zend/zend_gc.c:388
#1  0x00000000007fafe5 in zval_mark_grey (pz=0x272afb8) at /usr/src/build/php-
5.4.15/Zend/zend_gc.c:432
#2  0x00000000007fbf05 in gc_mark_roots () at /usr/src/build/php-
5.4.15/Zend/zend_gc.c:501
#3  gc_collect_cycles () at /usr/src/build/php-5.4.15/Zend/zend_gc.c:795
#4  0x00000000007fc290 in gc_zval_possible_root (zv=<optimized out>) at 
/usr/src/build/php-5.4.15/Zend/zend_gc.c:166
#5  0x00000000007fe297 in zend_object_std_dtor (object=0x390ab38) at 
/usr/src/build/php-5.4.15/Zend/zend_objects.c:54
#6  0x00000000007fe2c9 in zend_objects_free_object_storage (object=0x272afb8) at 
/usr/src/build/php-
5.4.15/Zend/zend_objects.c:137
#7  0x000000000080406b in zend_objects_store_del_ref_by_handle_ex (handle=
<optimized out>, handlers=<optimized out>)
    at /usr/src/build/php-5.4.15/Zend/zend_objects_API.c:221
#8  0x0000000000804093 in zend_objects_store_del_ref (zobject=0x390b088) at 
/usr/src/build/php-
5.4.15/Zend/zend_objects_API.c:173
#9  0x00000000007ce03d in _zval_dtor (zvalue=<optimized out>) at 
/usr/src/build/php-5.4.15/Zend/zend_variables.h:35
#10 _zval_ptr_dtor (zval_ptr=0x39781f8) at /usr/src/build/php-
5.4.15/Zend/zend_execute_API.c:438
#11 0x00000000007e9200 in zend_hash_destroy (ht=0x3978130) at 
/usr/src/build/php-5.4.15/Zend/zend_hash.c:560
#12 0x00000000007db01d in _zval_dtor_func (zvalue=0x390acd0) at 
/usr/src/build/php-5.4.15/Zend/zend_variables.c:45
#13 0x00000000007ce03d in _zval_dtor (zvalue=<optimized out>) at 
/usr/src/build/php-5.4.15/Zend/zend_variables.h:35
#14 _zval_ptr_dtor (zval_ptr=0x390d798) at /usr/src/build/php-
5.4.15/Zend/zend_execute_API.c:438
#15 0x00000000007fe297 in zend_object_std_dtor (object=0x38e4fb8) at 
/usr/src/build/php-5.4.15/Zend/zend_objects.c:54
#16 0x00000000007fe2c9 in zend_objects_free_object_storage (object=0x272afb8) at 
/usr/src/build/php-
5.4.15/Zend/zend_objects.c:137
#17 0x000000000080406b in zend_objects_store_del_ref_by_handle_ex (handle=
<optimized out>, handlers=<optimized out>)
    at /usr/src/build/php-5.4.15/Zend/zend_objects_API.c:221
#18 0x0000000000804093 in zend_objects_store_del_ref (zobject=0x3992400) at 
/usr/src/build/php-
5.4.15/Zend/zend_objects_API.c:173
#19 0x00000000007ce03d in _zval_dtor (zvalue=<optimized out>) at 
/usr/src/build/php-5.4.15/Zend/zend_variables.h:35
#20 _zval_ptr_dtor (zval_ptr=0x39922f8) at /usr/src/build/php-
5.4.15/Zend/zend_execute_API.c:438
#21 0x00000000007e9200 in zend_hash_destroy (ht=0x2533ab8) at 
/usr/src/build/php-5.4.15/Zend/zend_hash.c:560
#22 0x00000000007db01d in _zval_dtor_func (zvalue=0x2528948) at 
/usr/src/build/php-5.4.15/Zend/zend_variables.c:45
#23 0x00000000007ce03d in _zval_dtor (zvalue=<optimized out>) at 
/usr/src/build/php-5.4.15/Zend/zend_variables.h:35
#24 _zval_ptr_dtor (zval_ptr=0x2518c40) at /usr/src/build/php-
5.4.15/Zend/zend_execute_API.c:438
#25 0x00000000007fe297 in zend_object_std_dtor (object=0x250cd28) at 
/usr/src/build/php-5.4.15/Zend/zend_objects.c:54
#26 0x00000000007fe2c9 in zend_objects_free_object_storage (object=0x272afb8) at 
/usr/src/build/php-
5.4.15/Zend/zend_objects.c:137
#27 0x000000000080406b in zend_objects_store_del_ref_by_handle_ex (handle=
<optimized out>, handlers=<optimized out>)
    at /usr/src/build/php-5.4.15/Zend/zend_objects_API.c:221
#28 0x0000000000804093 in zend_objects_store_del_ref (zobject=0x250cb78) at 
/usr/src/build/php-
5.4.15/Zend/zend_objects_API.c:173
#29 0x00000000007ce03d in _zval_dtor (zvalue=<optimized out>) at 
/usr/src/build/php-5.4.15/Zend/zend_variables.h:35
#30 _zval_ptr_dtor (zval_ptr=0x2533c30) at /usr/src/build/php-
5.4.15/Zend/zend_execute_API.c:438
#31 0x00000000007e9200 in zend_hash_destroy (ht=0x2528898) at 
/usr/src/build/php-5.4.15/Zend/zend_hash.c:560
#32 0x00000000007db01d in _zval_dtor_func (zvalue=0x2523e80) at 
/usr/src/build/php-5.4.15/Zend/zend_variables.c:45
#33 0x00000000007ce03d in _zval_dtor (zvalue=<optimized out>) at 
/usr/src/build/php-5.4.15/Zend/zend_variables.h:35
#34 _zval_ptr_dtor (zval_ptr=0x25336d0) at /usr/src/build/php-
5.4.15/Zend/zend_execute_API.c:438
#35 0x00000000007fe297 in zend_object_std_dtor (object=0x2537758) at 
/usr/src/build/php-5.4.15/Zend/zend_objects.c:54
#36 0x00000000007fe2c9 in zend_objects_free_object_storage (object=0x272afb8) at 
/usr/src/build/php-
5.4.15/Zend/zend_objects.c:137
#37 0x000000000080406b in zend_objects_store_del_ref_by_handle_ex (handle=
<optimized out>, handlers=<optimized out>)
    at /usr/src/build/php-5.4.15/Zend/zend_objects_API.c:221
#38 0x0000000000804093 in zend_objects_store_del_ref (zobject=0x25376c8) at 
/usr/src/build/php-
5.4.15/Zend/zend_objects_API.c:173
#39 0x00007fc2385281a7 in accel_fast_hash_destroy (ht=<optimized out>) at 
/usr/src/build/ZendOptimizerPlus/ZendAccelerator.c:2141
#40 accel_fast_zval_ptr_dtor (zval_ptr=<optimized out>) at 
/usr/src/build/ZendOptimizerPlus/ZendAccelerator.c:2162
#41 0x00007fc23852823f in accel_clean_non_persistent_class (pce=<optimized out>) 
at 
/usr/src/build/ZendOptimizerPlus/ZendAccelerator.c:2238
#42 0x00000000007e8f73 in zend_hash_reverse_apply (ht=0x2174c60, 
apply_func=0x7fc2385281f0 <accel_clean_non_persistent_class>)
    at /usr/src/build/php-5.4.15/Zend/zend_hash.c:799
#43 0x00007fc238528042 in zend_accel_fast_shutdown () at 
/usr/src/build/ZendOptimizerPlus/ZendAccelerator.c:2290
#44 0x00007fc23852bddd in accel_deactivate () at 
/usr/src/build/ZendOptimizerPlus/ZendAccelerator.c:2319
#45 0x00000000007d16be in zend_llist_apply (l=<optimized out>, func=0x7cd270 
<zend_extension_deactivator>)
    at /usr/src/build/php-5.4.15/Zend/zend_llist.c:193
#46 0x00000000007d0c7b in shutdown_executor () at /usr/src/build/php-
5.4.15/Zend/zend_execute_API.c:246
#47 0x00000000007dc302 in zend_deactivate () at /usr/src/build/php-
5.4.15/Zend/zend.c:938
#48 0x000000000077dfbc in php_request_shutdown (dummy=<optimized out>) at 
/usr/src/build/php-5.4.15/main/main.c:1800
#49 0x000000000088c10c in main (argc=<optimized out>, argv=<optimized out>) at 
/usr/src/build/php-
5.4.15/sapi/cgi/cgi_main.c:2502


[...]
with breakpoint line 388: 
(gdb) print *pz
$9 = {value = {lval = 743, dval = 3.6709077486004618e-321, str = {val = 0x2e7 
<Address 0x2e7 out of bounds>, len = 16560416}, 
ht = 0x2e7,
    obj = {handle = 743, handlers = 0xfcb120}}, refcount__gc = 0, type = 5 
'\005', is_ref__gc = 0 '\000'}
(gdb) print obj
$10 = <optimized out>


Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2013-05-13 15:33 UTC] johannes@php.net
-Status: Open +Status: Not a bug
 [2013-05-13 15:33 UTC] johannes@php.net
Do not file bugs when you have Zend extensions (zend_extension=)
loaded. Examples are Zend Optimizer, Zend Debugger, Turck MM Cache,
APC, Xdebug and ionCube loader.  These extensions often modify engine
behavior which is not related to PHP itself.

.
 [2013-05-14 02:54 UTC] laruence@php.net
-Status: Not a bug +Status: Re-Opened -Package: *General Issues +Package: optimizer
 [2013-05-14 02:56 UTC] laruence@php.net
-Status: Re-Opened +Status: Open
 [2013-05-14 15:40 UTC] rasmus@php.net
I can confirm I am seeing these too occasionally. As far as I can tell they 
happen very infrequently, but when they happen it is usually on a request that 
was interrupted due to hitting the memory limit. 

Here is a backtrace with full symbols: https://gist.github.com/anonymous/5576932
 [2013-05-19 15:02 UTC] laruence@php.net
-Assigned To: +Assigned To: dmitry
 [2013-05-19 15:02 UTC] laruence@php.net
hmm, dmitry, before I look into this, maybe you have some hints?

thanks :)
 [2013-05-19 22:02 UTC] odoucet@php.net
bug still applies on PHP 5.5.0rc1
Backtrace with this version : https://gist.github.com/odoucet/5609218
 [2013-06-05 11:32 UTC] arjen at react dot com
https://bugs.php.net/bug.php?id=64868 also crashes in zval_mark_grey
 [2013-06-14 18:48 UTC] ircmaxell@php.net
Can you attempt to reproduce this using PHP from this branch: 
https://github.com/ircmaxell/php-src/tree/zval_mark_grey_tail_recursion ? I was 
working on fixing another issue, and would like to see if it solves this as 
well... I don't expect it to, but if it does that would be more justification for 
this refactor.

Thanks!
 [2013-06-17 12:01 UTC] odoucet@php.net
I tried reproducing this bug with your branch 'zval_mark_grey_tail_recursion' (commit bc785a8eea). 
It still produces a segfault, but not at the same place.

With PHP 5.5.0rc1, segfault happens _after_ the page is loaded.
With your version, it happens before any page output : 

Program received signal SIGSEGV, Segmentation fault.
zend_objects_store_del_ref_by_handle_ex (handle=47, handlers=0x101b440)
    at /usr/src/build/php/php-src-zval_mark_grey_tail_recursion/Zend/zend_objects_API.c:183

Backtrace seems recursive, so I posted a snippet here : 
https://gist.github.com/odoucet/5796378
 [2013-06-17 15:09 UTC] ircmaxell@php.net
odoucet,

Can you follow up in the comment thread for the gist (let's keep that thread 
there, as it'll keep noise out of here): 
https://gist.github.com/odoucet/5796378/#comment-846571 ? Thanks!
 [2013-06-18 11:39 UTC] ircmaxell@php.net
So digging through the original backtrace that you posted on the issue, I see what's going on.

Basically, the garbage collector is being fired during the destruction of an object. This causes 
zval_mark_grey() to run on the partially destroyed object (specifically the hash table) and hence the segfault 
when it tries to access previously free()'d memory.

I am still working out the exact circumstances this takes to be triggered (to work on a fix), but what it 
seems like is that the object's zval still exists during destruction here: 
http://lxr.php.net/xref/PHP_TRUNK/Zend/zend_objects_API.c#172 which then could still be found by reference by 
the garbage collector.

Off the top of my head, there appear to be two basic ways of fixing this. The first would be to put a lock on 
the garbage collector to prevent it from being run during any dtor call (zval_dtor, zval_ptr_dtor, 
zend_object_std_dtor, etc). This may be the simple "hack" to prevent the segfault.

The second possible solution here (and likely better) would be to edit zend_objects_store_del_ref_by_handle_ex 
to also accept the object's zval. This would allow it to properly set the zval's type to IS_NULL on 
destruction here: http://lxr.php.net/xref/PHP_TRUNK/Zend/zend_objects_API.c#217 just like is currently done 
for arrays here: http://lxr.php.net/xref/PHP_5_3/Zend/zend_variables.c#44

However that's an API change, which may have a larger impact than desired (although the only places in core 
that use it are the object API and the GC).

I'm going to experiment some more today and will post back more findings...
 [2013-06-20 10:19 UTC] laruence@php.net
-Assigned To: dmitry +Assigned To: laruence
 [2013-06-20 10:19 UTC] laruence@php.net
@odoucet is that possible that you could give me a access to you box which can 
reproduce this segfault?

thanks
 [2013-06-20 14:18 UTC] odoucet@php.net
Sorry, application is too difficult to package and there is some private data in 
it. ATM, we should go on with our previous tests : you provide branches and I test 
it :(
 [2013-06-20 14:35 UTC] arjen at react dot com
Any chance fixing #64896 or two of the three issues in #63481 helps resolving 
this problem?

Those bugs DO have simple scripts to reproduce them and also show 
zend_hash_destroy/zend_objects_free_object_storage combined with 
zval_dtor/zval_ptr_dtor/zend_object_std_dtor in the backtraces...

#64896 even contains gc_collect_cycles in the bt, however it does not crash 
during shutdown..
 [2013-06-25 05:49 UTC] laruence@php.net
Automatic comment on behalf of laruence
Revision: http://git.php.net/?p=php-src.git;a=commit;h=157ccaf507b7a94c43db4ec1b7321aac5cc68e8b
Log: Fixed bug #64827 Segfault in zval_mark_grey (zend_gc.c)
 [2013-06-25 05:49 UTC] laruence@php.net
-Status: Assigned +Status: Closed
 [2013-11-17 09:30 UTC] laruence@php.net
Automatic comment on behalf of laruence
Revision: http://git.php.net/?p=php-src.git;a=commit;h=157ccaf507b7a94c43db4ec1b7321aac5cc68e8b
Log: Fixed bug #64827 Segfault in zval_mark_grey (zend_gc.c)
 [2014-02-10 15:47 UTC] odoucet@php.net
-Status: Closed +Status: Assigned
 [2014-02-10 15:47 UTC] odoucet@php.net
I still experience this bug with latest version PHP 5.4.25 : 
https://gist.github.com/odoucet/8918221
 
PHP Copyright © 2001-2014 The PHP Group
All rights reserved.
Last updated: Sun Apr 20 01:02:05 2014 UTC