The platform is windows server 2003 (32-bit system) + Apache/2.2.9 (Win32) + PHP/5.2.17. The regular expression preg_match_all (for example, preg_match_all ("/ni (.*?) Wo/", $ html, $ matches);) for analysis and matching of a long string $ html (more than 0.1 million bytes, usually used to analyze the source code of the collected webpage ), the Apache server will crash and automatically restart.
The following error message is displayed in the Apache error log:
[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.
After reading Apache official documents and Forum materials, we found that when we use regular expressions preg_match_all or preg_match to analyze long strings on the win platform, the cause of apache crash and restart is that the thread stack space allocated by default in windows is too small. Win32 is only KB by default, while the default value in linux is 8 MB, which is why the same program works normally on the linux platform, but not on the Windows platform.
According to the official instructions of PCRE library: the size of pcre. recursion_limit corresponding to the 256 KB stack space should not exceed 524.
Here is a table of safe values of pcre. recursion_limit for a variety of executable stack sizes:
The following is a recommended security value corresponding to Stacksize and pcre. recursion_limit. If this value is exceeded, Stack Overflow is very likely. 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
If you have not adjusted the stack size, you must add the following at the beginning of the PHP page using regular expressions:
<? Php
Ini_set ("pcre. recursion_limit", "524"); // PHP default is 100,000.
?>
You can use the following code to view specific errors:
$ 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 = 'uncognized PREG error ';
Break;
}
}
Return ($ msg );
}
Description of the regular expression modifier isU:
I: in-casesensitive, which is case insensitive.
S: PCRE_DOTALL, indicating that the DOT can match the line break.
U: PCRE_UNGREEDY, non-greedy, equivalent to. *? In perl/python .*?, During the matching process, if A. * regular expression matches, it is executed immediately, instead of waiting for. * to search all characters and then return them one by one.
When using regular expressions, we should try to avoid recursive calls, which may easily cause stack overflow. For example:
/<Table ((?! <Table ).)*? </A>/isU will cause an error and use/<table .*? </A>/I is normal.
So how can we increase the ThreadStackSize of the win platform? In the apache configuration file httpd. enable "Include conf/extra/httpd-mpm.conf" in conf (delete previous comment #), then set "ThreadStackSize 8400000" in the mpm_winnt_module configuration module in the httpd-mpm.conf File (about 8 M ).
<IfModule mpm_winnt_module>
ThreadStackSize 8400000
ThreadsPerChild 200
MaxRequestsPerChild 10000
Win32DisableAcceptEx
</IfModule>
Note that a 32-bit Apache program can only use up to 2 GB of memory space! Therefore, the value of ThreadStackSize multiplied by ThreadsPerChild (8 M * 200) should not exceed 2 GB. Otherwise, apache cannot be started. The error log is as follows:
[Thu Apr 11 20:02:45 2013] [crit] (OS 8) does not have enough storage space to handle this command. : Child 4832: _ beginthreadex failed. Unable to create all worker threads. Created 212 of the 220 threads requested with the ThreadsPerChild configuration directive.
With the above prompt, it is easy to tell you that on my server, when the thread stack size is set to 8 MB, the maximum number of threads that I can set is 212.