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
Welcome back! If you're the original bug submitter, here's where you can edit the bug or add additional notes.
If you forgot your password, you can retrieve your password here.
Password:
Status:
Package:
Bug Type:
Summary:
From: miau dot jp at gmail dot com
New email:
PHP Version: OS:

 

 [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: Sun Dec 22 01:01:30 2024 UTC