@@ -174,6 +174,7 @@ import qualified StmContainers.Map as STM
174
174
import System.FilePath hiding (makeRelative )
175
175
import System.IO.Unsafe (unsafePerformIO )
176
176
import System.Time.Extra
177
+ import Control.Concurrent.Extra (signalBarrier )
177
178
-- See Note [Guidelines For Using CPP In GHCIDE Import Statements]
178
179
179
180
#if !MIN_VERSION_ghc(9,3,0)
@@ -759,31 +760,34 @@ delayedAction a = do
759
760
-- Any actions running in the current session will be aborted,
760
761
-- but actions added via 'shakeEnqueue' will be requeued.
761
762
shakeRestart :: 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
763
765
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)
787
791
788
792
-- | Enqueue an action in the existing 'ShakeSession'.
789
793
-- Returns a computation to block until the action is run, propagating exceptions.
0 commit comments