mod_cgi is responsible for handling all requests for programs which should be executed on the server. This includes shell/Perl/Python/PHP scripts but it is not limited only to these. It is also responsible for sending the proper error pages to the clients when a problem is encountered.
How it works
When a PHP script is executed there are 3 steps that are made:
- Apache receives a request for a PHP script and sets the proper MIME type for this file extension
- Apache's mod_cgi receives the request and based on the MIME type sets the proper PHPHANDLER
- Apache runs the script using suexec, which in turn is using the PHPHANDLER supplied by mod_cgi.
Modified mod_cgi version
Mod_cgi is responsible for handling the execution of scripts. And if apache is with 1H Hive, mod_cgi is responsible for sending the proper HANDLER to the suexec wrapper. So what we did was to patch mod_cgi to accept/recognize more than one version of PHP based on the MIME type set by the server configuration, virtual host configuration or even an .htaccess file.
- suexec is built in such a way that it handles PHP scripts differently than other scripts, for example perl/python scripts are executed directly. PHP scripts are executed using a file (php-cgi binary) with which we execute the php script. This php binary file is supplied by the mod_cgi in an environment variable PHPHANDLER.
- We used the above functionality to change the behavior of mod_cgi so that it sends a different PHPHANDLER for different MIME types. In mod_cgi we have added 7 different PHPHANDLERS:
AddHandler application/x-httpd-php52s AddHandler application/x-httpd-php53 AddHandler application/x-httpd-php52 AddHandler application/x-httpd-php51 AddHandler application/x-httpd-php5 AddHandler application/x-httpd-php4 AddHandler application/x-httpd-php
application/x-httpd-php is pointing to the default PHP for the server. We hope that the others are clear. These are static, built in mod_cgi and can not be changed. Every handler is pointing to a file:
AddHandler application/x-httpd-php52s -> /usr/local/php52s/bin/php AddHandler application/x-httpd-php53 -> /usr/local/php53/bin/php AddHandler application/x-httpd-php52 -> /usr/local/php52/bin/php AddHandler application/x-httpd-php51 -> /usr/local/php51/bin/php AddHandler application/x-httpd-php5 -> /usr/local/php5/bin/php AddHandler application/x-httpd-php4 -> /usr/local/php4/bin/php AddHandler application/x-httpd-php -> /usr/local/php52/bin/php
How to change the PHP version
This is done very simply, just add the line below in an .htaccess file in public_html for the whole user account or in the directory where the user wants to use a different PHP version:
AddHandler application/x-httpd-php51 .php .php3 .php4 .php5 .phtml
Based on the version, change the handler to the appropriate line.
You can also change the PHP version per file by adding something like this in your .htaccess files:
<Files only_php4.php> AddHandler application/x-httpd-php4 .php </Files>
As of version 0.4 of mod_cgi.so there is a new option for limiting the load of the server. After a certain value of load average is reached, the execution of scripts by apache will be stopped until the load average drops under the configured value. You can define the load limit in httpd.conf by using the MaxLoadLimit option. Example:
If this option is not present in the httpd.conf, the default value is used (20.0). If mod_info is enabled on this server, you can see the configuration options and a brief explanation on http://SERVER/server-info/. What you will see is this:
MaxLoadLimit - Maximum Server load before processing of scripts stops(default: 20.0)
When a script is denied start because of server overload (current loadavg > MaxLoadLimit), clients see ErrorPage 503 Service Temporary Unavailable and you can see this in the error log of apache:
[Thu Jan 3 05:25:30 2008] [error] [client 126.96.36.199] Execute of /home/sgtest/public_html/index.php stopped because of load 35.27 [Thu Jan 3 05:25:32 2008] [error] [client 188.8.131.52] Execute of /home/sgtest/public_html/index.php stopped because of load 35.27
strings /usr/local/apache/libexec/mod_cgi.so|grep PHP-CGI
# strings /usr/local/apache/libexec/mod_cgi.so|grep PHP-CGI PHP-CGI/0.4mm