Skip to content

mode :: Mode (CmdArgs Cmd) memoizes async exceptions, breaking HLS Shake restarts #1663

Description

@soulomoon

The top-level mode :: Mode (CmdArgs Cmd) in HLint is initialized using unsafePerformIO. If an asynchronous exception occurs during this initialization, the exception is captured and memoized in the CAF. As a result, every subsequent access to mode rethrows the same async exception.

In practice, this causes HLS to retain the cancel exception from an old Shake session and propagate it into the new session, immediately killing it.

See haskell/haskell-language-server#4718 (comment)

Activity

  1. soulomoon commented on Sep 7, 2025

    @soulomoon
    ContributorAuthor

    Minimal reproduction of the same problem:

    {-# LANGUAGE NumericUnderscores #-}
    module Main where
    import System.IO.Unsafe (unsafePerformIO)
    import Control.Concurrent
    import Control.Concurrent.Async
    import Control.Exception
    
    {-# NOINLINE initData #-}
    initData :: String
    initData = unsafePerformIO $ do
      threadDelay 1_000_000
      return "Initialized Data"
    
    threadRun :: IO String
    threadRun = do
      putStrLn "Thread started"
      evaluate initData
    
    main :: IO ()
    main = do
      putStrLn "Main started"
      oldRun <- async threadRun
      threadDelay 500_000
      cancel oldRun
    
      newRun <- async threadRun
      res <- waitCatch newRun
      print "First attempt:"
      print res
    
      newRun <- async threadRun
      res <- waitCatch newRun
      print "Second attempt:"
      print res
    
      putStrLn "Main ended"
    Main started
    Thread started
    Thread started
    "First attempt:"
    Left AsyncCancelled
    Thread started
    "Second attempt:"
    Left AsyncCancelled
    Main ended
    
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions