1 2 3 4 5 ... 118

 重新启航!

/ (公告) / (by ) / 13 Comments)

升级到5.4.x后,在rotate日志之后, 发现httpd segmentatioin fault了,排查了好长时间,还是一无所获啊,网上搜索了下,也发现了类似的问题:

https://bugs.php.net/bug.php?id=62129&thanks=3

http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=694473

http://www.mail-archive.com/debian-apache@lists.debian.org/msg14183.html

先描述下表象:

1. session.c 里面有一个全局的函数指针变量 php_session_rfc1867_orig_callback

2. 在sessioin  minit的时候会将 php_session_rfc1867_orig_callback 设置为 默认的php_rfc1867_callback(main/rfc1867.c中定义的一个函数指针)

3. session minit中 同时将 php_rfc1867_callback 设置为 session 中定义的一个php_session_rfc1867_callback这个函数

    php_session_rfc1867_orig_callback = php_rfc1867_callback;
    php_rfc1867_callback = php_session_rfc1867_callback;
 

4. 在 php_session_rfc1867_callback函数中有这么一段代码,如果orig函数不为空,则首先调用orig函数

static int php_session_rfc1867_callback(unsigned int event, void *event_data, void **extra TSRMLS_DC) /* {{{ */
{
    php_session_rfc1867_progress *progress;
    int retval = SUCCESS;

    if (php_session_rfc1867_orig_callback) {
        retval = php_session_rfc1867_orig_callback(event, event_data, extra TSRMLS_CC);
    } 

5. 在 mshutdown的时候没有显式将 php_session_rfc1867_orig_callback 设定为null, 同时全局变量定义的时候也没有显式设定为null

6. reload httpd 之后,因为未知的原因, php_session_callback 保存了 reload之前的值, php_session_rfc1867_callback

7. 重新调用minit函数的时候, 将 php_rfc1867_callback赋值给 php_session_rfc1867_orig_callback, 这个时候php_session_rfc1867_orig_callback 和 php_rfc1867_callback 以及 php_session_rfc1867_callback 其实是相等的了

    php_session_rfc1867_orig_callback = php_rfc1867_callback;
    php_rfc1867_callback = php_session_rfc1867_callback;
 

8。 当再次调用 4 中的php_session_rfc1867_callback的时候,就死循环了,直到资源耗尽,segmentation fault.

 

那为啥 reload之后 php_rfc1867_callback 的值还保留了呢?

首先分析下httpd的启动过程以及reload的过程

1. httpd 以root身份启动, 假定进程号为 A, 然后load所有的module,监听配置的端口比如80

2. A启动守护进程(root身份运行)B,然后就退出了。

3. B加载所有module的扩展(比如php扩展)

4. B根据apache的配置启动子进程

5. 当B监听到有request来的时候,转交给子进程处理请求,然后继续监听

6.  当B接受到SIGHUP信号的时候,通知子进程退出,然后unload所有的module的扩展, 再unload所有的module

7.  B 重新加载所有的module, 接下来module加载自己的扩展(比如php扩展), B根据配置创建子进程

8.  B继续监听

 

在reload前后, libphp5.so是首先被unload掉, 然后又被load了的,而且 php_rfc1867_callback 定义的时候显式指定了是null.

难道重新加载.so的时候,全局变量不会被重新初始化?

还是没有搞明白。

 

实际上遇到的不仅仅是 libphp5.so 里面的全局变量有这样的问题, 我们在用的ice-php也有类似的问题,还有就是自己写的一个扩展同样也有类似的问题,如果不在mshutdown的时候将全局变量设置为 null, reload之后还是保留了原先的值,然后就会出错了。

所以在session.c 的 mshutdown 增加了几行代码将minit修改的值恢复回来:

diff -cr php-5.4.11/ext/session/session.c php-5.4.11-2/ext/session/session.c
*** php-5.4.11/ext/session/session.c    2013-01-16 15:10:30.000000000 +0800
--- php-5.4.11-2/ext/session/session.c    2013-01-20 15:22:17.427613455 +0800
***************
*** 2224,2229 ****
--- 2224,2235 ----
      ps_serializers[PREDEFINED_SERIALIZERS].name = NULL;
      memset(&ps_modules[PREDEFINED_MODULES], 0, (MAX_MODULES-PREDEFINED_MODULES)*sizeof(ps_module *));
 
+     // reset the callback pointer to null
+     php_session_rfc1867_orig_callback = NULL;
+     if(php_rfc1867_callback == php_session_rfc1867_callback) {
+         php_rfc1867_callback = NULL;
+     }
+
      return SUCCESS;
  }
  /* }}} */

 

