Hi Lars,

uh, order issues are difficult for me.
Although this is not the answer, I write a little.

At first:
  "critical section" ... is block that should protect the invariants.
  "atomic block"     ... is undivided code block.

Your point (1) and (2) are "critical section" for mfd and fd,
but not "atomic block".

readMVar can't create "atomic block". It's only read the content of MVar.

Of cource, as you have said.
If point (1) have no memory allocations, 
async exception and timer-based thread context switch don't occur there.
But you might think many other case, such as implement dependent.

If you want to protect the critical section exactly,
it is better to use an explicit mechanism rather than implicit mechanism.


Libraries on hackage[1] might be helpful.

For performance pursuit, there may be a gimmick way;-)

[1]: https://hackage.haskell.org/

Cheers,
Takenobu



2015-05-22 20:55 GMT+09:00 Lars Petersen <info@lars-petersen.net>:
Hello cafe,

I'm currently trying to understand Haskell's threading model and GHC's
implementation of it. Specifically I wondered about the safety of file
IO. Consider this piece of code:

> newtype Socket = Socket (MVar Fd)
>
> read :: Socket -> IO ByteString
> read (Socket mfd) = do
>   fd <- readMVar mfd
>   -- (1)
>   threadWaitRead fd
>   -- (2)
>   withMVar mfd $ \fd'-> do
>     -- (3) the actual read...

Context:
  - The socket is configured non-blocking.
  - No other operation will hold the MVar over a blocking call (because
this would make it impossible to close it while it's blocking).
  - My close operation will fill the MVar with -1 after it's closed and
will hold the MVar during the close operation.

Questions:
  - Is it theoretically possible that my thread gets paused at (1) or
within threadWaitRead, another thread closes the socket (or even worse
opens another file with the same fd) _and_ my thread is resumed
afterwards (I'm not asking about async exceptions)?
  - What constructs contain safepoints and which are guaranteed to be
executed without interruption?

Considerations (so far):
  - It is unlikely that (1) is a safepoint as no memory allocations
occur, but is it guaranteed?
  - If the socket were closed during (1), threadWaitRead throws an
exception complaining about a bad file descriptor which is unexpected
but not harmful.
  - I found this thread
(https://mail.haskell.org/pipermail/haskell-cafe/2014-September/115841.html)
which is somewhat related, but I couldn't extract a clear answer from it.

Best,
  Lars



_______________________________________________
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe