win2003使用preg_match_all导致apache崩溃解决办法

Apache/2.2.9 (Win32) + PHP/5.2.17,在使用正则表达式 preg_match_all (如 preg_match_all("/ni(.*?)wo/", $html, $matches);)进行分析匹配比较长的字符串 $html 时(大于10万字节,一般用于分析采集回来的网页源码),Apache服务器会崩溃自动重启。

在Apache错误日志里有这样的提示:

[Thu Apr 11 18:31:31 2013] [notice] Parent: child process exited with status 128 -- Restarting.
[Thu Apr 11 18:31:31 2013] [notice] Apache/2.2.9 (Win32) PHP/5.2.17 configured -- resuming normal operations
[Thu Apr 11 18:31:31 2013] [notice] Server built: Jun 13 2008 04:04:59
[Thu Apr 11 18:31:31 2013] [notice] Parent: Created child process 2964
[Thu Apr 11 18:31:31 2013] [notice] Disabled use of AcceptEx() WinSock2 API
[Thu Apr 11 18:31:31 2013] [notice] Child 2964: Child process is running
[Thu Apr 11 18:31:31 2013] [notice] Child 2964: Acquired the start mutex.
[Thu Apr 11 18:31:31 2013] [notice] Child 2964: Starting 350 worker threads.
[Thu Apr 11 18:31:31 2013] [notice] Child 2964: Listening on port 80.

经过查阅Apache官方以及论坛资料后,发现win平台下用正则 preg_match_all 或preg_match 分析比较长的字符串时,导致apache崩溃重启的原因是windows平台下默认分配的线程堆栈空间 ThreadStackSize 太小导致的。 win32默认只有256KB,而在 linux下默认值是 8M,这就是为什么同样的程序在 linux平台下正常,而在 win平台下不正常的原因。

根据PCRE library的官方说明:256 KB 的堆栈空间对应的pcre.recursion_limit大小应该不超过524。
Here is a table of safe values of pcre.recursion_limit for a variety of executable stack sizes:
下面就是一张Stacksize和pcre.recursion_limit对应的建议安全值,超过这个数值就极有可能发生堆栈溢出,apache crash:

Stacksize   pcre.recursion_limit
 64 MB      134217
 32 MB      67108
 16 MB      33554
  8 MB      16777
  4 MB      8388
  2 MB      4194
  1 MB      2097
512 KB      1048
256 KB      524
如果你没有调整堆栈大小,就必须在使用正则的PHP页面最开头加入:

<?php
ini_set("pcre.recursion_limit", "524"); // PHP default is 100,000.
?>

查看具体的错误可以使用下面的代码:

 代码如下 复制代码
$resultsArray = preg_match_all("/table.*?<a>/isU", $html, $contents);
if ($resultsArray === 0){
echo get_pcre_err();
}
function get_pcre_err(){
        $pcre_err = preg_last_error();  // PHP 5.2 and above.
        if ($pcre_err === PREG_NO_ERROR) {
            $msg = 'Successful non-match.';
        } else {
            // preg_match error!
            switch ($pcre_err) {
                case PREG_INTERNAL_ERROR:
                    $msg = 'PREG_INTERNAL_ERROR';
                    break;
                case PREG_BACKTRACK_LIMIT_ERROR:
                    $msg = 'PREG_BACKTRACK_LIMIT_ERROR';
                    break;
                case PREG_RECURSION_LIMIT_ERROR:
                    $msg = 'PREG_RECURSION_LIMIT_ERROR';
                    break;
                case PREG_BAD_UTF8_ERROR:
                    $msg = 'PREG_BAD_UTF8_ERROR';
                    break;
                case PREG_BAD_UTF8_OFFSET_ERROR:
                    $msg = 'PREG_BAD_UTF8_OFFSET_ERROR';
                    break;
                default:
                    $msg = 'Unrecognized PREG error';
                    break;
            }
        }
    return($msg);
}

    对于正则的修饰符 isU 说明:
i: 表示in-casesensitive,即大小写不敏感
s: PCRE_DOTALL,表示点号可以匹配换行符。
U: 表示PCRE_UNGREEDY,表示非贪婪,相当于perl/python语言的.*?,在匹配过程中,对于.*正则,一有匹配立即执行,而不是等.*搜索了所有字符再一一返回
    在使用正则表达式时,我们应该尽量避免递归调用,递归容易导致堆栈溢出。比如:
