Proposal: a revoke() system call

Coleman Kane cokane at FreeBSD.org
Mon Jul 7 15:39:50 UTC 2008


On Mon, 2008-07-07 at 10:12 -0500, 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.
> 
> -SB
> 

In cases where I need to wake the select() up immediately for cases such
as this, I've implemented a "trigger pipe" that I include on the select
list. This is a simple pipe, that is written to by the application in
the cases where I want to design multi-threaded blocking I/O mechanisms
such as this to wake up immediately. The "master thread" writes to the
pipe, and the blocking thread gets notified of the readability of that
pipe's fd through my blocking select() call. Then, it attempts to read
(non-blocking-read) from the fd that I had closed, and gets an error
returned. The reader thread then knows to exit the read-loop and return
to the caller (which hopefully cleans it up later with pthread_join).

That method seems to work really well in a relatively cross-platform
manner. I typically shy away from these types of designs, however. I
attempt to ensure that my "reader threads" use select() calls with a
reasonable timeout (100ms or even 250ms is usually decent for
non-realtime software), and have an external trigger variable such as a
bool or similar (named stop_threads) that is part of the struct pointer
that I have passed in the void* argument to the thread function when
calling pthread_create().

Basically, my master thread would have a cleanup routine that runs at
shut-down and sets the variable to true. It then proceeds to
pthread_join() all of the threads that trigger their exits on that
variable. Only once all threads are joined do I close() the file
descriptor. The sequence of events can easily be applied to non-shutdown
events where such behavior is desired, however. The key point here is
the use of select() to determine when a descriptor is readable, and then
using non-blocking I/O to perform the actual read/write calls.

-- 
Coleman Kane
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 195 bytes
Desc: This is a digitally signed message part
Url : http://lists.freebsd.org/pipermail/freebsd-arch/attachments/20080707/647ee4a3/attachment.pgp


More information about the freebsd-arch mailing list