[Haskell-cafe] Reading from a process
Mitar
mmitar at gmail.com
Wed Dec 16 15:19:09 EST 2009
Hi!
I would like to make an one-directional inter-process communication in
a way that one process is printing out read-compatible Haskell data
types and Haskell program is reading them from a pipe. I would like to
make a function which would return Nothing if there is no data type in
a pipe or Just last data type there was in a pipe (discarding all
before). So it should behave in a non-blocking way.
In an attempt I made this:
getLastMyData :: MyState (Maybe MyData)
getLastMyData = do
p <- gets process
case p of
Nothing -> fail "No process"
Just (MyProcess processOut processPid processBuffer) -> do
processRunning <- io $ getProcessExitCode processPid
case processRunning of
Just _ -> processExited
_ -> do
ret <- io $ tryJust (guard . isEOFError) $ slurpInput
processOut processBuffer
case ret of
Left _ -> processExited -- EOF
Right currentBuffer -> do
let (datalist, currentBuffer') = readData currentBuffer
modify (\s -> s { process = Just (MyProcess processOut
processPid currentBuffer') })
if null datalist
then return Nothing
else return $ Just $ head datalist -- MyData is stored
in the reverse order so head is the last MyData from the process
slurpInput :: Handle -> String -> IO String
slurpInput h buffer = do
ready <- hReady h
if not ready
then return buffer
else do
char <- hGetChar h
slurpInput h (buffer ++ [char])
readData :: String -> ([MyData], String)
readData buffer = readData' [] buffer
where readData' datalist [] = (datalist, [])
readData' datalist buf = case reads buf of
[(x, rest)] -> readData' ((head
x):datalist) rest -- x is a list and currently it has only one element
[] -> if length buf > 5 *
maxMyDataDescLength
then error
"Invalid data from process"
else (datalist,
buf) -- we probably do not have enough data to read MyData properly
_ -> error "Ambiguous
parse from process"
(I have cleaned a code somewhat, I hope I have not introduced any
errors. MyData is encapsulated in a list when printed from a process,
this is why is there "head".)
The problem is that I do not like this approach. And it does not look
nice. For example I am reading byte per byte and appending it to the
end. Then the problem is that if process is sending garbage faster
then Haskell can consume it Haskell stays in slurpInput function and
never gets to readData where it would found out that there is garbage
coming in. I could use hGetBufNonBlocking? But it would still not
solve garbage problem.
So is there some better way to do it?
Mitar
More information about the Haskell-Cafe
mailing list