httpd-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Roy T. Fielding" <field...@kiwi.ICS.UCI.EDU>
Subject Re: [Fwd: [BUG]: "accept: I/O Error looping" on UnixWare]
Date Sat, 15 Feb 1997 06:30:14 GMT
I responded to a similar message on the newsgroup yesterday:

In <33016BE6.7C6A@direct.ca> "Derek C. Ferguson" <derekf@direct.ca> writes:

>  I don't think that's the problem... I've already dealt with the
>excessive open log files problem by opening only three logs and
>using custom logging. I've set the number of descriptors from
>256 to 1024, and I still get a consistent spam of these errors:
>
>[Tue Feb 11 22:58:22 1997] getsockname: Bad file number
>[Tue Feb 11 22:58:24 1997] accept: Protocol error
>[Tue Feb 11 22:58:24 1997] - socket error: accept failed
>[Tue Feb 11 22:58:24 1997] getsockname: Bad file number
>[Tue Feb 11 22:58:25 1997] read timed out for 153.35.17.62
>[Tue Feb 11 22:58:27 1997] accept: Protocol error
>[Tue Feb 11 22:58:27 1997] - socket error: accept failed
>[Tue Feb 11 22:58:27 1997] getsockname: Bad file number
>[Tue Feb 11 22:58:27 1997] accept: Protocol error

I think I know what the problem is, but it is a bit difficult to
describe without a patch and, due to an unfortunate coincidence,
I seem to be unable to do that today.  Grump.

Anyway, if you look in http_main.c, in child_main(), you will find

===============
            do {
                clen = sizeof(sa_client);
                csd  = accept(sd, &sa_client, &clen);
            } while (csd < 0 && errno == EINTR);
            if (csd < 0)
                log_unixerr("accept", NULL, "socket error: accept failed",
                            server_conf);
        }

        accept_mutex_off(); /* unlock after "accept" */

        clen = sizeof(sa_server);
        if(getsockname(csd, &sa_server, &clen) < 0) {
            log_unixerr("getsockname", NULL, NULL, server_conf);
            continue;
        }
===============

The getsockname error is caused because the first if() above is
allowing the code to drop through even though csd < 0 (an invalid
file descriptor) instead of looping back to the select.  A good fix
will involve more changes, but here is a quick (untested) fix:

===============
            do {
                clen = sizeof(sa_client);
                csd  = accept(sd, &sa_client, &clen);
            } while (csd < 0 && errno == EINTR);
            if (csd < 0) {
                if ((errno != EPROTO) && (errno != ECONNABORTED))
                    log_unixerr("accept", NULL, "socket error: accept failed",
                                server_conf);
                accept_mutex_off(); /* unlock after "accept" */
                continue;           /* while(1) */
            }
        }

        accept_mutex_off(); /* unlock after "accept" */

        clen = sizeof(sa_server);
        if(getsockname(csd, &sa_server, &clen) < 0) {
            log_unixerr("getsockname", NULL, NULL, server_conf);
            continue;
        }
===============

Note, however, that EPROTO and ECONNABORTED are not portable, so the
above will only work on SunOS5.5.1 without also adding #ifdefs.

In case you are wondering, those two errors mean that the client aborted
the connection between the select and the accept.

Like I said, the above is untested.  Please let us know if it works.

 ...Roy T. Fielding
    Department of Information & Computer Science    (fielding@ics.uci.edu)
    University of California, Irvine, CA 92697-3425    fax:+1(714)824-4056
    http://www.ics.uci.edu/~fielding/

Mime
View raw message