php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #60805 Apache/PHP crashes sometimes when using APC
Submitted: 2012-01-19 14:53 UTC Modified: 2012-03-07 21:56 UTC
Votes:4
Avg. Score:4.2 ± 0.8
Reproduced:2 of 2 (100.0%)
Same Version:1 (50.0%)
Same OS:0 (0.0%)
From: ghosh at q-one dot com Assigned: ab (profile)
Status: Closed Package: APC (PECL)
PHP Version: 5.4.0RC5 OS: Ubuntu Natty
Private report: No CVE-ID: None
 [2012-01-19 14:53 UTC] ghosh at q-one dot com
Description:
------------
Today, I upgraded our server to PHP 5.4.0RC5 to try it out.
I found the following problem: Apache/PHP now sometimes (I know this isnt very specific unfortunately) seems to crash. The backtrace quoted below is written to Apache's "error.log". Strangely, I can only reproduce this once after Apache has just started (/etc/init.d/apache2 restart). And when I do some minor modifications to a script the error totally disappears, even after a restart. I cant really pinpoint it down. The only thing I know is that this didn't happen with PHP 5.3.x.

===

/lib/x86_64-linux-gnu/libc.so.6(+0x78a8f)[0x7f5174489a8f]
/lib/x86_64-linux-gnu/libc.so.6(cfree+0x73)[0x7f517448d8e3]
/usr/lib/apache2/modules/libphp5.so(destroy_zend_class+0x255)[0x7f51715015d5]
/usr/lib/apache2/modules/libphp5.so(zend_hash_clean+0x6b)[0x7f5171518ddb]
/usr/lib/php/apc.so(apc_interned_strings_shutdown+0x20)[0x7f516b6fcff0]
/usr/lib/php/apc.so(apc_module_shutdown+0x12a)[0x7f516b6f672a]
/usr/lib/php/apc.so(+0xae6f)[0x7f516b6ebe6f]
/usr/lib/apache2/modules/libphp5.so(+0x461075)[0x7f5171512075]
/usr/lib/apache2/modules/libphp5.so(+0x46653b)[0x7f517151753b]
/usr/lib/apache2/modules/libphp5.so(zend_hash_graceful_reverse_destroy+0x18)[0x7f5171518eb8]
/usr/lib/apache2/modules/libphp5.so(+0x459eb3)[0x7f517150aeb3]
/usr/lib/apache2/modules/libphp5.so(php_module_shutdown+0x2a)[0x7f51714ade5a]
/usr/lib/apache2/modules/libphp5.so(php_module_shutdown_wrapper+0x9)[0x7f51714adf19]
/usr/lib/apache2/modules/libphp5.so(+0x5041f1)[0x7f51715b51f1]
/usr/lib/libapr-1.so.0(+0x1deed)[0x7f51749e0eed]
/usr/lib/libapr-1.so.0(apr_pool_destroy+0x57)[0x7f51749dfded]
/usr/sbin/apache2(+0x562de)[0x7f51752d32de]
/usr/sbin/apache2(+0x566dc)[0x7f51752d36dc]
/usr/sbin/apache2(+0x5694a)[0x7f51752d394a]
/usr/sbin/apache2(ap_mpm_run+0x9e4)[0x7f51752d44f4]
/usr/sbin/apache2(main+0x95a)[0x7f51752a93aa]
/lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xff)[0x7f517442feff]
/usr/sbin/apache2(+0x2b569)[0x7f51752a8569]



Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2012-01-19 22:39 UTC] rasmus@php.net
-Status: Open +Status: Feedback
 [2012-01-19 22:39 UTC] rasmus@php.net
Are you using the latest pecl/apc from svn?
 [2012-01-20 12:24 UTC] ghosh at q-one dot com
I downloaded APC with "pecl download APC". Version 3.1.9 was downloaded. 
Now, after your question, I downloaded with:

svn co http://svn.php.net/repository/pecl/apc/trunk/ apc-trunk

This seems to be the very same version, though. In phpinfo() it says "Revision 308812".

Nevertheless I compiled the SVN version as well just to be sure and it also crashes frequently. As a workaround, for now, I set

apc.cache_by_default=off

At least I can now use APC's variable store facilities. Though the missing cache, of course, still remains a big performance problem.
 [2012-01-20 12:24 UTC] ghosh at q-one dot com
-Status: Feedback +Status: Open
 [2012-01-20 19:58 UTC] uw@php.net
Are you using a thread-safe build? Please, provide your PHP's configure line.

Thanks!
 [2012-01-20 19:58 UTC] uw@php.net
-Status: Open +Status: Feedback
 [2012-01-20 20:32 UTC] uw@php.net
APC: pecl/svn - trunk (Revision 322504)
PHP: 5_4, svn - PHP 5.4.0RC7-dev
Static build: ./configure --enable-apc --disable-apc-pthreadmutex --enable-maintainer-zts --enable-debug

