@@ -415,7 +415,21 @@ spawnChannelLocal proc = do
415415callLocal :: Process a -> Process a
416416callLocal proc = mask $ \release -> do
417417 mv <- liftIO newEmptyMVar :: Process (MVar (Either SomeException a))
418− child <- spawnLocal $ try (release proc) >>= liftIO . putMVar mv
419− rs <- liftIO (takeMVar mv) `onException`
420− (kill child "exception in parent process" >> liftIO (takeMVar mv))
418+ child <- spawnLocal $ mask_ $ try (release proc) >>= liftIO . putMVar mv
419+ ref <- monitor child
420+ rs <- liftIO (takeMVar mv)
421+ `onException`
422+ (do kill child "exception in parent process"
423+ waitFor ref
424+ )
421425 either throw return rs
426+ where
427+ -- TODO: when processes spawned with spawnLocal inherit the masking state of
428+ -- the parent, this can be simplified to simply reading the MVar.
429+ --
430+ -- At the time of this writing, the spawned process is unmasked and can be
431+ -- killed before the MVar is filled.
432+ waitFor ref = receiveWait
433+ [ matchIf (\(ProcessMonitorNotification ref' _ _) -> ref == ref')
434+ (\_ -> return ())
435+ ]