[peruser] Patch for busy servers

Taavi Sannik taavi at kood.ee
Wed Jan 5 03:44:00 MST 2011

Hello again!

I see that you have added a special case if MinProcessors is 0, then it 
will allow processor count to be below MinSpareProcessors (if 
IdleTimeout is reached).
This gets really bad, if one of the active workers hangs and all the 
other workers get killed, because noone would accept new connections and 
noone will clone new children.

The steps to reproduce this:
- use this peruser configuration:
<IfModule peruser.c>
     ServerLimit 700
     MaxClients 700
     MinSpareProcessors 1
     MaxSpareProcessors 20
     MinProcessors 0
     MaxProcessors 80
     MaxRequestsPerChild 1000
     ExpireTimeout 7200
     IdleTimeout 10
     MinMultiplexers 3
     MaxMultiplexers 40
     MultiplexerIdleTimeout 120
     ProcessorWaitTimeout 5
- create an infinite sleep script (for example in PHP: <?php while(true) 
sleep(1); ?>)
- start the server and run lynx on this script (lynx 
http://hostname/sleep.php). Lynx will start to wait for the response.
- if you look at the server-status or ps aux, you can see 2 workers (one 
of them is handling the sleep script, and the second is idle).
- wait until idletimeout kicks in. There is now only the "sleeping" 
worker left and the virtualhost is no longer accessible.
- run ab -c 100 -n 10000 against the dead virtualhost (you may need to 
repeat it a couple of times as ab timeouts).
- the whole server is now not accessible, all multiplexers have been 
spawned and are trying to forward the requests to the dead virtualhost's 
workers but there is noone to accept them.

There would be 2 ways to fix this:
  - rewrite the child cloning part and make multiplexers able to clone 
other children
  - disallow setting MinSpareProcessors to 0. If MinProcessors is 0 then 
kill the idle workers only if there are no active workers and all the 
workers have their idletimeout limit reached.


More information about the Peruser mailing list