@@ -154,7 +154,8 @@ import Development.IDE.Graph.Database (ShakeDatabase,
154154import Development.IDE.Graph.Internal.Action (runActionInDbCb )
155155import Development.IDE.Graph.Internal.Database (AsyncParentKill (AsyncParentKill ))
156156import Development.IDE.Graph.Internal.Types (DBQue , Step (.. ),
157- getShakeStep )
157+ getShakeStep ,
158+ withLockInShakeDatabase )
158159import Development.IDE.Graph.Rule
159160import Development.IDE.Types.Action
160161import Development.IDE.Types.Diagnostics
@@ -615,7 +616,6 @@ data IdeState = IdeState
615616 }
616617
617618
618-
619619-- This is debugging code that generates a series of profiles, if the Boolean is true
620620shakeDatabaseProfileIO :: Maybe FilePath -> IO (ShakeDatabase -> IO (Maybe FilePath ))
621621shakeDatabaseProfileIO mbProfileDir = do
@@ -754,7 +754,6 @@ shakeOpen recorder lspEnv defaultConfig idePlugins debouncer
754754 pure ShakeExtras {shakeRecorder = recorder, .. }
755755 shakeDb <-
756756 shakeNewDatabase
757- shakeControlQueue
758757 opts { shakeExtra = newShakeExtra shakeExtras }
759758 rules
760759 shakeSession <- newEmptyMVar
@@ -912,43 +911,44 @@ runRestartTaskDyn recorder ideStateVar dy = runRestartTask recorder ideStateVar
912911runRestartTask :: Recorder (WithPriority Log ) -> MVar IdeState -> ShakeRestartArgs -> IO ()
913912runRestartTask recorder ideStateVar shakeRestartArgs = do
914913 IdeState {shakeDb, shakeSession, shakeExtras, shakeDatabaseProfile} <- readMVar ideStateVar
915- let prepareRestart sra@ ShakeRestartArgs {.. } = do
916- keys <- sraBetweenSessions
917- -- it is every important to update the dirty keys after we enter the critical section
918- -- see Note [Housekeeping rule cache and dirty key outside of hls-graph]
919- atomically $ modifyTVar' (dirtyKeys shakeExtras) $ \ x -> foldl' (flip insertKeySet) x keys
920- -- Check if there is another restart request pending, if so, we run that one too
921- readAndGo sra sraShakeControlQueue
922- readAndGo sra sraShakeControlQueue = do
923- nextRestartArg <- atomically $ tryReadTaskQueue sraShakeControlQueue
924- case nextRestartArg of
925- Nothing -> return sra
926- Just (Left dy) -> do
927- res <- prepareRestart $ dynShakeRestart dy
928- return $ sra <> res
929- Just (Right _) -> readAndGo sra sraShakeControlQueue
930- withMVar'
931- shakeSession
932- ( \ runner -> do
933- -- takeShakeLock shakeDb
934- (stopTime, () ) <- duration $ logErrorAfter 10 $ cancelShakeSession runner
935- restartArgs <- prepareRestart shakeRestartArgs
936- queue <- atomicallyNamed " actionQueue - peek" $ peekInProgress $ actionQueue shakeExtras
937- res <- shakeDatabaseProfile shakeDb
938- backlog <- readTVarIO $ dirtyKeys shakeExtras
939- -- this log is required by tests
940- step <- shakeGetBuildStep shakeDb
941- logWith recorder Info $ LogBuildSessionRestart restartArgs queue backlog stopTime res step
942- return restartArgs
943- )
944- -- It is crucial to be masked here, otherwise we can get killed
945- -- between spawning the new thread and updating shakeSession.
946- -- See https://github.com/haskell/ghcide/issues/79
947- ( \ (ShakeRestartArgs {.. }) ->
948- do
949- (,() ) <$> newSession recorder shakeExtras sraVfs shakeDb sraActions sraReason
950- `finally` for_ sraWaitMVars (`putMVar` () )
951- )
914+ withLockInShakeDatabase shakeDb $ do
915+ let prepareRestart sra@ ShakeRestartArgs {.. } = do
916+ keys <- sraBetweenSessions
917+ -- it is every important to update the dirty keys after we enter the critical section
918+ -- see Note [Housekeeping rule cache and dirty key outside of hls-graph]
919+ atomically $ modifyTVar' (dirtyKeys shakeExtras) $ \ x -> foldl' (flip insertKeySet) x keys
920+ -- Check if there is another restart request pending, if so, we run that one too
921+ readAndGo sra sraShakeControlQueue
922+ readAndGo sra sraShakeControlQueue = do
923+ nextRestartArg <- atomically $ tryReadTaskQueue sraShakeControlQueue
924+ case nextRestartArg of
925+ Nothing -> return sra
926+ Just (Left dy) -> do
927+ res <- prepareRestart $ dynShakeRestart dy
928+ return $ sra <> res
929+ Just (Right _) -> readAndGo sra sraShakeControlQueue
930+ withMVar'
931+ shakeSession
932+ ( \ runner -> do
933+ -- takeShakeLock shakeDb
934+ (stopTime, () ) <- duration $ logErrorAfter 10 $ cancelShakeSession runner
935+ restartArgs <- prepareRestart shakeRestartArgs
936+ queue <- atomicallyNamed " actionQueue - peek" $ peekInProgress $ actionQueue shakeExtras
937+ res <- shakeDatabaseProfile shakeDb
938+ backlog <- readTVarIO $ dirtyKeys shakeExtras
939+ -- this log is required by tests
940+ step <- shakeGetBuildStep shakeDb
941+ logWith recorder Info $ LogBuildSessionRestart restartArgs queue backlog stopTime res step
942+ return restartArgs
943+ )
944+ -- It is crucial to be masked here, otherwise we can get killed
945+ -- between spawning the new thread and updating shakeSession.
946+ -- See https://github.com/haskell/ghcide/issues/79
947+ ( \ (ShakeRestartArgs {.. }) ->
948+ do
949+ (,() ) <$> newSession recorder shakeExtras sraVfs shakeDb sraActions sraReason
950+ `finally` for_ sraWaitMVars (`putMVar` () )
951+ )
952952 where
953953 logErrorAfter :: Seconds -> IO () -> IO ()
954954 logErrorAfter seconds action = flip withAsync (const action) $ do
0 commit comments