[Haskell-cafe] Double free-ing (was: Reading from a process)
Mitar
mmitar at gmail.com
Thu Dec 17 09:38:32 EST 2009
Hi!
On Thu, Dec 17, 2009 at 5:28 AM, Jason Dusek <jason.dusek at gmail.com> wrote:
> It seems like the message delimiter to me because you keep
> buffering till you receive it.
Hm, true. I have changed code to this:
getLastMyData :: MySate (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) $ slurpMyData
processOut processBuffer
case ret of
Left _ -> processExited -- EOF
Right (datalist, currentBuffer) -> do
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
slurpMyData :: Handle -> DataBuffer -> IO ([MyData], DataBuffer)
slurpMyData = slurpMyData' []
where slurpMyData' datalist h buffer@(DataBuffer capacity array
bytecount) = do
ready <- hReady h
if not ready
then return (datalist, buffer)
else do
let array' = advancePtr array bytecount
count <- hGetBufNonBlocking h array' (capacity - bytecount)
let bytecount' = bytecount + count
chars <- peekArray bytecount' array
let (d, rest) = readData . dataToString $ chars
rest' = stringToData rest
if null d
then if length rest' == capacity
then error "Invalid data from the process"
else return (datalist, buffer)
else do
assert (length rest' <= capacity) $ pokeArray array rest'
let buffer' = DataBuffer capacity array (length rest')
slurpMyData' (d ++ datalist) h buffer'
readData :: String -> ([MyData], String)
readData = readData' []
where readData' datalist "" = (datalist, "")
readData' datalist string = case reads string of
[(x, rest)] -> readData' ((head
x):datalist) rest -- x is a list and currently it has only one element
[] -> (datalist,
string) -- we probably do not have enough data to read MyData properly
_ -> error "Ambiguous
parse from the process"
And now it works. I just do not like using malloc and free.
And talking about free, I have now a problem of double freeing this
buffer. I am getting it after I send ctrl-c to the main process (with
underlying process I am communicating with). I am freeing it in
processExited:
processExited :: MyState a
processExited = do
terminateDataProcess
fail "Process exited"
terminateDataProcess :: MyState ()
terminateDataProcess = do
p <- gets process
case p of
Just (MyProcess _ processPid (DataBuffer _ array _)) -> do
modify (\s -> s { process = Nothing })
io $ free array
io $ terminateProcess processPid
_ -> return ()
So I run processExited if there is EOF from underlying process. But I
also run terminateDataProcess in a bracket I am calling getLastMyData.
Code is like this:
bracket initDataProcess terminateDataProcess (... read getLastMyData
repeatedly and process it ...)
Why I am getting this double free-ing errors? Should I introduce some
locks on terminateDataProcess?
I am using Linux 2.6.30 amd64 and 6.10.4.
Mitar
More information about the Haskell-Cafe
mailing list