Cannot fork

From time to time, the virtual server I rented acted up. When logging into the system, I would get error messages indicating the server wasn't able to create any more processes: "cannot fork". This was weird because ps(1) showed only 20 processes, while the hard limit of the virtual machine host was apparently set to 94.

My server doesn't do a lot: There's just a couple of deamons, including an Apache instance that servers less than 1000 page impressions per day. Load is pretty much zero most of the time, there's very little network I/O, and memory use is below limits, too.

After some head scratching, I realized what the problem was: The virtual machine host counts kernel level threads towards the process limit! It's quite obvious when you think about it; a quick "ps -efL" confirmed the suspicion.

The culprit was Apache with its threaded worker model (apache2-mpm-worker). The default settings were unsuitable for my rather limited virtual machine, they caused Apache to spawn too many threads. Fortunately, after reading the documentation this was rather easy to fix. I edited the configuration (/etc/apache2/apache2.conf on my system), adjusting the default settings:

<IfModule mpm_worker_module>
    StartServers          2
    ServerLimit           4
    MaxClients           64
    ThreadsPerChild      16
    MinSpareThreads       4
    MaxSpareThreads       8
    MaxRequestsPerChild   0
</IfModule>

After an Apache restart, my problems were gone.

This configuration limits the number of active worker threads to 64 (MaxClients), which is well below the virtual machine's threshold. Those 64 threads run in up to 4 child processes (ServerLimit), with 2 processes created on startup (StartServers). Each server process contains at most 16 threads (ThreadsPerChild), with 4 threads created at minimum and at most 8 idle threads kept in the worker pool (MinSpareThreads and MaxSpareThreads respectively). There's no limit on the number of requests a process may serve (MaxRequestsPerChild).

An alternative solution would be to switch to the prefork module. It works with processes rather than threads and is a lot easier to configure. Just install the apache2-mpm-prefork and set its MaxClients appropriately.

Keep in mind that browsers typically open several connections to your host, so one client can easily hog half a dozen workers. For my site, that's no problem, for others it may very well be.

social