php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #63432 cache expiration of included files cause segfault on apc_request_shutdown()
Submitted: 2012-11-03 18:26 UTC Modified: 2012-12-12 08:08 UTC
From: miau dot jp at gmail dot com Assigned:
Status: Not a bug Package: APC (PECL)
PHP Version: 5.3.18 OS: Linux
Private report: No CVE-ID: None
 [2012-11-03 18:26 UTC] miau dot jp at gmail dot com
Description:
------------
My project has many test cases and phpunit sometimes fails with segfault.
("exec returned: 139" on Jenkins console log)

Here is some information from the core dump. Segfault was occured on
releasing apc_globals.cache_stack.data[16].

---- 

Core was generated by `/usr/bin/php /usr/bin/phpunit --debug'.
Program terminated with signal 11, Segmentation fault.
#0  0x00002b740ecb3213 in apc_deactivate () at /var/tmp/APC/apc_main.c:929

warning: Source file is more recent than executable.
929                 for (i = 0; cache_entry->data.file.classes[i].class_entry != 
NULL; i++) {
(gdb) bt
#0  0x00002b740ecb3213 in apc_deactivate () at /var/tmp/APC/apc_main.c:929
#1  apc_request_shutdown () at /var/tmp/APC/apc_main.c:1042
#2  0x00002b740ecaa775 in zm_deactivate_apc (type=207817184, 
module_number=404473472)
    at /var/tmp/APC/php_apc.c:407
#3  0x00000000005c483c in ?? ()
#4  0x00000000005cf174 in zend_hash_reverse_apply ()
#5  0x00000000005c27bd in ?? ()
#6  0x000000000056f2b5 in php_request_shutdown ()
#7  0x000000000064b953 in ?? ()
#8  0x0000003b6f61d994 in __libc_start_main () from /lib64/libc.so.6
#9  0x0000000000422509 in _start ()
(gdb) p *apc_globals.cache_stack
$37 = {data = 0x24a2be50, capacity = 160, size = 16}
(gdb) p *(apc_cache_entry_t *) apc_globals.cache_stack.data[16]
$59 = {data = {file = {filename = 0x0, op_array = 0x0, functions = 0x0, classes 
= 0x8, halt_offset = 0, 
      exec_refcount = 0x0}, user = {info = 0x0, info_len = 0, val = 0x0, ttl = 
8}}, type = 0 '\000', 
  ref_count = 0, mem_size = 8, pool = 0x0}

---- 

From more investigation, apc_globals.cache_stack.data[16] was below before 
corrupted.

(gdb) p *(apc_cache_entry_t *) apc_globals.cache_stack.data[16]
$7 = {data = {file = {filename = 0x2adcae4e91d8 
"/usr/share/pear/Zend/Validate/Hostname/Jp.php", op_array = 0x2adcae4c60a8, 
      functions = 0x2adcae4e9158, classes = 0x2adcae4e9170, halt_offset = -1, 
exec_refcount = 0x21a0d350}, user = {
      info = 0x2adcae4e91d8 "/usr/share/pear/Zend/Validate/Hostname/Jp.php", 
info_len = -1370726232, val = 0x2adcae4e9158, ttl = 2924384624}},

Although this chache was pushed on apc_globals.cache_stack, long
( > apc.gc_ttl) running of script cause freeing this cache and the same
address seems to be reused by another cache.

Download the following gist and running segfault.php with
"-d apc.gc_ttl=1 -d apc.shm_size=1M" option will reproduce the problem.
(Tested on PHP 5.3.18 and APC 3.1.13)

Test script:
---------------
https://gist.github.com/4008149

Expected result:
----------------
# php -d apc.gc_ttl=1 -d apc.shm_size=1M segfault.php
(no output)
# echo $?
0


Actual result:
--------------
# php -d apc.gc_ttl=1 -d apc.shm_size=1M segfault.php
Segmentation fault
# echo $?
139


Patches

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2012-11-04 06:57 UTC] gopalv@php.net
apc.gc_ttl is set to 1 hour (i.e 3600, not 1) by default, for exactly this reason 
- if execution time > gc_ttl, you will have errors.

Remember apc.gc_ttl does absolutely nothing to the user cache, it merely deletes 
entries off the opcode cache after their refcount > 0 for gc_ttl time in the 
deleted list.

That would cause SEGVs if your script runs for longer.
 [2012-11-04 14:46 UTC] miau dot jp at gmail dot com
I know that. I would be able to avoid the problem by setting
apc.gc_ttl = 0 for running phpunit. But I think it is a problem and
reported here. Is the behavior by design?

By the way, I have noticed that running test script with
"-d apc.gc_ttl=0" detects a memory leak. This might be another problem.

# php -d apc.gc_ttl=0 -d apc.shm_size=1M segfault.php
[Sun Nov  4 17:12:15 2012]  Script:  '/root/segfault_test/segfault.php'
/tmp/pear/temp/APC/apc_zend.c(38) :  Freeing 0x06E8D560 (4 bytes), 
script=/root/segfault_test/segfault.php
=== Total 1 memory leaks detected ===
 [2012-11-04 16:05 UTC] laruence@php.net
it'fine, it's not real memleaks, since php will release all allocated memory in 
request shutdown phase when you using php memory manager.

So we can live with it, thanks
 [2012-12-12 08:08 UTC] ab@php.net
-Status: Open +Status: Not a bug
 [2012-12-12 08:08 UTC] ab@php.net
Config issue, not a bug.
 [2012-12-13 20:55 UTC] miau dot jp at gmail dot com
Okay. I'm sold.

I think it is better that this problem is refered in the documentation
such as "When you run a PHP script over 1 hour, you must set
gc_ttl>3600 or gc_ttl=0", because some developers encounter this
problem at a long CI task.

For example:
  http://edorian.posterous.com/dealing-with-segfaults-while-phpunit-code-cov
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Sat Dec 21 14:01:32 2024 UTC