[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