@@ -21,8 +21,6 @@ import Neovim.RPC.Common (newRPCConfig, RPCConfig)
2121import Neovim.RPC.EventHandler (runEventHandler )
2222import Neovim.RPC.SocketReader (runSocketReader )
2323
24- import Control.Concurrent
25- import Control.Concurrent.STM (atomically , putTMVar )
2624import Control.Monad.Reader (runReaderT )
2725import Control.Monad.Trans.Resource (runResourceT )
2826import GHC.IO.Exception (ioe_filename )
@@ -32,6 +30,9 @@ import System.IO (Handle)
3230import System.Process
3331import Text.PrettyPrint.ANSI.Leijen (red , text , putDoc , (<$$>) )
3432import UnliftIO.Exception
33+ import UnliftIO.STM (atomically , putTMVar )
34+ import UnliftIO.Async (async , cancel )
35+ import UnliftIO.Concurrent (threadDelay )
3536
3637
3738-- | Type synonym for 'Word'.
@@ -55,7 +56,7 @@ testWithEmbeddedNeovim file timeout r (Internal.Neovim a) =
5556 runTest `catch` catchIfNvimIsNotOnPath
5657 where
5758 runTest = do
58- (_, _, ph, cfg) <- startEmbeddedNvim file timeout
59+ (_, _, ph, cfg, cleanUp ) <- startEmbeddedNvim file timeout
5960
6061 let testCfg = Internal. retypeConfig r cfg
6162
@@ -65,14 +66,16 @@ testWithEmbeddedNeovim file timeout r (Internal.Neovim a) =
6566 -- result of the operation since neovim cannot send a result if it
6667 -- has quit.
6768 let Internal. Neovim q = vim_command " qa!"
68- void . forkIO . void $ runReaderT (runResourceT q) testCfg
69+ testRunner <- async . void $ runReaderT (runResourceT q) testCfg
6970
7071 waitForProcess ph >>= \ case
7172 ExitFailure i ->
7273 fail $ " Neovim returned with an exit status of: " ++ show i
7374
7475 ExitSuccess ->
7576 return ()
77+ cancel testRunner
78+ cleanUp
7679
7780
7881catchIfNvimIsNotOnPath :: IOException -> IO ()
@@ -87,7 +90,7 @@ catchIfNvimIsNotOnPath e = case ioe_filename e of
8790startEmbeddedNvim
8891 :: Maybe FilePath
8992 -> Seconds
90- -> IO (Handle , Handle , ProcessHandle , Internal. Config RPCConfig )
93+ -> IO (Handle , Handle , ProcessHandle , Internal. Config RPCConfig , IO () )
9194startEmbeddedNvim file (Seconds timeout) = do
9295 args <- case file of
9396 Nothing ->
@@ -107,21 +110,23 @@ startEmbeddedNvim file (Seconds timeout) = do
107110
108111 cfg <- Internal. newConfig (pure Nothing ) newRPCConfig
109112
110- void . forkIO $ runSocketReader
113+ socketReader <- async . void $ runSocketReader
111114 hout
112115 (cfg { Internal. pluginSettings = Nothing })
113116
114- void . forkIO $ runEventHandler
117+ eventHandler <- async . void $ runEventHandler
115118 hin
116119 (cfg { Internal. pluginSettings = Nothing })
117120
118121 atomically $ putTMVar
119122 (Internal. globalFunctionMap cfg)
120123 (Internal. mkFunctionMap [] )
121124
122- void . forkIO $ do
125+ timeoutAsync <- async . void $ do
123126 threadDelay $ (fromIntegral timeout) * 1000 * 1000
124127 getProcessExitCode ph >>= maybe (terminateProcess ph) (\ _ -> return () )
125128
126- return (hin, hout, ph, cfg)
129+ let cleanUp = mapM_ cancel [socketReader, eventHandler, timeoutAsync]
130+
131+ return (hin, hout, ph, cfg, cleanUp)
127132
0 commit comments