|
php.net | support | documentation | report a bug | advanced search | search howto | statistics | random bug | login |
[2003-01-06 19:00 UTC] pollita@php.net
This is a note to myself to fix this. When stream_get_filters(true) is called between stream_register_filter() and stream_fitler_(ap|pre)pend(), engine will segfault on script exit. PatchesPull RequestsHistoryAllCommentsChangesGit/SVN commits
|
|||||||||||||||||||||||||||
Copyright © 2001-2025 The PHP GroupAll rights reserved. |
Last updated: Thu Nov 06 16:00:01 2025 UTC |
It seems this error does not occour as a direct result of stream_get_filters but is instead coincidental. I was testing code in the streams/filters implementation in PHP-CVS using the following script: <?php /* Define our filter class */ class rot13_filter extends php_user_filter { function read($length) { $tempstr = parent::read($length); for($i = 0; $i < strlen($tempstr); $i++) if (($tempstr[$i] >= 'A' AND $tempstr[$i] <= 'M') OR ($tempstr[$i] >= 'a' AND $tempstr[$i] <= 'm')) $tempstr[$i] = chr(ord($tempstr[$i]) + 13); else if (($tempstr[$i] >= 'N' AND $tempstr[$i] <= 'Z') OR ($tempstr[$i] >= 'n' AND $tempstr[$i] <= 'z')) $tempstr[$i] = chr(ord($tempstr[$i]) - 13); return $tempstr; } function write($data) { for($i = 0; $i < strlen($data); $i++) if (($data[$i] >= 'A' AND $data[$i] <= 'M') OR ($data[$i] >= 'a' AND $data[$i] <= 'm')) $data[$i] = chr(ord($data[$i]) + 13); else if (($data[$i] >= 'N' AND $data[$i] <= 'Z') OR ($data[$i] >= 'n' AND $data[$i] <= 'z')) $data[$i] = chr(ord($data[$i]) - 13); return parent::write($data); } } var_dump(stream_get_filters(true)); /* Register our filter with PHP */ stream_register_filter("rot13", "rot13_filter") or die("Failed to register filter"); var_dump(stream_get_filters(true)); $fp = fopen("foo-bar.txt","w"); stream_filter_append($fp, "string.rot13"); stream_filter_append($fp, "string.toupper"); stream_filter_append($fp, "rot13"); var_dump(stream_get_filters(true)); fwrite($fp,"This is a test.\n"); fclose($fp); readfile("foo-bar.txt"); print "\n\n"; ?> And discovered a consistently reproducable crash upon script exit. Oddly, compiling with --enable-debug causes the segfault to stop occouring. (Making a backtrace difficult) After exploration I discovered that commenting out one of the occourances of stream_get_filters() would prevent the segfault so I believed the fault to be in that function. But here's the wierd twist: Turns out that if you do something as innocuous as add: $myvar = ""; to the end of that script, the segfault goes away. After putting in a series of watches I tracked the segfault down to the call to: ZEND_DO_FREE(ptr) on line 462 of Zend/zend_alloc.c in shutdown_memory_manager. The value of ptr looks reasonable and is in the same neighborhood as other calls in the i/j loops. I wish I could give you something better to work with but this is a seriously elusive heisenbug. I'll continue to explore the code locally, but I don't pretend to know the Zend engine as well as many of you others. - pollita@php.net CVS: 2003-01-06 ./configure --without-mysql --disable-cgi#0 0x40108fdd in chunk_free (ar_ptr=0x4019ff80, p=0x82ca930) at malloc.c:3131 #1 0x40108ea3 in __libc_free (mem=0x82ca938) at malloc.c:3054 #2 0x080bf61c in shutdown_memory_manager (silent=0, clean_cache=0) at /home/rei/PHP_CVS/php4/Zend/zend_alloc.c:462 #3 0x080a94e6 in php_request_shutdown (dummy=0x0) at /home/rei/PHP_CVS/php4/main/main.c:1069 #4 0x080e25a6 in main (argc=2, argv=0xbffff764) at /home/rei/PHP_CVS/php4/sapi/cli/php_cli.c:801 #5 0x400b5f5c in __libc_start_main (main=0x80e1ca0 <main>, argc=2, ubp_av=0xbffff764, init=0x8059428 <_init>, fini=0x80e288c <_fini>, rtld_fini=0x4000ce30 <_dl_fini>, stack_end=0xbffff75c) at ../sysdeps/generic/libc-start.c:129 Here is the backtrace of the crash, what is indeed most curious is that the crash ONLY occurs when PHP is compiled with -0N optimization flags.Program received signal SIGSEGV, Segmentation fault. _zval_ptr_dtor (zval_ptr=0x73) at /root/src/php4-standard/Zend/zend_execute_API.c:289 289 (*zval_ptr)->refcount--; (gdb) bt #0 _zval_ptr_dtor (zval_ptr=0x73) at /root/src/php4-standard/Zend/zend_execute_API.c:289 #1 0x4036240c in zend_hash_destroy (ht=0x8138f14) at /root/src/php4-standard/Zend/zend_hash.c:543 #2 0x4035d1e2 in _zval_dtor (zvalue=0x809fb1c) at /root/src/php4-standard/Zend/zend_variables.c:51 #3 0x40356fb9 in _zval_ptr_dtor (zval_ptr=0x8147a10) at /root/src/php4-standard/Zend/zend_execute_API.c:291 #4 0x4036240c in zend_hash_destroy (ht=0x4040f56c) at /root/src/php4-standard/Zend/zend_hash.c:543 #5 0x40356db0 in shutdown_executor () at /root/src/php4-standard/Zend/zend_execute_API.c:186 #6 0x4035e0be in zend_deactivate () at /root/src/php4-standard/Zend/zend.c:649 #7 0x40337cb3 in php_request_shutdown (dummy=0x0) at /root/src/php4-standard/main/main.c:942 #8 0x4036e9fe in apache_php_module_main (r=0x8104d44, display_source_mode=0) at /root/src/php4-standard/sapi/apache/sapi_apache.c:61 #9 0x4036f3b7 in send_php (r=0x8104d44, display_source_mode=0, filename=0x0) at /root/src/php4-standard/sapi/apache/mod_php4.c:610 #10 0x4036f565 in send_parsed_php (r=0x8104d44) at /root/src/php4-standard/sapi/apache/mod_php4.c:625 #11 0x08053b34 in ap_invoke_handler () #12 0x0806368c in ap_some_auth_required () #13 0x080636e8 in ap_process_request () #14 0x0805ce2b in ap_child_terminate () #15 0x0805cfbc in ap_child_terminate () #16 0x0805d0d9 in ap_child_terminate () #17 0x0805d5b5 in ap_child_terminate () #18 0x0805dcbd in main () #19 0x400dfa51 in __libc_start_main () from /lib/libc.so.6 this would be the same as the description to/for the problem described here... i suspect that it has something to do with either not cleaning ob_start() buffers manually, or something with header("Location: ") (or a combination of both).. that atleast is regarding my problem this backtrace is from the latest php4-200303181430, but i can also reproduce it on the -STABLE branch (ill post the bt later).Another reproducing script: Happens with HEAD as of today. ./configure --with-gd --with-zlib-dir=/usr --with-mysql --enable-ftp --enable-bcmath --enable-maintainer-zts --enable-sockets --with-gmp=/usr --with-imap --with-imap-ssl=/usr/src/openssl-0.9.6g I've gotten similar results with simpler ./configure lines and simpler scripts, but this is the configuration that is immediately available to me. #!sapi/cli/php <?php class debugfilter extends php_user_filter { function filter($in, $out, &$consumed, $closing) { while ($bucket = stream_bucket_make_writeable($in)) { $bucket->data = strtoupper($bucket->data); stream_bucket_append($out, $bucket); $consumed += strlen($bucket->data); } return PSFS_PASS_ON; } } stream_register_filter("myfilter","debugfilter"); $fp = fopen("test.txt","w"); stream_filter_append($fp, "myfilter"); stream_filter_append($fp, "myfilter"); stream_filter_append($fp, "myfilter"); fwrite($fp, "This is a test.\n"); print "Done.\n"; fclose($fp); // Uncommenting the following 'print' line causes the segfault to stop occuring // print "2\n"; readfile("test.txt"); ?>