On Thu, Jan 08, 2004 at 09:33:29AM -0800, Hal Daume III wrote: > Hi, > > I'm using POpen to shell out to a command several hundreds or thousands of > times per call (none of them simultaneous, though, this is completely > serial). After running my program for a while, I get: > > Fail: resource exhausted > Action: forkProcess > Reason: Resource temporarily unavailable > > which basically seems to be telling me that the program hasn't been > closing the old processes, even though they're definitely not in use > anymore. > > Does anyone have any suggestions how to get around this?
I had a similar problem, and finally I created my own solution that doesn't leave zombies and doesn't block when the launched process writes too much to stderr. I tested it in GHC 6.0. For 6.2 you'd have to change the use of forkProcess. Usage: launch :: String -> [String] -> String -> IO (ProcessStatus, String, String) (status, out, err) <- launch prog args progInput Example: *Shell> (status, out, err) <- launch "tr" ["a-z", "A-Z"] (unlines (replicate 10000 "Haskell")) *Shell> status Exited ExitSuccess *Shell> length out 80000 *Shell> mapM_ putStrLn (take 10 (lines out)) HASKELL HASKELL HASKELL HASKELL HASKELL HASKELL HASKELL HASKELL HASKELL HASKELL Best regards, Tom -- .signature: Too many levels of symbolic links
module Shell where import System.Posix.Process import System.Posix.IO import Control.Concurrent import IO launch :: String -> [String] -> String -> IO (ProcessStatus, String, String) launch prog args inputStr = do (childIn, parentIn) <- createPipe (parentOut, childOut) <- createPipe (parentErr, childErr) <- createPipe forkProcess >>= \pid -> case pid of Nothing -> do -- child closeFd parentIn closeFd parentOut closeFd parentErr closeFd 0 -- FIXME: What if some of 0,1,2 are already closed? closeFd 1 closeFd 2 childIn `dupTo` 0 childOut `dupTo` 1 childErr `dupTo` 2 closeFd childIn closeFd childOut closeFd childErr executeFile prog True args Nothing fail "launch: executeFile failed" Just child -> do -- parent closeFd childIn closeFd childOut closeFd childErr input <- fdToHandle parentIn output <- fdToHandle parentOut err <- fdToHandle parentErr outputCS <- hGetContents output errCS <- hGetContents err outputMV <- newEmptyMVar errMV <- newEmptyMVar inputMV <- newEmptyMVar forkIO $ hPutStr input inputStr >> hClose input >> putMVar inputMV () forkIO $ foldr seq () outputCS `seq` hClose output >> putMVar outputMV () forkIO $ foldr seq () errCS `seq` hClose err >> putMVar errMV () takeMVar outputMV takeMVar errMV takeMVar inputMV mStatus <- getProcessStatus True False child case mStatus of Nothing -> fail "launch: can't get child process status" Just stat -> return (stat, outputCS, errCS)
_______________________________________________ Glasgow-haskell-users mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/glasgow-haskell-users