Messages in this thread | | | Date | Mon, 21 Feb 2000 14:04:17 -0800 (PST) | From | Dean Gaudet <> | Subject | Re: accept() improvements for rt signals |
| |
On Mon, 21 Feb 2000, Dan Kegel wrote:
> Dean Gaudet wrote: > > On Mon, 21 Feb 2000, Dan Kegel wrote: > > > * the new socket to inherit the F_SETSIG settings of the old > > > one (works for some cases, but makes some server designs hard) > > > or > > > * an atomic accept-and-F_SETSIG,FASYNC,F_SETOWN call (works for > > > all server designs I know of) > > > > there's also the need to turn on non-blocking i/o, to enable > > close-on-exec, and to disable nagle (or set the cork). but collapsing > > syscalls is kind of a bad thing to do. > > > > what if there were: > > accept2(int s_listen, struct sockaddr *, int *addrlen, int s_client); > > > > where s_client is a socket created by socket() with its options all set up > > as desired by the application? that way the app can do the F_SETSIG/etc. > > before it is attached to the network. > > That's pretty sexy. > > Alternately, accept2() might create a new socket but copy all socket > settings and options from s_client. Then the socket returned from accept2() > would be an instance of the class defined by s_client, as it were.
i thought about it more and it doesn't make sense -- it doesn't save any syscalls really... in the current model you have to do an extra read() to check if you missed an event. with accept2() you have to do an extra socket(), so it works out the same.
also -- the close() (or even the initial F_SETSIG) causing a queued event sounds sketchy... for a pretty obscure reason.
with HTTP (and with other pipelined protocols, such as SMTP, IMAP, and multiplexed protocols such as SCP and S/MUX) you generally can't just close() a connection. you have to go through a sequence of shutdown(s, 1); followed by read() until EOF (or a timeout) and then finally a close(). this essentially simulates a correct lingering close, but in my tests a while ago it was always faster to do it in userland.
the problem, if you're not familiar with it, is that if you close() a socket while there's still pending written data in the kernel, and then the client sends another data packet (which it's sometimes allowed to do in the protocols listed above) it will cause a RST to be sent -- and this potentially causes data loss because there's still data pending to be written. it's documented more fully in a draft from Jim Gettys, of which i've got an old copy at <http://arctic.org/~dean/apache/standards/draft-ietf-http-connection-00.txt>
so assume that the application has to do this
shutdown(s, 1); while (read(s) > 0) {}; close(s);
sequence. the kernel shouldn't queue any more "ready to write" events after the shutdown (not sure if it does or not). in order to read you would suck up any "ready to read" events. and then finally you close.
so in the unlikely event that the last write() hit the send buffer edge you might have a ghost write event in the queue before the shutdown happens. and in the uncommon event that the read() doesn't return EOF before the timeout occurs *and* the client sends data at just the wrong moment before the close() then you might end up with a ghost read event.
and so you might pay an extra syscall or two *occasionally* on a new socket for events meant for an older socket... but... i guess i'm just unconvinced this is a performance problem worth making complex kernel changes for :)
i think the main functionality i'd like to see, if it's not there already, is to stop sending write events after a shutdown(s, 1).
Dean
- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.rutgers.edu Please read the FAQ at http://www.tux.org/lkml/
| |