Use spawn-fcgi for lighttpd + PHP-FastCGI

Tagged in

I had a problem with Lighttpd and PHP on the default Gentoo install. The configuration that comes with Gentoo, and the “official recommendation” use bin-ath in the mod_fastcgi to point to PHP’s CGI executable.

For example,

fastcgi.server = (
    ".php" => (
        "localhost" => (
            "bin-path"  => "/usr/bin/php-cgi",
            "host" => "127.0.0.1",
            "port" => 1026
        )
    )
)

When lighttpd starts, lighttpd process itself will spawn multiple php-cgi processes, and communicate with them on port 1026 using the FastCGI protocol. Whenever a PHP script needs to be executed, one of spawned php-cgi child will take over the execution.

It is all fine — until the restart time.

There are some issues with lighttpd’s restarting/reloading. First of all, in my experience lighttpd does not always handle reloading properly via the standard SIGHUP. The init script on Gentoo nor implemented “reload” — logrotate script basically relies on the service to restart (Update: logrotate is now using SIGHUP after lighttpd 1.4.11 has been emerged). However, due to the way lighttpd implemented graceful restart, sometimes I found the FastCGI processes (in this case php-cgi) do not get restarted together with lighttpd. I think it is how it happens.

  1. Run “/etc/init.d/lighttpd restart”, which sends a SIGINT to the old process, and then fire up a new lighttpd process.
  2. Old lighttpd process received SIGINT, unbind the HTTP port to stop accepting new connections, however it cannot be terminated straight away because some of its PHP sub-processes are still finishing up their requests.
  3. New lighttpd process started, and bind itself to HTTP/HTTPS port which are now available. However, it cannot spawn the php-cgi FastCGI process, because port 1026 is still occupied by the php-cgi processes from the old lighttpd instance.
  4. New, old lighttpd process died after all its php-cgi children have finished their tasks. However the new lighttpd process is still left child-less. All new PHP requests will return 500 Internal Error.

I had that happening this morning, and this VM stopped serving PHP scripts for almost 4 hours, until I restarted lighttpd again! It has actually happened quite a few times before, but being procrastinating in nature, I only managed to “do something about it” today.

The solution, for me at least, is to use the spawn-fcgi script that also gets installed when you emerged lighttpd. It starts php-cgi independently from lighttpd, so that restarting lighttpd process do not have to restart all PHP FastCGI processes.

The configuration file can be found in /etc/conf.d/spawn-fcgi, and its default setting is quite reasonable for PHP. It starts 5 PHP FastCGI instance when it starts, and binds to TCP port 1026. First of all, you need to modify your lighttpd’s mod_fastcgi.conf file so that it would not try to look for local executable. All you need to do is to comment out the line where bin-path is specified. For example,

fastcgi.server = (
    ".php" => (
        "localhost" => (
#           "bin-path"  => "/usr/bin/php-cgi",
            "host" => "127.0.0.1",
            "port" => 1026
        )
    )
)

And then you need to restart lighttpd. spawn-fcgi comes with its own init script, so you’ll also need to do

localhost ~ # /etc/init.d/spawn-fcgi start
 * Starting spawn-fcgi ...        [ ok ]
localhost ~ # rc-update add spawn-fcgi default
 * spawn-fcgi added to runlevel default
 * rc-update complete.
localhost ~ #

Yup — remember to use rc-update to add spawn-fcgi to your start up script.

Now starting/stopping lighttpd would not affect starting and stopping of PHP FastCGI processes.

Comments

Gravatar

I had this problem aswell on my gentoo box, managed to fix the problem before finding this website (doh). I’m also wondering whether you have the the problem with spawn-fcgi not adaptive spawning extra php-cgi processes under heavy load? All my new requests get ‘handle-req’ and aren’t sent any data. The browser just sits there waiting for one of the php-cgi processes to become free.

Really annoying as i don’t want to be running 20 php-cgi processes, maybe just 5, but get it to spawn more as it needs.

Any ideas? :)

Gravatar

Yeah. That’s certainly one issue for me as well. But then again even with php-cgi spawn from lighttpd it would not spawn new PHP process when more requests come in. min-procs/max-procs do not seem to do anything for me.

Gravatar

I think lighty does not do adaptive spawning anymore, it starts with min-procs=max-procs so not much difference when using spawn-fcgi…but I wonder if it kills the process after a specific number of requests otherwise the server would end up with stall fcgi processes.

Post new comment

The content of this field is kept private and will not be shown publicly.

More information about formatting options