httpd-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Rob Hartill <r...@imdb.com>
Subject Apache 1.2b7, extra code in process control (fwd)
Date Tue, 25 Feb 1997 03:50:42 GMT

Not acked.

---------- 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