Proposal: System.Timeout module for base (Trac #980)

Peter Simons simons at cryp.to
Thu Mar 1 14:57:25 EST 2007


Johannes Waldmann writes:

 > I have two (or more) threads (created by forkIO) and each does an
 > external ( System.Cmd.system ) call. When the first of these
 > returns, the others should be killed.

Unfortunately, 'timeout' doesn't help solving that problem. What you
are looking for is 'terminateProcess':

  import System.IO
  import System.Process
  import Control.Concurrent ( threadDelay )

  run :: FilePath -> Maybe Handle -> Maybe Handle -> IO ProcessHandle
  run cmd hin hout = runProcess cmd [] Nothing Nothing hin hout Nothing

  main :: IO ()
  main = do
    pid <- withFile "/dev/urandom" ReadMode $ \hin ->
             withFile "/dev/null" WriteMode $ \hout ->
               run "/usr/bin/cat" (Just hin) (Just hout)
    threadDelay (5*10^6)          -- sleep 5 seconds
    terminateProcess pid          -- send kill signal
    waitForProcess pid >>= print  -- wait on termination

A mechanism that terminates all external processes once one of them
terminates is easily defined using 'Control.Exception.bracket'. You'll
find that the code structure is quite similar to timeout:

  main' :: IO ()
  main' = do
    let start  = withFile "/dev/urandom" ReadMode $ \hin ->
                 withFile "/dev/null" WriteMode $ \hout ->
                 run "/usr/bin/cat" (Just hin) (Just hout)
        stop p = terminateProcess p >> waitForProcess p
    bracket start stop $ \_ ->
      bracket start stop $ \_ ->
        bracket start stop $ \_ ->
          bracket start stop $ \_ ->
            return () -- kill em all NOW

I hope this helps.

Peter



More information about the Libraries mailing list