Date: Thu, 21 Nov 2002 18:36:54 +1100 (EST) From: Bruce Evans <bde@zeta.org.au> To: jayanth <jayanth@yahoo-inc.com> Cc: freebsd-net@FreeBSD.ORG Subject: Re: file descriptor flags and socket flags out of sync ? Message-ID: <20021121171101.K37954-100000@gamplex.bde.org> In-Reply-To: <20021120110632.A62938@yahoo-inc.com>
next in thread | previous in thread | raw e-mail | index | archive | help
On Wed, 20 Nov 2002, jayanth wrote: > Some developers here have encountered a scenario where the file > descriptor flags and the socket flags seem to be out of sync. > > if an application does: > > listen(listenfd) > while (!done) { > select() > <-------------------- new connection arrives before fcntl() > fcntl(listenfd,O_NONBLOCK) > newfd = accept(listenfd,...) > fnctl(listenfd,0) /* make socket blocking */ > if (newfd & O_NONBLOCK) Better delete the last line. newfd doesn't contain any file flags. > /* fd is O_NONBLOCK, but socket is blocking */ > } > > At this point socket is blocking because the state > of the new socket = state of the listen socket only during the connection > setup phase, not during the accept phase. However, the filedescriptor > flags are copied during the accept phase. So at this point > the filedescriptor flags are nonblocking but the socket is actually blocking. This is related to my pet peeve of keeping the O_NONBLOCK flag in several places (one of them inadequate) and using the wrong copies. For sockets, the per-socket flag is adequate since open() doesn't work on sockets so there only needs to be one flag per socket, and using the per-socket flag mostly works right. For devices that can be opened more than once, a per-device flag is inadequate since file flags are supposed to be per-open. Non-broken device drivers use the copy of the file flags passed to their read/write/ioctl/close/etc functions, but making a copy causes synchronization problems. However, accessing the per-file flag from the device layer or the socket layer would be a layering violation. > Agreed, that the solution is to have the application set NONBLOCK before > the listen() call, but it seems incorrect to have the newfd's flags and socket > state be out of sync. You could also use "fnctl(newfd, 0)" to sync things for newfd. > Copying the state of the socket during the accept might lead to a slightly > different behaviour, but will solve this particular problem. I think this is the correct fix. The states are supposed to be consistent. This is enforced by fcntl() if the file flag state using it. I think you can still make a mess by changing the state using ioctl(). Bruce To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-net" in the body of the message
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20021121171101.K37954-100000>