The actual problem is as follows:
There are two methods of getting a new worker: by creating a new child or cloning from unused (UNKNOWN type) one. Then creating a new one and serverlimit is not reached it work, if it has been reached, it will be denied.

clone function uses the same base as the one used for creating a new one except it reuses old child TYPE_UNKNOWN and problem is that ServerLimit is checked before actually checking for free (TYPE_UNKNOWN) children and if serverLimit has ever been reached in the past it will always fail.


Attached patch will fix this error.

To reproduce:
   use 1 vhost. set
      1 multiplexer
       ServerLimit 5.
       Maxprocessors >= 5.
       IdleTimeout 10
exhaust all free slots.
   wait 20s (over IdleTimeout) for children to go into TYPE_UNKNOWN state.

   try to exhaust all slots again. Not possible.

Janno Sannik wrote:
There will be trouble if ServerLimit < MaxProcessors * Users

The problem is that then child is being terminated it's TYPE will be marked as UNKNOWN and STATUS standby. If the same vhost want's to use it whom it belonged it will work OK. But if someone else ( a vhost that hasn't been active till now) needs to create a new processor/worker, then it will hit the server limit, because childID's = NumServers.

This was tested by generating configuration file with 100+1(for status monitoring, this will be the "poorly used" vhost) domains in it. with every domain under different uid. Then we programmed a small bencmarking utility which hammers apache with 100threads every thread randomizing 100 domain names. After hammering apache settled down and I was left with 1 processor, 1 worker, 1 multiplexor and 319-2-100=217 STANDBY, UNKNOWN children. Since this server status user had only one processor at the time I started bencmark and ended it can't create any more children since ServerLimit was allready reached.

[Fri Aug 10 22:34:12 2007] [warn] (peruser: pid=18883 uid=48 child=1) child_main(): CHECKING IF WE SHOULD CLONE A CHILD... [Fri Aug 10 22:34:12 2007] [warn] (peruser: pid=18883 uid=48 child=1) child_main(): total_processors = 1, max_processors = 100 [Fri Aug 10 22:34:12 2007] [warn] (peruser: pid=18883 uid=48 child=1) child_main(): idle_processors = 1, min_free_processors = 3 [Fri Aug 10 22:34:12 2007] [warn] (peruser: pid=18883 uid=48 child=1) child_main(): CLONING CHILD [Fri Aug 10 22:34:12 2007] [warn] (peruser: pid=18883 uid=48 child=1) child_clone(): Trying to use more child ID's than NumServers. Increase NumServers in your config file

Could these UNKNOWN children be reused by everyone somehow or to be completely discarded so new ones can born? I the mean time I look into perform_idle_server_maintenance(), since it seems to be responsible for killing and starting children.



NameVirtualHost *

<IfModule peruser.c>
        ServerLimit 320
        MaxClients 320
        MinSpareProcessors 3
        MaxProcessors 100
        MaxRequestsPerChild 1000
        ExpireTimeout 7200
        IdleTimeout 15
        Multiplexer nobody nobody
</IfModule>


"poor vhost"
###### default #######
<IfModule peruser.c>
Processor apache apache </IfModule>
<Virtualhost *>

    ServerAdmin     [EMAIL PROTECTED]
    DocumentRoot    /home/system/apache/httpd.p1/default
    ServerName      default
    ErrorLog        /home/system/apache/httpd.p1/default_error.log
    CustomLog       /home/system/apache/httpd.p1/default_custm.log combined

    <IfModule peruser.c>
        ServerEnvironment apache apache
    </IfModule>

    <Location /sss>
        SetHandler server-status
    </Location>

</Virtualhost>

"1/100 vhost":

NameVirtualHost *

########## vhost1.kood.ee ##########
<Virtualhost *>

        DocumentRoot    /home/test/6001/vhost1
        ServerName      vhost1.domain

        <IfModule peruser.c>
                ServerEnvironment #6001 #6001
        </IfModule>

</Virtualhost>


Debug:

[Fri Aug 10 22:34:12 2007] [warn] (peruser: pid=18883 uid=0 child=1) child_main(): sock_fd_in=212 sock_fd_out=213 [Fri Aug 10 22:34:12 2007] [warn] (peruser: pid=18883 uid=0 child=1) child_main(): PROCESSOR 1 [Fri Aug 10 22:34:12 2007] [warn] (peruser: pid=18883 uid=0 child=1) listen_clear(): function entered [Fri Aug 10 22:34:12 2007] [warn] (peruser: pid=18883 uid=0 child=1) listen_add(): function entered [Fri Aug 10 22:34:12 2007] [warn] (peruser: pid=18883 uid=0 child=1) listen_add(): function entered [Fri Aug 10 22:34:12 2007] [warn] (peruser: pid=18883 uid=48 child=1) child_main(): input available ... resetting socket. [Fri Aug 10 22:34:12 2007] [warn] (peruser: pid=18883 uid=48 child=1) receive_from_multiplexer(): receiving from sock_fd=212 [Fri Aug 10 22:34:12 2007] [warn] (peruser: pid=18883 uid=48 child=1) receive_from_multiplexer(): recvmsg returned 449 [Fri Aug 10 22:34:12 2007] [warn] (peruser: pid=18883 uid=48 child=1) receive_from_multiplexer(): trans_sock=93825040384080 fdx=6 sock_fd=6 [Fri Aug 10 22:34:12 2007] [warn] (peruser: pid=18883 uid=48 child=1) receive_from_multiplexer(): header_len=432 headers="GET /sss HTTP/1.1\r\nHost: 192.168.0.8\r\nUser-Age [Fri Aug 10 22:34:12 2007] [warn] (peruser: pid=18883 uid=48 child=1) receive_from_multiplexer(): header_len > 0, we got a request [Fri Aug 10 22:34:12 2007] [warn] (peruser: pid=18883 uid=48 child=1) receive_from_multiplexer(): There is no body [Fri Aug 10 22:34:12 2007] [warn] (peruser: pid=18883 uid=48 child=1) receive_from_multiplexer(): returning 0 [Fri Aug 10 22:34:12 2007] [warn] (peruser: pid=18883 uid=48 child=1) child_main(): CHECKING IF WE SHOULD CLONE A CHILD... [Fri Aug 10 22:34:12 2007] [warn] (peruser: pid=18883 uid=48 child=1) child_main(): total_processors = 1, max_processors = 100 [Fri Aug 10 22:34:12 2007] [warn] (peruser: pid=18883 uid=48 child=1) child_main(): idle_processors = 1, min_free_processors = 3 [Fri Aug 10 22:34:12 2007] [warn] (peruser: pid=18883 uid=48 child=1) child_main(): CLONING CHILD [Fri Aug 10 22:34:12 2007] [warn] (peruser: pid=18883 uid=48 child=1) child_clone(): Trying to use more child ID's than NumServers. Increase NumServers in your config file [Fri Aug 10 22:34:12 2007] [warn] (peruser: pid=18883 uid=48 child=1) child_main(): marked jmpbuffer [Fri Aug 10 22:34:12 2007] [warn] (peruser: pid=18883 uid=48 child=1) child_main(): calling process_socket() [Fri Aug 10 22:34:12 2007] [warn] (peruser: pid=18883 uid=48 child=1) process_socket(): Creating dummy connection to use the vhost lookup api [Fri Aug 10 22:34:12 2007] [warn] (peruser: pid=18883 uid=48 child=1) process_socket(): Looking up the right vhost [Fri Aug 10 22:34:12 2007] [warn] (peruser: pid=18883 uid=48 child=1) process_socket(): Base server is default, name based vhosts on [Fri Aug 10 22:34:12 2007] [warn] (peruser: pid=18883 uid=48 child=1) process_socket(): child_num=1 sock=93825040384080 sock_fd=6\n [Fri Aug 10 22:34:12 2007] [warn] (peruser: pid=18883 uid=48 child=1) process_socket(): type=PROCESSOR 1 [Fri Aug 10 22:34:12 2007] [warn] (peruser: pid=18883 uid=48 child=1) peruser_process_connection(): function entered [Fri Aug 10 22:34:12 2007] [warn] (peruser: pid=18883 uid=48 child=1) peruser_process_connection(): leaving (DECLINED) [Fri Aug 10 22:34:12 2007] [warn] (peruser: pid=18883 uid=48 child=1) peruser_post_read(): PROCESSOR 1 [Fri Aug 10 22:34:12 2007] [warn] (peruser: pid=18883 uid=48 child=1) peruser_post_read(): request for 192.168.0.8 / (server default) seems to be for us [Fri Aug 10 22:34:12 2007] [warn] (peruser: pid=18883 uid=48 child=1) child_main(): returned from process_socket()




_______________________________________________
Peruser mailing list
[email protected]
http://www.telana.com/mailman/listinfo/peruser

--- httpd-2.2.3-clean/server/mpm/experimental/peruser/peruser.c 2007-08-13 
09:41:41.000000000 +0300
+++ httpd-2.2.3/server/mpm/experimental/peruser/peruser.c       2007-08-13 
11:43:11.644871624 +0300
@@ -1788,18 +1788,18 @@
     child_info_t *this;
     child_info_t *new;
 
-    if(NUM_CHILDS >= server_limit)
-    {
-        _DBG("Trying to use more child ID's than NumServers.  "
-               "Increase NumServers in your config file.");
-        return NULL;
-    }
-
     for(i = 0; i < NUM_CHILDS; i++)
     {
       if(CHILD_INFO_TABLE[i].pid == 0 &&
          CHILD_INFO_TABLE[i].type == CHILD_TYPE_UNKNOWN) break;
     }
+    
+    if(i == NUM_CHILDS && NUM_CHILDS >= server_limit)
+    {
+        _DBG("Trying to use more child ID's than NumServers.  "
+               "Increase NumServers in your config file.");
+        return NULL;
+    }    
 
     _DBG("cloning child #%d from #%d", i, my_child_num);
 
_______________________________________________
Peruser mailing list
[email protected]
http://www.telana.com/mailman/listinfo/peruser

Reply via email to