@@ -174,6 +174,7 @@ import qualified StmContainers.Map as STM
174174import System.FilePath hiding (makeRelative )
175175import System.IO.Unsafe (unsafePerformIO )
176176import System.Time.Extra
177+ import Control.Concurrent.Extra (signalBarrier )
177178-- See Note [Guidelines For Using CPP In GHCIDE Import Statements]
178179
179180#if !MIN_VERSION_ghc(9,3,0)
@@ -759,31 +760,34 @@ delayedAction a = do
759760-- Any actions running in the current session will be aborted,
760761-- but actions added via 'shakeEnqueue' will be requeued.
761762shakeRestart :: Recorder (WithPriority Log ) -> IdeState -> VFSModified -> String -> [DelayedAction () ] -> IO [Key ] -> IO ()
762- shakeRestart recorder IdeState {.. } vfs reason acts ioActionBetweenShakeSession =
763+ shakeRestart recorder IdeState {.. } vfs reason acts ioActionBetweenShakeSession = do
764+ barrier <- newBarrier
763765 atomically $ writeTQueue (shakeOpQueue $ shakeExtras) $
764- withMVar'
765- shakeSession
766- (\ runner -> do
767- (stopTime,() ) <- duration $ logErrorAfter 10 $ cancelShakeSession runner
768- keys <- ioActionBetweenShakeSession
769- atomically $ modifyTVar' (dirtyKeys shakeExtras) $ \ x -> foldl' (flip insertKeySet) x keys
770- res <- shakeDatabaseProfile shakeDb
771- backlog <- readTVarIO $ dirtyKeys shakeExtras
772- queue <- atomicallyNamed " actionQueue - peek" $ peekInProgress $ actionQueue shakeExtras
773-
774- -- this log is required by tests
775- logWith recorder Debug $ LogBuildSessionRestart reason queue backlog stopTime res
776- )
777- -- It is crucial to be masked here, otherwise we can get killed
778- -- between spawning the new thread and updating shakeSession.
779- -- See https://github.com/haskell/ghcide/issues/79
780- (\ () -> do
781- (,() ) <$> newSession recorder shakeExtras vfs shakeDb acts reason)
782- where
783- logErrorAfter :: Seconds -> IO () -> IO ()
784- logErrorAfter seconds action = flip withAsync (const action) $ do
785- sleep seconds
786- logWith recorder Error (LogBuildSessionRestartTakingTooLong seconds)
766+ withMVar'
767+ shakeSession
768+ (\ runner -> do
769+ signalBarrier barrier ()
770+ (stopTime,() ) <- duration $ logErrorAfter 10 $ cancelShakeSession runner
771+ keys <- ioActionBetweenShakeSession
772+ atomically $ modifyTVar' (dirtyKeys shakeExtras) $ \ x -> foldl' (flip insertKeySet) x keys
773+ res <- shakeDatabaseProfile shakeDb
774+ backlog <- readTVarIO $ dirtyKeys shakeExtras
775+ queue <- atomicallyNamed " actionQueue - peek" $ peekInProgress $ actionQueue shakeExtras
776+
777+ -- this log is required by tests
778+ logWith recorder Debug $ LogBuildSessionRestart reason queue backlog stopTime res
779+ )
780+ -- It is crucial to be masked here, otherwise we can get killed
781+ -- between spawning the new thread and updating shakeSession.
782+ -- See https://github.com/haskell/ghcide/issues/79
783+ (\ () -> do
784+ (,() ) <$> newSession recorder shakeExtras vfs shakeDb acts reason)
785+ waitBarrier barrier
786+ where
787+ logErrorAfter :: Seconds -> IO () -> IO ()
788+ logErrorAfter seconds action = flip withAsync (const action) $ do
789+ sleep seconds
790+ logWith recorder Error (LogBuildSessionRestartTakingTooLong seconds)
787791
788792-- | Enqueue an action in the existing 'ShakeSession'.
789793-- Returns a computation to block until the action is run, propagating exceptions.
0 commit comments