@@ -39,6 +39,8 @@ main = do
39
39
testGetPid
40
40
testReadProcess
41
41
testInterruptWith
42
+ testDoubleWait
43
+ testKillDoubleWait
42
44
putStrLn " >>> Tests passed successfully"
43
45
44
46
run :: String -> IO () -> IO ()
@@ -195,6 +197,61 @@ testInterruptWith = run "interrupt withCreateProcess" $ do
195
197
threadDelay 1000 -- give some time for threads to finish
196
198
readIORef exceptions
197
199
200
+ -- Test that we can wait without exception twice, if the process exited on its own.
201
+ testDoubleWait :: IO ()
202
+ testDoubleWait = run " run process, then wait twice" $ do
203
+ let sleep = (proc " sleep" [" 0" ])
204
+ (_, _, _, p) <- createProcess sleep
205
+ res <- try $ waitForProcess p
206
+ case res of
207
+ Left e -> error $ " waitForProcess threw: " <> show (e :: SomeException )
208
+ Right ExitSuccess -> return ()
209
+ Right exitCode -> error $ " unexpected exit code: " <> show exitCode
210
+
211
+ res2 <- try $ waitForProcess p
212
+ case res2 of
213
+ Left e -> error $ " second waitForProcess threw: " <> show (e :: SomeException )
214
+ Right ExitSuccess -> return ()
215
+ Right exitCode -> error $ " unexpected exit code: " <> show exitCode
216
+
217
+ -- Test that we can wait without exception twice, if the process was killed.
218
+ testKillDoubleWait :: IO ()
219
+ testKillDoubleWait = do
220
+ run " terminate process, then wait twice (delegate_ctlc = False)" $ runTest " TERM" False
221
+ run " terminate process, then wait twice (delegate_ctlc = True)" $ runTest " TERM" True
222
+ run " interrupt process, then wait twice (delegate_ctlc = False)" $ runTest " INT" False
223
+ run " interrupt process, then wait twice (delegate_ctlc = True)" $ runTest " INT" True
224
+ where
225
+ runTest sig delegate = do
226
+ let sleep = (proc " sleep" [" 10" ])
227
+ (_, _, _, p) <- createProcess sleep { delegate_ctlc = delegate }
228
+ Just pid <- getPid p
229
+ void $ readProcess " kill" [" -" <> sig, show pid] " "
230
+
231
+ res <- try $ waitForProcess p
232
+ checkFirst sig delegate res
233
+
234
+ res' <- try $ waitForProcess p
235
+ checkSecond sig delegate res'
236
+
237
+ checkFirst :: String -> Bool -> Either SomeException ExitCode -> IO ()
238
+ checkFirst sig delegate res = case (sig, delegate) of
239
+ (" INT" , True ) -> case res of
240
+ Left e -> case fromException e of
241
+ Just UserInterrupt -> putStrLn " result ok"
242
+ Nothing -> error $ " waitForProcess threw: " <> show e
243
+ Right _ -> error $ " expected exception, got " <> show res
244
+ _ -> case res of
245
+ Left e -> error $ " waitForProcess threw: " <> show e
246
+ Right ExitSuccess -> error " waitForProcess: expected failure code"
247
+ _ -> putStrLn " result ok"
248
+
249
+ checkSecond :: String -> Bool -> Either SomeException ExitCode -> IO ()
250
+ checkSecond sig delegate res = case (sig, delegate) of
251
+ (" INT" , True ) -> checkFirst " INT" False res -- TODO: should this also throw?
252
+ _ -> checkFirst sig delegate res
253
+
254
+
198
255
withCurrentDirectory :: FilePath -> IO a -> IO a
199
256
withCurrentDirectory new inner = do
200
257
orig <- getCurrentDirectory
0 commit comments