/<table((?!<table).)*?</a>/isU 就会发生错误,而使用 /<table.*?</a>/i 就正常。

 那么如何增加win平台下 ThreadStackSize 的大小呢? 在apache的配置文件 httpd.conf 里启用 “Include conf/extra/httpd-mpm.conf”(删除前面的注释#),然后在 httpd-mpm.conf 文件里的 mpm_winnt_module 配置模块里设置 “ThreadStackSize 8400000”即可(大约8M)。

 代码如下 复制代码

<IfModule mpm_winnt_module>
    ThreadStackSize 8400000
    ThreadsPerChild      200
    MaxRequestsPerChild    10000
    Win32DisableAcceptEx
</IfModule>

这里需要注意的是,32位的Apache程序只能最多使用大约2GB内存空间! 因此,ThreadStackSize 和ThreadsPerChild 的值相乘后(8M * 200)不应该超过2G,否则无法启动apache,出现的错误日志如下:
[Thu Apr 11 20:02:45 2013] [crit] (OS 8)存储空间不足,无法处理此命令。  : Child 4832: _beginthreadex failed. Unable to create all worker threads. Created 212 of the 220 threads requested with the ThreadsPerChild configuration directive.
    通过上面的提示,飘易可以告诉大家的是在我的这台服务器上,当线程堆栈大小设为8M时,我可以设置的线程数最多是212个。

时间: 2024-08-23 01:24:07

win2003使用preg_match_all导致apache崩溃解决办法的相关文章

win2003下PHP使用preg_match_all导致apache崩溃问题的解决方法_Linux

小编的平台是windows server 2003(32位系统) + Apache/2.2.9 (Win32) + PHP/5.2.17,在使用正则表达式 preg_match_all (如 preg_match_all("/ni(.*?)wo/", $html, $matches);)进行分析匹配比较长的字符串 $html 时(大于10万字节,一般用于分析采集回来的网页源码),Apache服务器会崩溃自动重启.     在Apache错误日志里有这样的提示: 复制代码 代码如下: [

05.php_pdo引用不恰当libmysql.dll导致Apache崩溃

05.php_pdo引用不恰当libmysql.dll导致Apache崩溃 郑昀 2010 隶属于<07.杂项>小节 现象 在测试环境Windows XP/2003+PHP v5.2.14+Apache v2.2下,使用php_pdo对象试图连接 MySql 数据库服务时,apache的error.log中什么也没报告,httpd.exe 二话不说径直崩溃. 在 php.ini 中注释掉 extension=php_pdo.dll 后,Apache则不再崩溃.   解决方法 该环境在 %SYS

剑灵崩溃怎么办?剑灵崩溃解决办法

剑灵崩溃原因分析 安装剑灵组件失败,玩游戏时出现系统摄错,闪退,或提示服务器无法连接或服务器维护中. 可能出现的原因 1.没有安装剑灵必装组件了 2.msvcrdtd.dll未被正确编译 3.本地防火墙给拦截了 解决办法 1.下载一个QQ电脑管家,然后我们把它下载到电脑并安装, 2.之后我们打开找到"电脑诊所"然后进入后搜索"剑灵崩溃"找到方法点击进入 3.进入后如图所示我们点击修复即可解决你的问题.

Edge浏览器在Win10 14942中崩溃 解决办法来了

微软上周推送了Windows 10 Build 14942版本更新,在带来部分小功能改进的同时也引发了一些新毛病. 有不少用户向微软投诉,在升级Build 14942之后Edge浏览器频繁崩溃.好在微软已经很快找到了解决办法. 微软建议那些遭遇Edge浏览器崩溃的用户在PowerShell中运行以下命令: Get-ChildItem'HKCU: Software Classes Local Settings Software Microsoft Windows CurrentVersion Ap

WordPress数据库修改表前缀导致错误及解决办法

WordPress 默认的数据表前缀是『wp_』:(注:这是默认的数据表,如果安装了其他插件有可能生成其他 wp_ 开头的数据表)     wp_commentmeta    wp_comments    wp_links    wp_options    wp_postmeta    wp_posts    wp_terms    wp_term_relationships    wp_term_taxonomy    wp_usermeta    wp_users 第一步:那么第一件事就是把

ubuntu 交换分区挂载出错导致开机乱码解决办法

首先,什么是交换分区?我们可以等同于虚拟内存.在我们安装ubutu的时候,我们可以先分出一个物理内存1.5倍-2倍的大小作为交换分区,我就这样做了,最终出现了这个问题. 其次,分区的挂载.linux中硬盘数据要被读取必须有一个挂载的过程,如果打算一开机就挂载上,就要开机自动挂载.我读了一些文章后发现交换分区开机自动挂载有一个加密的过程,我想应该是权限控制的问题. 最后我是怎么解决的呢? 1.找出当初用来做交换分区的磁盘分区. 安装了一个叫GParted的磁盘分区管理软件,发现原来作为swap分区

360浏览器老崩溃怎么办?360浏览器崩溃解决办法

方法一, 打开360浏览器,点菜单栏上的工具,点360安全浏览器选项, 然后,点框架和增强, 在[优化性能]中选,"优化CPU"占用, 在[浏览器进程模式]选"混合模式", 然后重新启动浏览器! 如果还有问题,建议你卸载360浏览器,然后去360的官网下载最新版的360安全卫士3.7安装! 方法二,网站整理的其它办法 方法1: 释放360浏览器使用的内存,安装360安装卫士即可使用360加速球一键加速释放不必要的内存.如果浏览器崩溃屏幕卡住了,那么可以右击电脑桌面任

chrome浏览器网页崩溃怎么办?chrome网页崩溃解决办法

1.我们只要同时按下键盘上的"Win+R"调出运行对话框,然后在运行窗口中输入regedit命令,打开注册表编辑器 2.需要在注册表中找到google浏览器相关注册表文件,可使用注册表搜索"google",然后将搜索后的相关文件夹删除,然后再重新打开谷歌浏览器 好了上面就是小编为各位整理的解决chrome浏览器网页崩溃的教程与方法了,如果你有碰到可以按上面方法来尝试解决的哦,希望对大家能够有帮助.

AMH面板变更面板MYSQL数据库密码导致无法连接解决办法

老左已经好久没有关注到AMH面板上面的信息,因为后面的5.0版本开始是收费版本,一来我没有购买体验 ,二来是有问题官方会提供解决,三来免费的4.2版本基本上也能满足基本的建站需求.今天有网友找我说自己在PHPMYADMIN面板中修改网站数据库密码的时候,数据表选错了,直接将ROOT用户的密码修改,这个用户可是AMH面板链接的数据库. 如果这个密码错误会导致我们打开面板有"[Amysql-Notice] Access denied for user 'root'@'localhost' (usin