[tolj@wapme-systems.de: Re: Problem with accept?!! (was: Re: apache cygwin package hangs when MaxRequestsPerChild reached!)]

Corinna Vinschen vinschen@redhat.com
Mon Jun 2 11:18:00 GMT 2003

----- Forwarded message from Stipe Tolj <tolj@wapme-systems.de> -----
> Date: Mon, 02 Jun 2003 11:07:31 +0200
> From: Stipe Tolj <tolj@wapme-systems.de>
> Subject: Re: Problem with accept?!! (was: Re: apache cygwin package hangs when 
>  MaxRequestsPerChild reached!)
> To: "Christopher B. Liebman" <liebman@zod.com>
> Cc: cygwin@cygwin.com
> Hi Christopher,
> "Christopher B. Liebman" schrieb:
> > 
> > Ok, after some investigation I am starting to think that the issue is with
> > the behavior of accept().  When the apache main forks off its pool of worker
> > procs, each one calls accept() on the socket file descriptor.  What I have
> > found is that when the first process in the pool exits (usually due to the
> > max requests being reached) ***none*** of the other pool process return from
> > accept() when the next request comes in on the socket.  If I kill off the
> > current pool procs the *first* new one will respond to requests untill the
> > max is recieved again then as before, non of the other pool procs return
> > from accept.  Any ideas on how to deal with this?
> ok, this is a pretty good description of the problem I guess.
> Let's ask Corinna, Chris et al for their explanation if something in
> the accept() behaviour *inside* Cygwin changed from 1.3.10+ ?!?!?!?
> Stipe
----- End forwarded message -----

I think I know what's going on.  What bugs me, though, is that Stipe now
managed to get around debugging the situation for over a year.

Anyway, here's the deal.  Since WinSock's accept is not interruptible
Thomas invented the new method (which we are also using in connect
in the meantime) to switch the socket to non-blocking and to use
WSAEventSelect/WSAWaitForMultipleEvents instead of calling accept directly.
This allows to call WinSock's accept if a FD_ACCEPT event happens or to
interrupt the call if a signal arrives, exactly what we want.

This works nicely in most circumstances.  Unfortunately, apache isn't
"most".  As per the above description, what apache seems to do is, it
creates a listening socket in the main process and then forks a bunch
of children which inherit this socket.  Now all this children call accept.

Fine.  Except that we now have a new problem, which is a result of
WinSock's incredible stupidity:

    Duplicated sockets all share the same event handler.
Only one of all the WSAEventSelect calls on the same (even though
duplicated) sockets, the latest one, actually *gets* events.  This means,
only the latest forked child process actually gets events.  That means, if
this child exits, all other children are stuck in WaitForMultipleEvents().

And that means, we have three choices how to proceed:

- *shrug*, let apache run only with one child process (hmm, not good).
- *sic*, remove all the event stuff from accept and connect and revert
  to non-interruptible accept and connect calls (oh, boy).
- *ouch*, invent a complete new technique to allow interruptible sockets
  for Cygwin.

As a starting point I'm now throwing some fuel in here:  What about
running accept and connect in another thread which can be terminated
using TerminateThread if a signal arrives?


Corinna Vinschen                  Please, send mails regarding Cygwin to
Cygwin Developer                                mailto:cygwin@cygwin.com
Red Hat, Inc.

More information about the Cygwin-developers mailing list