[Haskell-cafe] Race conditions with threadWait(Read/Write) and closeFdWith

John Lato jwlato at gmail.com
Wed Sep 3 08:21:24 UTC 2014


On Tue, Sep 2, 2014 at 12:26 PM, Leon Smith <leon.p.smith at gmail.com> wrote:

> On Tue, Sep 2, 2014 at 1:31 PM, Felipe Lessa <felipe.lessa at gmail.com>
> wrote:
>
>> I don't see how one could allow concurrent readers and "closers" without
>>  leaving this small opening.  The best workaround I can think of is to
>> create a blocking close operation that waits for readers using a
>> semaphore.
>
>
> Well yes,  I can't think of a simple lock-based solution to this problem,
>  because you don't want to hold any kind of lock while you are blocked on
> the file descriptor.
>

If you wanted to go this route, you could use an MVar (Maybe (Int,Fd)),
where the Int is a count of interested threads.  Instead of using readMVar
before threadWaitRead, you would use modifyMVar to atomically increment the
counter and retrieve the fd.  Then, after threadWaitRead returns, decrement
the counter.  You'd need to make sure that you never close an fd when the
counter is greater than 0.  This would work better with a TMVar, because
then the close operation could block until the counter has changed.


>     It would be solvable though if we had a thread-safe
>
> threadWaitReadMVar :: MVar Fd -> IO ()
>
> You should be able to implement this relatively easily if you dig deeper
> into the IO manager itself,  but we already have threadWaitReadSTM.    (For
> different reasons, which doesn't cover this use case.)   How many
> variations on this theme are we going to need.
>
> We could implement threadWaitReadMVar if we had a non-blocking way of
> registering interest in a file descriptor,  and then later actually
> blocking on it.   So let's say something like
>
> registerWaitRead :: Fd -> IO (IO ())
>
> threadWaitReadMVar fd = join $ withMVar fd registerWaitRead
>
> Which,  ignoring asynchronous exceptions for the moment,  should be
> adequate for the task.    I suppose that means you could instead do
>
> threadWaitReadMVar fd = (atomically . fst) =<< withMVar fd
> threadWaitReadSTM
>

> Which seems like an odd use of STM,  but that also does seem like a
> solution.   So I guess the earlier part of this email (as well as eariler
> emails)  is in fact wrong,  that threadWaitReadSTM does cover this use
> case.     And STM might also offer a nicer way of making multiple reads
> from the inotify binding thread-safe as well.
>

This should work even in the presence of async exceptions, barring bugs in
withMVar and threadWaitReadSTM.  You can implement your registerWaitRead
using forkIO and MVars, but I think the only reason to do so would be for
compatibility with older ghcs.  It's probably more sensible to just copy
the definition of threadWaitReadSTM in that case, unless you want to target
pre-STM compiler versions.

John
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://www.haskell.org/pipermail/haskell-cafe/attachments/20140903/6d9ec3d4/attachment.html>


More information about the Haskell-Cafe mailing list