[Haskell-cafe] Locking of threads in one OS thread

Alexander Kjeldaas alexander.kjeldaas at gmail.com
Wed Aug 20 12:36:27 UTC 2014


On Tue, Aug 19, 2014 at 11:36 PM, Nikolay Amiantov <nikoamia at gmail.com>
wrote:

> Hello Cafe,
>
> I'm using FFI to interact with a library which calls, when fail, leave
> the reason in some kind of "errno"-like variable which is retrived via
> another call. AFAIU, this is not thread-safe in Haskell even if
> thread-local storage is used inside the library, because Haskell uses
> its own thread management and the Haskell thread in the same OS thread
> might be switched between the actual call and the retrival of errno
> value.


Good question!


> This should be somehow handled already in Haskell (errno is
> widely used with syscalls in Linux, for example), but the source of
> Foreign.C.Error suggests that this is not handled in any way at all.
> For example, throwErrnoIf is implemented as such:
>
> throwErrno loc  = do
>     errno <- getErrno
>     ioError (errnoToIOError loc errno Nothing Nothing)
>
> throwErrnoIf pred loc f  = do
>     res <- f
>     if pred res then throwErrno loc else return res
>
> So, the question is: how is it ensured that this block is "atomic" in
> sense that at most one Haskell thread computes this whole function at
> every moment in every OS thread?
>
>
I do not know the RTS very well, but I think this might be unsafe.  If the
thread is *bound*, then *getErrno* is guaranteed to be executed on the same
thread, but otherwise no such guarantee is given.

However, reading http://blog.ezyang.com/2013/01/the-ghc-scheduler/ it might
be unlikely.

If GC happens, "Threads are put in *front* (pushOnRunQueue) if: ... In the
threaded runtime, if a thread was interrupted because another Capability
needed to do a stop-the-world GC (see commit 6d18141d8);"

However, the same post indicates that you can force this behavior using
signals.

"Threads are put in *back* (appendToRunQueue) in the case of pre-emption,
or if it’s new; particularly, if: ...A thread was pre-empted via the
context switch flag (e.g. incoming message from another thread, the timer
fired, the thread cooperatively yielded, etc; see also [8] on how this
interacts with heap overflows);"

Reading errno directly after the FFI call can eliminate heap overflows, but
the async exception and timer issues still seem possible.

I would also like to see a good explanation of this.

Alexander
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://www.haskell.org/pipermail/haskell-cafe/attachments/20140820/8c0d1de7/attachment.html>


More information about the Haskell-Cafe mailing list