fix STM deadlock in finishCommandActions
Happened every time, because it was taking the pool TMVar while threads were still running, and then the thread would try to switch state.
This commit is contained in:
parent
19321e6892
commit
ad6b8c5f77
2 changed files with 16 additions and 6 deletions
|
@ -129,11 +129,12 @@ finishCommandActions = Annex.getState Annex.workers >>= \case
|
|||
Nothing -> noop
|
||||
Just tv -> do
|
||||
Annex.changeState $ \s -> s { Annex.workers = Nothing }
|
||||
pool <- liftIO $ atomically $ takeTMVar tv
|
||||
forM_ (mapMaybe workerAsync $ workerList pool) $ \aid ->
|
||||
liftIO (waitCatch aid) >>= \case
|
||||
Left _ -> noop
|
||||
Right st -> mergeState st
|
||||
sts <- liftIO $ atomically $ do
|
||||
pool <- readTMVar tv
|
||||
if allIdle pool
|
||||
then return (spareVals pool)
|
||||
else retry
|
||||
mapM_ mergeState sts
|
||||
|
||||
{- Like commandAction, but without the concurrency. -}
|
||||
includeCommandAction :: CommandStart -> CommandCleanup
|
||||
|
|
|
@ -17,7 +17,8 @@ data WorkerPool t = WorkerPool
|
|||
, workerList :: [Worker t]
|
||||
, spareVals :: [t]
|
||||
-- ^ Normally there is one value for each IdleWorker,
|
||||
-- but there can temporarily be fewer.
|
||||
-- but there can temporarily be fewer values, when a thread is
|
||||
-- changing between stages.
|
||||
}
|
||||
deriving (Show)
|
||||
|
||||
|
@ -130,3 +131,11 @@ deactivateWorker pool aid t = pool
|
|||
| a == aid = IdleWorker st : rest
|
||||
| otherwise = w : go rest
|
||||
|
||||
allIdle :: WorkerPool t -> Bool
|
||||
allIdle pool = all idle (workerList pool)
|
||||
-- If this does not hold, a thread must be transitioning between
|
||||
-- states, so it's not really idle.
|
||||
&& length (spareVals pool) == length (workerList pool)
|
||||
where
|
||||
idle (IdleWorker _) = True
|
||||
idle (ActiveWorker _ _) = False
|
||||
|
|
Loading…
Reference in a new issue