Proposal: a revoke() system call

Sergey Babkin babkin at verizon.net
Mon Jul 7 21:51:01 UTC 2008


>From: David Schultz <das at 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


More information about the freebsd-arch mailing list