errno handling in concurrent haskell

Hi. I have some doubts about errno handling in a Concurrent Haskell program. Let's suppose that GHC non threaded runtime is used, so that each Haskell thread is bound to an OS thread. Let's suppose there are two threads running (`A` and `B`). Thread `A` calls a function `f`, that, in turn, calls via FFI a C function `c_f`. Function `c_f` fails, settings errno; however the GHC scheduler suspends execution of thread `A` and switch to thread `B`, before the current value of errno is read. Now, let's suppose thread `B` calls a function `g`, that, in turn, calls via FFI a C function `c_g`. Function `c_g`, too, fails, setting errno. Is this possible? P.S.: I have found this is C.Foreign.Error.hs, in base package (not the latest version): throwErrnoIfRetry :: (a -> Bool) -> String -> IO a -> IO a throwErrnoIfRetry pred loc f = do res <- f if pred res then do err <- getErrno if err == eINTR then throwErrnoIfRetry pred loc f else throwErrno loc else return res This function calls getErrno two times. Is this safe? Why the throwErrno function does not accept errno as parameter? Thanks Manlio Perillo

Manlio Perillo wrote:
I have some doubts about errno handling in a Concurrent Haskell program.
Let's suppose that GHC non threaded runtime is used, so that each Haskell thread is bound to an OS thread.
Let's suppose there are two threads running (`A` and `B`). Thread `A` calls a function `f`, that, in turn, calls via FFI a C function `c_f`.
Function `c_f` fails, settings errno; however the GHC scheduler suspends execution of thread `A` and switch to thread `B`, before the current value of errno is read.
Now, let's suppose thread `B` calls a function `g`, that, in turn, calls via FFI a C function `c_g`. Function `c_g`, too, fails, setting errno.
Is this possible?
It's safe, we save the value of errno when a Haskell thread is descheduled, and restore it when it is scheduled again. We do the same on Windows for GetLastError().
P.S.: I have found this is C.Foreign.Error.hs, in base package (not the latest version):
throwErrnoIfRetry :: (a -> Bool) -> String -> IO a -> IO a throwErrnoIfRetry pred loc f = do res <- f if pred res then do err <- getErrno if err == eINTR then throwErrnoIfRetry pred loc f else throwErrno loc else return res
This function calls getErrno two times. Is this safe?
yes
Why the throwErrno function does not accept errno as parameter?
because it reads the global errno. Cheers, Simon

Simon Marlow ha scritto:
Manlio Perillo wrote:
I have some doubts about errno handling in a Concurrent Haskell program.
Let's suppose that GHC non threaded runtime is used, so that each Haskell thread is bound to an OS thread.
Let's suppose there are two threads running (`A` and `B`). Thread `A` calls a function `f`, that, in turn, calls via FFI a C function `c_f`.
Function `c_f` fails, settings errno; however the GHC scheduler suspends execution of thread `A` and switch to thread `B`, before the current value of errno is read.
Now, let's suppose thread `B` calls a function `g`, that, in turn, calls via FFI a C function `c_g`. Function `c_g`, too, fails, setting errno.
Is this possible?
It's safe, we save the value of errno when a Haskell thread is descheduled, and restore it when it is scheduled again. We do the same on Windows for GetLastError().
Thanks. I was just replying to the message, after having read the code of the scheduler. Manlio Perillo
participants (2)
-
Manlio Perillo
-
Simon Marlow