aterrien / forp-PHP-profiler

A PHP profiler written in C. forp is a lightweight PHP extension which provides the full call stack of your script, with CPU and memory usage, in a plain PHP Array or JSON output.
http://anthonyterrien.com/forp/
MIT License
336 stars 30 forks source link

SIGSEV on NGINX with PHP-FPM 5.4.4 #20

Open ichiriac opened 10 years ago

ichiriac commented 10 years ago

When I enable forp on nginx with php-fpm 5.4 the fpm-server fail to serve the request :

child 15497 exited on signal 11 (SIGSEGV)

ichiriac commented 10 years ago

found this thread, the guy has the same problem : http://serverfault.com/questions/429506/php-fpm-version-5-4-with-nginx-constantly-restarting

ichiriac commented 10 years ago

I've tried with PHP 5.4.23 and found the same problem...

Error message :

Program terminated with signal 11, Segmentation fault.
#0  0x00592bb8 in zval_isref_p (pz=0x5a5a5a5a) at /tmp/php-5.4.23/Zend/zend.h:399
399             return pz->is_ref__gc;

Full Back Trace :

(gdb) bt
#0  0x00592bb8 in zval_isref_p (pz=0x5a5a5a5a) at /tmp/php-5.4.23/Zend/zend.h:399
#1  0x005eda60 in zend_send_by_var_helper_SPEC_CV (execute_data=0xb6726b48)
    at /tmp/php-5.4.23/Zend/zend_vm_execute.h:27102
#2  0x005ee1a0 in ZEND_SEND_VAR_SPEC_CV_HANDLER (execute_data=0xb6726b48)
    at /tmp/php-5.4.23/Zend/zend_vm_execute.h:27216
#3  0x00599dec in execute (op_array=0xb6389d90) at /tmp/php-5.4.23/Zend/zend_vm_execute.h:410
#4  0x001f52f4 in forp_execute (op_array=0xb6389d90) at /tmp/php-5.4.23/ext/forp/forp.c:419
#5  0x0059ab38 in zend_do_fcall_common_helper_SPEC (execute_data=0xb6725f68)
    at /tmp/php-5.4.23/Zend/zend_vm_execute.h:673
#6  0x0059b0e8 in ZEND_DO_FCALL_BY_NAME_SPEC_HANDLER (execute_data=0xb6725f68)
    at /tmp/php-5.4.23/Zend/zend_vm_execute.h:756
#7  0x00599dec in execute (op_array=0xb6753fc0) at /tmp/php-5.4.23/Zend/zend_vm_execute.h:410
#8  0x001f52f4 in forp_execute (op_array=0xb6753fc0) at /tmp/php-5.4.23/ext/forp/forp.c:419
#9  0x0059ab38 in zend_do_fcall_common_helper_SPEC (execute_data=0xb6725af0)
    at /tmp/php-5.4.23/Zend/zend_vm_execute.h:673
#10 0x0059b0e8 in ZEND_DO_FCALL_BY_NAME_SPEC_HANDLER (execute_data=0xb6725af0)
    at /tmp/php-5.4.23/Zend/zend_vm_execute.h:756
#11 0x00599dec in execute (op_array=0xb6747478) at /tmp/php-5.4.23/Zend/zend_vm_execute.h:410
#12 0x00558d4c in zend_execute_scripts (type=8, retval=0x0, file_count=3) at /tmp/php-5.4.23/Zend/zend.c:1319
#13 0x004be920 in php_execute_script (primary_file=0xbe912c8c) at /tmp/php-5.4.23/main/main.c:2502
#14 0x0061c590 in main (argc=3, argv=0xbe912e94) at /tmp/php-5.4.23/sapi/fpm/fpm/fpm_main.c:1933
ichiriac commented 10 years ago

Found the reason : http://www.php.net/manual/en/migration55.internals.php

Extensions cannot override zend_execute() any more and should override zend_execute_ex() instead. 
EG(current_execute_data) is already initialized in zend_execute_ex(), so for compatibility 
extensions may need to use EG(current_execute_data)->prev_execute_data instead.
aterrien commented 10 years ago

I plan to work on it soon. happy new year ! skype you soon :)

ichiriac commented 10 years ago

Glad to see you & happy new year !

I've confused php 5.4 with 5.5 (I'm currently working on 5.4) ... but i've made a commit for handling 5.5 :)

I've digg the problem, forp fails only at the beaba framework dispatch so the closest thing I found is : https://bugs.php.net/bug.php?id=63635

I continue to digg ^^

ichiriac commented 10 years ago

I've located the problem in forp.c line 231 to 238 but I found no way to isolate a php code to reproduce the bug from the cli.

If I remove the ProfileCaption annotation only on this part of the code (I continue tu use it anywhere else) or if disable the specified lines of code in forp.c it works.

The function :

    /**
     * Raise an event
     * @ProfileGroup("event")
     * @ProfileCaption("#1")
     * @param string $event
     * @param array $args
     * @return array
     */
    protected function _raise($event, array $args = null)
    {
        $results = array();
        $events = $this->events();
        if (!empty($events[$event])) {
            foreach (
            $events[$event] as $listener
            ) {
                if (is_array($listener)) {
                    $results[] = call_user_func_array($listener,
                        array($this, $args));
                } else {
                    $results[] = $listener($this, $args);
                }
            }
        }
        return $results;
    }

Fails only when it called Application::dispatch with the following :

    /**
     * Dispatching the specified request
     * @ProfileGroup("dispatch")
     * @param string $url
     * @param array $params
     * @throws \Exception
     */
    public function dispatch($method = null, $url = null, array $params = null)
    {

        $this->_raise(
            self::E_DISPATCH,
            array(
            'request' => $url,
            'params' => $params
            )
        );

Values are :

E_DISPATCH = 'onDispatch';
 $url = null;
 $params = array();