2

Deliverer 1.1.2 修复使用魔术方法后调用栈丢失的问题

 2 years ago
source link: https://segmentfault.com/a/1190000040656571
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

Deliverer 1.1.2 修复使用魔术方法后调用栈丢失的问题

非常高兴还是有不少朋友在使用这个项目的,从而帮助他们解决了一些线上的问题。

如果你对线上一个项目运行逻辑不熟悉,或者你对某个方法的调用来源不清楚,又或者线上有一个接口不知道是哪里异常退出了,还有线上调用特别耗时,都比较适合使用 Deliverer 来解决,帮助你避免跑路。

https://github.com/zhoumengka...

前几日有一位群友线上遇到一些问题,使用 Deliverer 来排查,但是也还是没能立马解决,于是微信联系了我。在工具使用上和我沟通了下,虽然通过 Deliverer 的历史日志记录最终定位了线上 bug,但是也发现了 Deliverer 工具之前忽略的一个问题:

因为为了尽量减少日志的输出和性能的损耗,只监控了用户自定义的方法和函数,导致一些通过系统的魔术方法,比如__get__call

比如下面这段代码

error_reporting(E_ALL);
ini_set('display_errors',true);
function aaa($a){
    return bbb($a+100);
}

function bbb($b){
    return ccc($b*100);
}

function ccc($c){
    echo 11111;
    return 1;
}

function ddd(){
    return 2;
}
class abc{
    public function test(){
        $this->aaa;
    }

    private function test2($name){
        echo $name;
        $abcd = new abcd();
        call_user_func([$abcd,"test"]);
    }

    public function __get($name)
    {
        return $this->test2($name);
    }
}

class abcd{
    public function test(){
        $this->aaa;
    }

    private function test2($name){
        $this->test3($name);
    }

    private function test3($name){
        echo $name;
    }

    public function __get($name)
    {
        return $this->test2($name);
    }
}

aaa(1234);
ddd();

$abc = new abc();
$abc->test();
$abcd = new abcd();
$abcd->test();
call_user_func([$abcd,"test"]);
24307-1630335728072334 cli /root/deliverer-main/deliverer/extension/test.php
1630335728072690|0x7ff12cc1e030|(nil)|aaa|/root/deliverer-main/deliverer/extension/test.php|56
1630335728072710|0x7ff12cc1e1a0|0x7ff12cc1e030|bbb|/root/deliverer-main/deliverer/extension/test.php|5
1630335728072712|0x7ff12cc1e220|0x7ff12cc1e1a0|ccc|/root/deliverer-main/deliverer/extension/test.php|9
1630335728072725|0x7ff12cc1e030|(nil)|ddd|/root/deliverer-main/deliverer/extension/test.php|57
1630335728072735|0x7ff12cc1e030|(nil)|abc::test|/root/deliverer-main/deliverer/extension/test.php|60
1630335728072749|0x7ff12cc1e200|0x7fff6976a640|abc::test2|/root/deliverer-main/deliverer/extension/test.php|33
1630335728072762|0x7ff12cc1e270|0x7ff12cc1e200|abcd::test|/root/deliverer-main/deliverer/extension/test.php|28
1630335728072764|0x7ff12cc1e390|0x7fff6976a060|abcd::test2|/root/deliverer-main/deliverer/extension/test.php|52
1630335728072766|0x7ff12cc1e400|0x7ff12cc1e390|abcd::test3|/root/deliverer-main/deliverer/extension/test.php|43
1630335728072772|0x7ff12cc1e030|(nil)|abcd::test|/root/deliverer-main/deliverer/extension/test.php|62
1630335728072773|0x7ff12cc1e200|0x7fff6976a640|abcd::test2|/root/deliverer-main/deliverer/extension/test.php|52
1630335728072774|0x7ff12cc1e270|0x7ff12cc1e200|abcd::test3|/root/deliverer-main/deliverer/extension/test.php|43
1630335728072777|0x7ff12cc1e030|(nil)|abcd::test|/root/deliverer-main/deliverer/extension/test.php|63
1630335728072778|0x7ff12cc1e200|0x7fff6976a640|abcd::test2|/root/deliverer-main/deliverer/extension/test.php|52
1630335728072779|0x7ff12cc1e270|0x7ff12cc1e200|abcd::test3|/root/deliverer-main/deliverer/extension/test.php|43

可以看到abcd::test两次通过call_user_func,是没问题的,是一个 callback 的方式,有独立的入栈出栈,但是因为__get是系统方法,没有在日志里记录,所以abc::test2abcd::test2都找不到
0x7fff6976a060父节点。

本来计划是单独监控魔术方法的,但是想了下,单线程模型下,我直接根据时间戳来就行了,直接挂在前一时刻的函数下就行了。

https://github.com/zhoumengka...


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK