lkml.org 
[lkml]   [2000]   [Feb]   [21]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
/
Date
From
SubjectRe: 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/

\
 
 \ /
  Last update: 2005-03-22 13:56    [W:0.043 / U:0.116 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site