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 [EMAIL PROTECTED] with "unsubscribe freebsd-net" in the body of the message