Skip to content

Commit eab156c

Browse files
soulomoonmichaelpj
andauthored
Stop doing action for handles and ignore responses after shutdown (#567)
* stop doing action before handler after shutdown * allowed method can run the before-action * fix * add log * swap log location * block the response call back * stop tryChangeConfig * Update lsp/src/Language/LSP/Server/Processing.hs Co-authored-by: Michael Peyton Jones <[email protected]> * revert barrior in tryChangeConfig * fix typo * revert tryChangeConfig * add documentation * Update lsp/src/Language/LSP/Server/Processing.hs Co-authored-by: Michael Peyton Jones <[email protected]> * refine shutdown blocking * refine shutdown blocking * fix format * fix format * fix doc * fix doc * Update Processing.hs --------- Co-authored-by: Michael Peyton Jones <[email protected]>
1 parent 1e5940b commit eab156c

File tree

2 files changed

+22
-9
lines changed

2 files changed

+22
-9
lines changed

lsp/src/Language/LSP/Server/Core.hs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1024,4 +1024,8 @@ be cancelled when we receive `shutdown`.
10241024
Shutdown is a request, and the client won't send `exit` until a server responds, so if you
10251025
want to be sure that some cleanup happens, you need to ensure we don't respond to `shutdown`
10261026
until it's done. The best way to do this is just to install a specific `shutdown` handler.
1027+
1028+
After the `shutdown` request, we don't handle any more requests and notifications other than
1029+
`exit`. We also don't handle any more responses to requests we have sent but just throw the
1030+
responses away.
10271031
-}

lsp/src/Language/LSP/Server/Processing.hs

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@ instance Pretty LspProcessingLog where
9292
processMessage :: (m ~ LspM config) => LogAction m (WithSeverity LspProcessingLog) -> BSL.ByteString -> m ()
9393
processMessage logger jsonStr = do
9494
pendingResponsesVar <- LspT $ asks $ resPendingResponses . resState
95+
shutdown <- isShuttingDown
9596
join $ liftIO $ atomically $ fmap handleErrors $ runExceptT $ do
9697
val <- except $ eitherDecode jsonStr
9798
pending <- lift $ readTVar pendingResponsesVar
@@ -100,8 +101,10 @@ processMessage logger jsonStr = do
100101
FromClientMess m mess ->
101102
pure $ handle logger m mess
102103
FromClientRsp (P.Pair (ServerResponseCallback f) (Const !newMap)) res -> do
104+
-- see Note [Shutdown]
103105
writeTVar pendingResponsesVar newMap
104-
pure $ liftIO $ f (res ^. L.result)
106+
unless shutdown <$> do
107+
pure $ liftIO $ f (res ^. L.result)
105108
where
106109
parser :: ResponseMap -> Value -> Parser (FromClientMessage' (P.Product ServerResponseCallback (Const ResponseMap)))
107110
parser rm = parseClientMessage $ \i ->
@@ -449,31 +452,37 @@ handle' ::
449452
TClientMessage meth ->
450453
m ()
451454
handle' logger mAction m msg = do
452-
maybe (return ()) (\f -> f msg) mAction
455+
shutdown <- isShuttingDown
456+
-- These are the methods that we are allowed to process during shutdown.
457+
-- The reason that we do not include 'shutdown' itself here is because
458+
-- by the time we get the first 'shutdown' message, isShuttingDown will
459+
-- still be false, so we would still be able to process it.
460+
-- This ensures we won't process the second 'shutdown' message and only
461+
-- process 'exit' during shutdown.
462+
let allowedMethod m = case (splitClientMethod m, m) of
463+
(IsClientNot, SMethod_Exit) -> True
464+
_ -> False
465+
466+
case mAction of
467+
Just f | not shutdown || allowedMethod m -> f msg
468+
_ -> pure ()
453469

454470
dynReqHandlers <- getsState resRegistrationsReq
455471
dynNotHandlers <- getsState resRegistrationsNot
456472

457473
env <- getLspEnv
458474
let Handlers{reqHandlers, notHandlers} = resHandlers env
459-
shutdown <- isShuttingDown
460475

461476
case splitClientMethod m of
462477
-- See Note [Shutdown]
463478
IsClientNot | shutdown, not (allowedMethod m) -> notificationDuringShutdown
464-
where
465-
allowedMethod SMethod_Exit = True
466-
allowedMethod _ = False
467479
IsClientNot -> case pickHandler dynNotHandlers notHandlers of
468480
Just h -> liftIO $ h msg
469481
Nothing
470482
| SMethod_Exit <- m -> exitNotificationHandler logger msg
471483
| otherwise -> missingNotificationHandler
472484
-- See Note [Shutdown]
473485
IsClientReq | shutdown, not (allowedMethod m) -> requestDuringShutdown msg
474-
where
475-
allowedMethod SMethod_Shutdown = True
476-
allowedMethod _ = False
477486
IsClientReq -> case pickHandler dynReqHandlers reqHandlers of
478487
Just h -> liftIO $ h msg (runLspT env . sendResponse msg)
479488
Nothing

0 commit comments

Comments
 (0)