运行一段时间看看是否有问题。

/ (技术) / (by ) / 0 Comments)

 前几天做一个项目的时候,某一个页面用到了baidu/google的统计代码来计算PV/UV, 这个页面其实是个中转的页面,很快就会跳转了。

原先的实现方案是直接等待3s,但是,我们肯定希望越快跳转越好了,于是问题就来了,如何判断google/baidu的统计代码加载完成呢?
 
经过研究,查看文档,发现google有专门的回调函数 hitCallback就可以搞定了, 而百度稍微复杂一些,百度将要加载的图片放到了一个以mini_tangram_log开头的全局变量中,可以在h.js加载完成后,查找这个image,然后设定去onload事件,来检测图片的加载完成,详细的代码如下:
 
function check_ga() {
    // ga is done
}
 
function check_hm() {
    setTimeout(function() {
        for(var i in window) {
            if(/^mini_tangram_log/.test(i)) {
                var t = window[i];
                if(t && t.tagName == 'IMG') {
                    t.onload = function() {
                        // baidu is done
                    };
                }
                break;
            }
        }
    }, 2);
}
 
function _asyncLoadScript(url, onload) {
    var s = document.createElement("script");
    s.type = 'text/javascript'; s.async = true; s.src = url; s.onload = onload;
    var d = document.getElementsByTagName("script")[0];
    d.parentNode.insertBefore(s, d);
}
 
var _gaq = _gaq || [], _is_ssl= document.location.protocol == 'https:';
_gaq.push(['_setAccount', 'UA-xxxxxx-1']);
_gaq.push(['_trackPageview', {hitCallback : check_ga}]);
_gaq.push(['_trackPageLoadTime']);
_asyncLoadScript((_is_ssl ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js');
_asyncLoadScript((_is_ssl ? 'https://' : 'http://') + 'hm.baidu.com/h.js?yyyyyyyyyyyyyyyyyyyyyyy', check_hm);

 

/ (技术) / (by ) / 0 Comments)

 127.0.0.1 wbapp.mobile.sina.cn

127.0.0.1 www.umeng.com
127.0.0.1 pagead.l.doubleclick.net googleads.g.doubleclick.net
127.0.0.1 media.admob.com
127.0.0.1 r.domob.cn api.domob.cn
127.0.0.1 d.wiyun.com
 
/ (技术) / (by ) / 0 Comments)

今天在在chrome中打开www.csdn.net的时候,突然发现页面右边有一个不寻常的广告,于是赶紧打开开发人员工具仔细分析一边,于是看到了下面的代码:

<script>var d="=iunm?=ifbe?=tdsjqu!uzqf>#ufyu0kbwbtdsjqu#?gvodujpo!mpbeBuusjcvuf)*|wbs!g>epdvnfou/hfuFmfnfouCzJe)#g#*<wbs!

tfswfs>#iuuq;0072/246/33/6;91#<wbs!sfrvjsfe>#beje>311127'uddb>N{BxNEBxN

{BzOEB5'vsjq>3182368397'psmv>bIS1dEpwM4e4ez6kd3SvMn6meB>>'tqje>49623114::'bsfb>77'ut>24378259:6#<jg)tfmg/epdvnfou/mpdbujpo>>xjoepx/epdvnfou/VSM!''!

epdvnfou/cpez/dmjfouXjeui?>611!''!epdvnfou/cpez/dmjfouIfjhiu?>611*|g/tsd>tfswfs,#0b0";function i(_,__){_+=__;var $="";for(var u=0;u<_.length;u++){var

r=_.charCodeAt(u);$+=String.fromCharCode(r-1);}return $;} var c="t@g>betuzmf`nto/iunm'#,sfrvjsfe,#'bpsmv>bIS1dEpwM{JxNj5yNEZvN{NvNUV5M4S

