httpd-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Marc Slemko <ma...@znep.com>
Subject Re: Apache 1.2b7, extra code in process control (fwd)
Date Tue, 25 Feb 1997 15:31:14 GMT
The reason why the select is needed is because when the Listen directive
is used (ie. listeners != NULL), we have more than one socket open, so we
can't just accept() on one.  It would be possible to avoid that in the
case that listeners == NULL, but that introduces more special case code.

May get changed when this section is rewritten after 1.2 while Apache is
being made threaded, but it is too late for 1.2.  I'll do some testing and
see if it makes any noticable performance difference, if so perhaps post a
link to a patch from the peformance hints page.

Thanks for the comments.

> ---------- Forwarded message ----------
> Date: Mon, 24 Feb 1997 20:19:54 -0600 (MDT)
> From: Joe Doupnik <JRD@cc.usu.edu>
> To: APACHE-BUGS@apache.org
> Cc: RSTEVENS@kohala.kohala.com
> Subject: Apache 1.2b7, extra code in process control
> 
> Gentlemen:
> 	This really isn't a bug report per se, but rather something which 
> might help Apache's performance a bit.
> 	First a tiny piece of background information. Over the past week
> or so I struggled with the problem of Apache locking up under slight
> stimulation (by, say, Netscape) when run in standalone mode. This was
> on a UnixWare 2.1.1 machine. The solution was to ensure mutex file locking
> was available, via -DUSE_FCNTL_SERIALIZED_ACCEPT. I mentioned this to one of
> your people over the weekend and he said that define would be put back
> into conf.h for the UW case. Fine, appreciated.
> 	The lockup puzzled me because I hadn't expected there to be a 
> race condition over accept() when the single socket descriptor became 
> available to all children. But under UnixWare's SYSV the race turns into
> civil war when a rapid succession of connections are pending (Netscape style).
> 	I asked Rich Stevens (cc'd here) about this and we exchanged some 
> info yesterday and today. A non-serializing accept() in SYSV turns out to 
> be a well known problem, at least in some circles. Rich was curious why one
> needs a select() preceeding the accept() given that the mutex lock already
> lets only one child have at the single socket descriptor. All select() would
> do is eat cpu time and slow down matters unnecessarily. Even without the lock,
> on suitable systems, select() isn't doing anything here that accept() omits, 
> so it is duplication of effort to no apparent advantage. 
> 	So I thought about it and tried an experiment with Apache 1.2b7. As 
> shown below, I #ifdef'd out the select() material and then banged on the test
> Apache 1.2b7/modified with Netscape 3.01. No problems were seen; it worked 
> like a charm.
> 	Thus I suggest your people give consideration to removing select()
> and worker code and save the high volume sites some cpu cycles and backlog 
> queue length. It is possible there are other reasons to retain select(), 
> but off hand I can't imagine what they might be.
> 	My thanks to Rich for taking time out on Sunday night and Monday 
> morning, for gosh sakes, to chat about this interesting manner of fast serving.
> 	Joe D.
> -----------------
> Section of http_main.c with select() removed by TEST_JRD. Locking is
> active via -DUSE_FCNTL_SERIALIZED_ACCEPT. UnixWare 2.1.1.
> 
>         /*
>          * Wait for an acceptable connection to arrive.
>          */
> #define TEST_JRD 1
>         accept_mutex_on();  /* Lock around "accept", if necessary */
> 
>         for (;;) {
> #ifndef TEST_JRD
>             memcpy(&main_fds, &listenfds, sizeof(fd_set));
> #ifdef SELECT_NEEDS_CAST
>             srv = select(listenmaxfd+1, (int*)&main_fds, NULL, NULL, NULL);
> #else
>             srv = select(listenmaxfd+1, &main_fds, NULL, NULL, NULL);
> #endif
>             errsave = errno;
> #endif  /* TEST_JRD */
>             sync_scoreboard_image();
>             if (scoreboard_image->global.exit_generation >= generation)
>                 exit(0);
> #ifndef TEST_JRD
>             errno = errsave;
>             if (srv < 0 && errno != EINTR)
>                 log_unixerr("select", "(listen)", NULL, server_conf);
> 
>             if (srv <= 0)
>                 continue;
> 
>             if (listeners != NULL) {
>                 for (sd = listenmaxfd; sd >= 0; sd--)
>                     if (FD_ISSET(sd, &main_fds)) break;
>                 if (sd < 0)
>                     continue;
>             }
> #endif  /* TEST_JRD */
>             do {
>                 clen = sizeof(sa_client);
>                 csd  = accept(sd, &sa_client, &clen);
>             } while (csd < 0 && errno == EINTR);
> 
>             if (csd >= 0)
>                 break;      /* We have a socket ready for reading */
>             else {
> #if defined(EPROTO) && defined(ECONNABORTED)
>               if ((errno != EPROTO) && (errno != ECONNABORTED))
> #elif defined(EPROTO)
>               if (errno != EPROTO)
> #elif defined(ECONNABORTED)
>               if (errno != ECONNABORTED)
> #endif
>                 log_unixerr("accept", "(client socket)", NULL, server_conf);
>             }
>         }
> 
>         accept_mutex_off(); /* unlock after "accept" */
> 
>         /*
>          * We now have a connection, so set it up with the appropriate
>          * socket options, file descriptors, and read/write buffers.
>          */
> 
> 


Mime
View raw message