[Haskell-cafe] Spurious program crashes
sebastian.sylvan at gmail.com
Thu Nov 17 09:03:56 EST 2005
On 11/17/05, Joel Reymont <joelr1 at gmail.com> wrote:
> On Nov 17, 2005, at 1:44 PM, Sebastian Sylvan wrote:
> > Are you sure it's safe to kill a thread which has already been killed?
> It seems so from the docs.
> > Why do you fork off the killing of the threads? Why not just run them
> > in sequence?
> Someone said that they read somewhere that killThread can block. I'm
> not gonna point any fingers at musasabi ;-).
> > Also, I'd recommend refactoring the code a bit, write a function
> > "parIO" which runs IO computations in parallell and then define
> > timeout in terms of that.
> I did this by stealing the timeout/either combinators from the
> Asynchronous Exceptions paper. It did not help a single bit.
This is somewhat frustrating for me because I had a very similar (if
not the exact same) issue when writing some test applications for an
FMOD binding. However, all that source code (and so much more) was
lost due to a hard disk failure. I am now struggling to remember what
was the cause, and how I solved.
What I do remember is that the timeout and parIO functions in the
concurrent programming papers I found were NOT correct. killThread did
NOT behave as expected when I killed an already killed thread.
I tried multiple tricks here (including some which required recursive
do-notation) to try to get the parIO function to only kill the *other*
This could be done by having the two spawned threads take their
computations in an MVar along with the threadID of the other thread.
parIO f1 f2 = do m <- newEmptyMVar -- result Mvar
mf1 <- newEmptyMVar -- MVar for f1
mf2 <- newEmptyMVar -- MVar for f2
-- fork worker threads
t1 <- forkIO (child m mf1)
t2 <- forkIO (child m mf2)
-- pass computations and threadID to worker threads
putMVar mf1 (t2, f1)
putMVar mf2 (t1, f2)
-- return result
where child m mf = do (tid, f) <- takeMVar mf
x <- f
putMVar m x
timeout t f = threadDelay (round (t * 1e6)) `parIO` f
As I remember another solution I came up with was to wrap the "child"
function body in a catch statement. The child function was just a
helper function that ran a computation and put its result in an MVar.
I *think* the problem *may* have been that when an FFI function got
"ThreadKilled" exception asynchrounously that got bubbled up to the
parIO thread for some reason.
More information about the Haskell-Cafe