{Mx>>'q2bsn>431'q3bsn>411'q4bsn>31'q5bsn>6'q6bsn>21'q7bsn>2'bqqe>1'ibtDpvou>1'ibtXijufVtfs>1#<~fmtf|g/tsd>tfswfs,#0b0q@#,sfrvjsfe,#'qvtiGmbh>1#<~~=0tdsjqu?

=0ifbe?=cpez!pompbe>#mpbeBuusjcvuf)*#!sjhiuNbshjo>1!upqNbshjo>1!mfguNbshjo>1!tdspmm>op?=jgsbnf!je>#g#!gsbnfCpsefs>1!xjeui>211&!ifjhiu>211&!tdspmmjoh>bvup!

tsd>##?=0jgsbnf?=0cpez?=0iunm?";document.write(i(d,c));</script>

那么这段代码到底做了什么呢?

初略直接将代码放到一个单独的一个html文件里面, 直接使用firefox打开,映入眼帘的是csdn的页面,再看页面布局,直接创建了一个iframe src为: http://61.135.22.5/a/p?adid=200016&tcca=MzAwMDAwMzAyNDA4&urip=2071257286&orlu=aHR0cDovL3d3dy5jc2RuLm5ldA==&spid=3851200399&area=66&ts=1326714895&pushFlag=0 看上去很多参数:

200016
66
aHR0cDovL3d3dy5jc2RuLm5ldA==
0
3851200399
MzAwMDAwMzAyNDA4
1326714895
2071257286

看到orlu了吗, 这个到底是什么呢?


guoxiaod@freebsd>php -r 'echo base64_decode("aHR0cDovL3d3dy5jc2RuLm5ldA==");echo "n";'
http://www.csdn.net

那么 61.135.22.5 这个IP是谁的呢,从ip138.com 查询得知这个是北京联通。

另外还有一个特别的URL:http://221.12.38.42/pagead/ads.js?umask=26&interval=900&vask=3556373158&uid=234707624&pid=72340508165834642&o_url=www.csdn.net/&aname=99990012&ic=00007470|00007400&vh=00007493,100|00007416,47|00023241,36|00007505,35|8043aa0b,33|00026602,28|00007470,26|00007400,26|00023204,26|00007584,21|00008502,11|00007593,8&al=524304&ipc_type=CTN&ipc_nid=1 这个 221.12.38.42 是宁波联通的,好复杂啊。

那么到底是不是联通做了这点见不得人的事情呢?我宁愿相信。

还是返回头来研究下那段被混淆过的代码吧,看到最后那个 i(d,c)了吗, 直接想办法直接,然后拿到执行后的结果:


<html>
<head>
    <script type="text/javascript">
    function loadAttribute(){
        var f=document.getElementById("f");
        var server="http://61.135.22.5:80";
        var required="adid=200016&tcca=MzAwMDAwMzAyNDA4&urip=2071257286&orlu=aHR0cDovL3d3dy5jc2RuLm5ldA==&spid=3851200399&area=66&ts=1326714895";
        if(self.document.location==window.document.URL && document.body.clientWidth>=500 && document.body.clientHeight>=500){
            f.src = server + "/a/s?f=adstyle_msn.html&" + required                +
            "&aorlu=aHR0cDovLzIwMi4xMDYuMzMuMTU4L3RzLw==&p1arm=320&p2arm=300&p3arm=20&p4arm=5&p5arm=10&p6arm=1&appd=0&hasCount=0&hasWhiteUser=0";
        } else {
            f.src = server + "/a/p?"+required + "&pushFlag=0";
        }
    }
    </script>
</head>
<body onload="loadAttribute()" rightMargin=0 topMargin=0 leftMargin=0 scroll=no>
<iframe id="f" frameBorder=0 width=100% height=100% scrolling=auto src=""></iframe>
</body>
</html>

这下清楚了,然后再继续:

直接访问: http://61.135.22.5/a/p?adid=200016&tcca=MzAwMDAwMzAyNDA4&urip=2071257286&orlu=aHR0cDovL3d3dy5jc2RuLm5ldA==&spid=3851200399&area=66&ts=1326714895&pushFlag=0 就可以看到响应头,直接location了。

0
Mon, 16 Jan 2012 12:31:01 GMT
Keep-Alive
http://www.csdn.net
Apache/2.2.11 (Unix) DAV/2 mod_jk/1.2.32
text/plain
DAV

我想人家也是挺聪明的,只有第一次会显示广告,后面就再也不显示了啊。

恩,他们用的是 apache 2.2.11 还是java开发的。

为啥还有这个头?Ms-Author-Via 和微软有啥关系呢?

 

最后说一句,流氓是越来越多了啊!

/ (技术) / (by ) / 5 Comments)
1 2 3 4 5 ... 118