Add cleanupRunningProcess to Compat module
authorjneira <atreyu.bbb@gmail.com>
Wed, 17 Jul 2019 12:57:26 +0000 (14:57 +0200)
committerjneira <atreyu.bbb@gmail.com>
Wed, 17 Jul 2019 12:57:26 +0000 (14:57 +0200)
src/Language/Haskell/LSP/Test/Compat.hs
src/Language/Haskell/LSP/Test/Session.hs

index 9467a322597cc75ed0d16c1f4010e9cb537b6cd0..ddf4a7893e9c4a635a007b91981e6077bfa6c86b 100644 (file)
@@ -6,10 +6,11 @@
 module Language.Haskell.LSP.Test.Compat where
 
 import Data.Maybe
+import System.IO
 
 #if MIN_VERSION_process(1,6,3)
-import System.Process hiding (getPid)
-import qualified System.Process (getPid)
+import System.Process hiding (getPid, cleanupProcess)
+import qualified System.Process (getPid, cleanupProcess)
 #else
 import System.Process
 import System.Process.Internals
@@ -52,3 +53,24 @@ getProcessID p = fromIntegral . fromJust <$> getProcessID' p
 #endif
       _ -> return Nothing
 #endif
+
+cleanupRunningProcess :: (Maybe Handle, Maybe Handle, Maybe Handle, ProcessHandle) -> IO ()
+cleanupRunningProcess p@(_, _, _, ph) =
+  getProcessExitCode ph >>= maybe (cleanupProcess p) (const $ return ())
+
+cleanupProcess :: (Maybe Handle, Maybe Handle, Maybe Handle, ProcessHandle) -> IO ()
+#if MIN_VERSION_process(1,6,3)
+cleanupProcess = System.Process.cleanupProcess
+#else
+cleanupProcess (mb_stdin, mb_stdout, mb_stderr, ph) = do
+
+    terminateProcess ph
+    -- Note, it's important that other threads that might be reading/writing
+    -- these handles also get killed off, since otherwise they might be holding
+    -- the handle lock and prevent us from closing, leading to deadlock.
+    maybe (return ()) hClose mb_stdin
+    maybe (return ()) hClose mb_stdout
+    maybe (return ()) hClose mb_stderr
+
+    return ()
+#endif
index f85eed92cfef9ead64e32007c5422188787f63a6..bbfdf386ac167bd0f8ab5b9a277b754920aacf57 100644 (file)
@@ -60,12 +60,13 @@ import Language.Haskell.LSP.Types.Capabilities
 import Language.Haskell.LSP.Types
 import Language.Haskell.LSP.Types.Lens hiding (error)
 import Language.Haskell.LSP.VFS
+import Language.Haskell.LSP.Test.Compat
 import Language.Haskell.LSP.Test.Decoding
 import Language.Haskell.LSP.Test.Exceptions
 import System.Console.ANSI
 import System.Directory
 import System.IO
-import System.Process
+import System.Process (ProcessHandle())
 import System.Timeout
 
 -- | A session representing one instance of launching and connecting to a server.
@@ -222,9 +223,7 @@ runSessionWithHandles serverIn serverOut serverProc serverHandler config caps ro
       server = (Just serverIn, Just serverOut, Nothing, serverProc)
       serverFinalizer tid = finally (timeout (messageTimeout config * 1000000)
                                              (runSession' exitServer))
-                                    (terminateProcess serverProc
-                                      >> hClose serverOut
-                                      >> killThread tid)
+                                    (cleanupRunningProcess server >> killThread tid)
       
   (result, _) <- bracket serverLauncher serverFinalizer (const $ runSession' session)
   return result