NOTE: I'm showing traces from a patched PHP/APC, line numbers may differ slightly, my copy has some additional php_printf()'s in it.



Some thoughts on this. I am able to reproduce the issue. It takes nothing but a thread-safe/ZTS PHP build with APC support on CLI:

  valgrind sapi/cli/php -d apc.enable_cli=1 -r 'echo 123;'

And there's our crash/invalid free:

==22448== Invalid free() / delete / delete[]
==22448==    at 0x40282A3: free (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==22448==    by 0x8431BB0: zend_hash_destroy (zend_hash.c:560)
==22448==    by 0x84202D4: zend_shutdown (zend.c:819)
==22448==    by 0x83889FB: php_module_shutdown (main.c:2349)
==22448==    by 0x8568679: main (php_cli.c:1371)
==22448==  Address 0x48b0e64 is 568,660 bytes inside a block of size 4,194,304 alloc'd
==22448==    at 0x81A7E67: apc_sma_malloc_ex (apc_sma.c:467)
==22448==    by 0x81A82F7: apc_sma_malloc (apc_sma.c:517)
==22448==    by 0x81B1930: apc_interned_strings_init (apc_string.c:218)
==22448==    by 0x81A6881: apc_module_init (apc_main.c:846)
==22448==    by 0x81967AC: zm_startup_apc (php_apc.c:347)
==22448==    by 0x842806F: zend_startup_module_ex (zend_API.c:1653)
==22448==    by 0x843220E: zend_hash_apply (zend_hash.c:716)
==22448==    by 0x8428578: zend_startup_modules (zend_API.c:1780)
==22448==    by 0x8388615: php_module_startup (main.c:2194)
==22448==    by 0x8565EC7: php_cli_startup (php_cli.c:414)
==22448==    by 0x85684CA: main (php_cli.c:1336)
==22448== 
==22448== Invalid free() / delete / delete[]
==22448==    at 0x40282A3: free (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==22448==    by 0x8431BB0: zend_hash_destroy (zend_hash.c:560)
==22448==    by 0x8413C54: destroy_zend_class (zend_opcode.c:327)
==22448==    by 0x8431BB0: zend_hash_destroy (zend_hash.c:560)
==22448==    by 0x84202D4: zend_shutdown (zend.c:819)
==22448==    by 0x83889FB: php_module_shutdown (main.c:2349)
==22448==    by 0x8568679: main (php_cli.c:1371)
==22448==  Address 0x48b1238 is 569,640 bytes inside a block of size 4,194,304 alloc'd
==22448==    at 0x81A7E67: apc_sma_malloc_ex (apc_sma.c:467)
==22448==    by 0x81A82F7: apc_sma_malloc (apc_sma.c:517)
==22448==    by 0x81B1930: apc_interned_strings_init (apc_string.c:218)
==22448==    by 0x81A6881: apc_module_init (apc_main.c:846)
==22448==    by 0x81967AC: zm_startup_apc (php_apc.c:347)
==22448==    by 0x842806F: zend_startup_module_ex (zend_API.c:1653)
==22448==    by 0x843220E: zend_hash_apply (zend_hash.c:716)
==22448==    by 0x8428578: zend_startup_modules (zend_API.c:1780)
==22448==    by 0x8388615: php_module_startup (main.c:2194)
==22448==    by 0x8565EC7: php_cli_startup (php_cli.c:414)
==22448==    by 0x85684CA: main (php_cli.c:1336)


The invalid delete happens after apc_interned_strings_shutdown(TSRMLS_D) from apc_string.c, http://lxr.php.net/opengrok/xref/PECL/apc/apc_string.c#227:

    227 void apc_interned_strings_shutdown(TSRMLS_D)
    228 {
    229     zend_hash_clean(CG(function_table));
    230     zend_hash_clean(CG(class_table));
    231     zend_hash_clean(EG(zend_constants));
    232 
    233     CG(interned_strings_start) = old_interned_strings_start;
    234     CG(interned_strings_end) = old_interned_strings_end;
    235     zend_new_interned_string = old_new_interned_string;
    236     zend_interned_strings_snapshot = old_interned_strings_snapshot;
    237     zend_interned_strings_restore = old_interned_strings_restore;
    238 
    239     DESTROY_LOCK(APCSG(lock));
    240 }

APC cleans some compile/executor global hash tables, among them CG(class_table). The trace shows that the invalid delete happens after:

  ==22448==    by 0x84202D4: zend_shutdown (zend.c:819)

http://lxr.php.net/opengrok/xref/PHP_5_4/Zend/zend.c#819 shows:

    807 void zend_shutdown(TSRMLS_D) /* {{{ */
    808 {
    809 #ifdef ZEND_SIGNALS
    810 	zend_signal_shutdown(TSRMLS_C);
    811 #endif
    812 #ifdef ZEND_WIN32
    813 	zend_shutdown_timeout_thread();
    814 #endif
    815 	zend_destroy_rsrc_list(&EG(persistent_list) TSRMLS_CC);
    816 	zend_destroy_modules();
    817 
    818 	zend_hash_destroy(GLOBAL_FUNCTION_TABLE);
    819 	zend_hash_destroy(GLOBAL_CLASS_TABLE);
    820 

Thus, one can see there is an issue with the class table. This, I think, is matched by other reports. My trace:

==22448==  Address 0x48b1238 is 569,640 bytes inside a block of size 4,194,304 alloc'd
==22448==    at 0x81A7E67: apc_sma_malloc_ex (apc_sma.c:467)
==22448==    by 0x81A82F7: apc_sma_malloc (apc_sma.c:517)
==22448==    by 0x81B1930: apc_interned_strings_init (apc_string.c:218)

Makes me assume, its about freeing an interned string from APC. At this point, I wondered what APC's zend_hash_clean() call is about: 

    230     zend_hash_clean(CG(class_table));

... which is then followed by Zend's shutdown activity:

    819 	zend_hash_destroy(GLOBAL_CLASS_TABLE);

I wondered why it reads differently and checked if there is a difference between CG(class_table) and GLOBAL_CLASS_TABLE. The two can be different, depending whether ZTS is used or not, http://lxr.php.net/opengrok/xref/PHP_5_3/Zend/zend.c#33: 

     33 #ifdef ZTS
     34 # define GLOBAL_FUNCTION_TABLE		global_function_table
     35 # define GLOBAL_CLASS_TABLE			global_class_table
     36 # define GLOBAL_CONSTANTS_TABLE		global_constants_table
     37 # define GLOBAL_AUTO_GLOBALS_TABLE	global_auto_globals_table
     38 #else
     39 # define GLOBAL_FUNCTION_TABLE		CG(function_table)
     40 # define GLOBAL_CLASS_TABLE			CG(class_table)
     41 # define GLOBAL_AUTO_GLOBALS_TABLE	CG(auto_globals)
     42 # define GLOBAL_CONSTANTS_TABLE		EG(zend_constants)
     43 #endif

If ZTS is used, the class table hash destroyed by Zend during shutdown is not CG(class_table) but global_class_table. global_class_table is a static variable from zend.c, http://lxr.php.net/opengrok/xref/PHP_5_3/Zend/zend.c#100:

    100 #ifdef ZTS
    101 ZEND_API int compiler_globals_id;
    102 ZEND_API int executor_globals_id;
    103 static HashTable *global_function_table = NULL;
    104 static HashTable *global_class_table = NULL;
    105 static HashTable *global_constants_table = NULL;
    106 static HashTable *global_auto_globals_table = NULL;
    107 static HashTable *global_persistent_list = NULL;
    108 #endif

This made me wonder what would happen, if I compiled PHP without ZTS. Guess what: no crash on my box if not using APC with ZTS....

Ulf
 [2012-01-23 11:24 UTC] ghosh at q-one dot com
-Status: Feedback +Status: Open
 [2012-01-23 11:24 UTC] ghosh at q-one dot com
In case this still helps: My configure line according to phpinfo():

	'./configure' '--prefix=/usr' '--datadir=/usr/share/php' '--mandir=/usr/share/man' '--bindir=/usr/bin' '--libdir=/usr/share' '--includedir=/usr/include' '--sysconfdir=/etc' '--with-libdir=lib64' '--with-config-file-path=/etc' '--with-exec-dir=/usr/lib/php/bin' '--disable-debug' '--enable-inline-optimization' '--enable-magic-quotes' '--enable-safe-mode' '--enable-sigchild' '--enable-ctype' '--enable-cli' '--with-openssl' '--with-t1lib' '--with-apxs2=/usr/bin/apxs2' 

I see nothing there about ZTS, though.
 [2012-01-23 14:46 UTC] uw@php.net
Automatic comment from SVN on behalf of uw
Revision: http://svn.php.net/viewvc/?view=revision&revision=322628
Log: Make APC storage handler compile against APC trunk from PECL SVN. Note, it will fail until APC bug #60820 is fixed. Also note, that APC ZTS builds on 5.4 seem to be broken currently (bug #60805). In sum: do not use the APC storage handler at the moment.
 [2012-03-07 21:51 UTC] ab@php.net
-Assigned To: +Assigned To: ab
 [2012-03-07 21:56 UTC] ab@php.net
-Status: Assigned +Status: Closed
 [2012-03-07 21:56 UTC] ab@php.net
This bug has been fixed in SVN.

Snapshots of the sources are packaged every three hours; this change
will be in the next snapshot. You can grab the snapshot at
http://snaps.php.net/.

 For Windows:

http://windows.php.net/snapshots/
 
Thank you for the report, and for helping us make PHP better.

This bug has been fixed in trunk, see #61238
 
PHP Copyright © 2001-2020 The PHP Group
All rights reserved.
Last updated: Tue Feb 25 10:01:23 2020 UTC