Use ProcessHandle in withServer to allow kill it by client code
[lsp-test.git] / src / Language / Haskell / LSP / Test / Server.hs
index 473f2c76e1c39c46252e0f1b0a0933a05db60185..0a77a6193e6fb9c320531e65f74255576bccf8f4 100644 (file)
@@ -1,28 +1,21 @@
 module Language.Haskell.LSP.Test.Server (withServer) where
 
-import Control.Concurrent
+import Control.Concurrent.Async
 import Control.Monad
-import Data.Maybe
 import System.IO
 import System.Process
 
-withServer :: String -> (Handle -> Handle -> Int -> IO a) -> IO a
-withServer serverExe f = do
+withServer :: String -> Bool -> (Handle -> Handle -> ProcessHandle -> IO a) -> IO a
+withServer serverExe logStdErr f = do
   -- TODO Probably should just change runServer to accept
   -- separate command and arguments
   let cmd:args = words serverExe
       createProc = (proc cmd args) { std_in = CreatePipe, std_out = CreatePipe, std_err = CreatePipe }
-  (Just serverIn, Just serverOut, Just serverErr, serverProc) <- createProcess createProc
-
+  withCreateProcess createProc $ \(Just serverIn) (Just serverOut) (Just serverErr) serverProc -> do
     -- Need to continuously consume to stderr else it gets blocked
     -- Can't pass NoStream either to std_err
     hSetBuffering serverErr NoBuffering
-  errSinkThread <- forkIO $ forever $ hGetLine serverErr
-
-  pid <- fromIntegral . fromJust <$> getPid serverProc
-
-  result <- f serverIn serverOut pid
-
-  killThread errSinkThread
-  terminateProcess serverProc
-  return result
+    hSetBinaryMode serverErr True
+    let errSinkThread = forever $ hGetLine serverErr >>= when logStdErr . putStrLn
+    withAsync errSinkThread $ \_ -> do
+      f serverIn serverOut serverProc