[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