Commit cc35a48a authored by Duncan Coutts's avatar Duncan Coutts
Browse files

Report process output decoding errors in context

It turns out that in rawSystemStdInOut any IO errors, including text
decoding, occurring while collecting the output (stderr or stdout) do
not get reported immediately, but only later if/when the output is
consumed. This is because the exceptions happened in the threads forked
to force the output, but if the main thread looks at the output later
then the exception is reported again.

This leads to very confusing results. In particular we had a case where
the configure process did not fail until writing out the LocalBuildInfo
because that was the first point that forced the output. So the distance
from when the exception really occurred and the fact that the exception
message does not include the name of the program run means that this is
then a pain to track down.

This patch makes sure that any exceptions arising from forcing the
program output occur immediately and with an error message that includes
the name of the program in question.
parent 41714567
......@@ -555,9 +555,9 @@ rawSystemStdInOut verbosity path args mcwd menv input outputBinary = do
out <- hGetContents outh
mv <- newEmptyMVar
let force str = (evaluate (length str) >> return ())
`Exception.finally` putMVar mv ()
--TODO: handle exceptions like text decoding.
let force str = do
mberr <- Exception.try (evaluate (length str) >> return ())
putMVar mv (mberr :: Either IOError ())
_ <- forkIO $ force out
_ <- forkIO $ force err
......@@ -573,8 +573,8 @@ rawSystemStdInOut verbosity path args mcwd menv input outputBinary = do
-- or if it closes stdin (eg if it exits)
-- wait for both to finish, in either order
takeMVar mv
takeMVar mv
mberr1 <- takeMVar mv
mberr2 <- takeMVar mv
-- wait for the program to terminate
exitcode <- waitForProcess pid
......@@ -587,7 +587,17 @@ rawSystemStdInOut verbosity path args mcwd menv input outputBinary = do
Just ("", _) -> ""
Just (inp, _) -> "\nstdin input:\n" ++ inp
-- Check if we we hit an exception while consuming the output
-- (e.g. a text decoding error)
reportOutputIOError mberr1
reportOutputIOError mberr2
return (out, err, exitcode)
where
reportOutputIOError :: Either IOError () -> IO ()
reportOutputIOError =
either (\e -> throwIO (ioeSetFileName e ("output of " ++ path)))
return
{-# DEPRECATED findProgramLocation
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment