Skip to content

Commit dd7e768

Browse files
committed
[fix] don't throw hard errors when no shutdown message is handled
Previously, when there was no shutdown message by a client and the client disconnected, resulting in the handlers to be GC'd the race that was supposed to free resources for the HieDB & co. would throw a hard error talking about the MVar being unreachable. We would like to instead finish gracefully because finishing the race as soon as the MVar was GC'd is the right thing to do anyway.
1 parent 2ea1046 commit dd7e768

File tree

1 file changed

+6
-3
lines changed

1 file changed

+6
-3
lines changed

ghcide/src/Development/IDE/LSP/LanguageServer.hs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ import UnliftIO.Directory
3434
import UnliftIO.Exception
3535

3636
import qualified Colog.Core as Colog
37+
import Control.Exception (BlockedIndefinitelyOnMVar (..))
3738
import Control.Monad.IO.Unlift (MonadUnliftIO)
3839
import Control.Monad.Trans.Cont (evalContT)
3940
import Development.IDE.Core.IdeConfiguration
@@ -265,11 +266,13 @@ runWithWorkerThreads recorder dbLoc f = evalContT $ do
265266
(WithHieDbShield hiedb, threadQueue) <- runWithDb recorder dbLoc
266267
liftIO $ f hiedb (ThreadQueue threadQueue sessionRestartTQueue sessionLoaderTQueue)
267268

268-
-- | Runs the action until it ends or until the given MVar is put.
269+
-- | Runs the action until it ends or until the given MVar is put or the thread to fill the mvar is dropped, in which case the MVar will never be filled.
270+
-- This happens when the thread that handles the shutdown notification dies. Ideally, this should not rely on the RTS detecting the blocked MVar
271+
-- and instead *also* run the shutdown inf a finally block enclosing the handlers. In which case the BlockedIndefinitelyOnMVar Exception also wouldn't
272+
-- be thrown.
269273
-- Rethrows any exceptions.
270274
untilMVar :: MonadUnliftIO m => MVar () -> m () -> m ()
271-
untilMVar mvar io = void $
272-
waitAnyCancel =<< traverse async [ io , readMVar mvar ]
275+
untilMVar mvar io = race_ (readMVar mvar `catch` \BlockedIndefinitelyOnMVar -> pure ()) io
273276

274277
cancelHandler :: (SomeLspId -> IO ()) -> LSP.Handlers (ServerM c)
275278
cancelHandler cancelRequest = LSP.notificationHandler SMethod_CancelRequest $ \TNotificationMessage{_params=CancelParams{_id}} ->

0 commit comments

Comments
 (0)