Date: Mon, 07 Jul 2008 16:50:47 -0500 (CDT) From: Sergey Babkin <babkin@verizon.net> To: Sergey Babkin <babkin@verizon.net>, David Schultz <das@FreeBSD.ORG> Cc: arch@FreeBSD.ORG, Poul-Henning Kamp <phk@phk.freebsd.dk> Subject: Re: Re: Re: Proposal: a revoke() system call Message-ID: <9484951.340521215467447990.JavaMail.root@vms126.mailsrvcs.net>
next in thread | raw e-mail | index | archive | help
>From: David Schultz <das@FreeBSD.ORG> >On Mon, Jul 07, 2008, Sergey Babkin wrote: >> >>Rationale: >> >> >> >>In the multithreaded programs often multiple threads work with the >> >>same file descriptor. A particularly typical situation is a reader >> >>thread and a writer thread. The reader thread calls read(), gets >> >>blocked until it gets more data, then processes the data and >> >>continues the loop. Another example of a "reader thread" would be >> >>the main thread of a daemon that accepts the incoming connections >> >>and starts new per-connection threads. >> > >> >Have you tried to implement the functionality you're asking for ? >> > >> >You'll have to hunt down into all sorts of protocols, drivers >> >and other code to find the threads sleeping on your fd so you can >> >wake them. >> >> My thinking has been that if close() wakes them up, then things would be >> inherited from there. The thing I didn't know is that apparently in many cases close() >> doesn't wake them up. > >In Solaris, if you close a file descriptor that has blocked >readers, the readers wake up and read() returns 0 bytes (EOF). >(At least this is true if you close the local end of a pipe.) >It seems like implementing the same behavior in FreeBSD would >address your problem without introducing a new system call. >Is there a good reason why this might not be the right thing to do? No, actually I didn't realize that FreeBSD has this issue at all :-) My experience comes from Linux and Solaris implementations. The issue is that close() introduces a race between setting the fd number in the aplication data and closing the socket. The reader works like this pseudocode: int fd; fd = mystructure.fd; if (fd < 0) return -1; return read(fd, ...); This leaves a small race window between fd is checked and read() is executed. If in the meantime another thread does close() (and sets mystructure.fd to -1), and the third thread does open() then the result of this open would use the same fd number as our old fd (since now it's likely to be the lowest available number), then read() would happen on a completely wrong file. And yes, it does happen in real world. The best workaround I've come up with is a small pause between setting mystructure.fd = -1 and calling close(). The point of proposal is to do a close() without freeing the file descriptor. -SB
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?9484951.340521215467447990.JavaMail.root>