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

Alexander Kjeldaas alexander.kjeldaas at gmail.com
Wed Sep 3 10:04:01 UTC 2014


On Wed, Sep 3, 2014 at 10:21 AM, John Lato <jwlato at gmail.com> wrote:

> 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.
>
>


Or a reader/writer lock.  Hold the lock as a reader across the blocking
operation.

Alexander


>      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
>
> _______________________________________________
> Haskell-Cafe mailing list
> Haskell-Cafe at haskell.org
> http://www.haskell.org/mailman/listinfo/haskell-cafe
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://www.haskell.org/pipermail/haskell-cafe/attachments/20140903/9cd41e16/attachment-0001.html>


More information about the Haskell-Cafe mailing list