Skip to content
Snippets Groups Projects
Commit 4a0b05a3 authored by Robert's avatar Robert Committed by mergify-bot
Browse files

Use async-safe bracket for withTempFileName

If `withTempFileName` receives an asynchronous exception (e.g.
a canceled async), the bracket cleanup handler will attempt to
remove the temporary file. This can fail with an IO exception.

Regular bracket then throws that IO exception, swallowing the
asynchronous exception. To calling code, this appears no different
from an IO exception thrown from the body, and it won't be able
to tell that it should be exiting promptly.

This manifests concretely during temporary file clean-up of
`asyncFetchPackages` on Windows (seen during unit testing in CI),
where temporary file removal fails (on GHC 8.4), which leads
to `concurrently` failing to cancel the outstanding download
because it's handled like a regular download failure.
parent deca6e7b
No related branches found
No related tags found
No related merge requests found
......@@ -49,7 +49,9 @@ import Data.List
( groupBy )
import Foreign.C.Types ( CInt(..) )
import qualified Control.Exception as Exception
( finally, bracket )
( finally )
import qualified Control.Exception.Safe as Safe
( bracket )
import System.Directory
( canonicalizePath, doesFileExist, findExecutable, getCurrentDirectory
, removeFile, setCurrentDirectory, getDirectoryContents, doesDirectoryExist )
......@@ -118,7 +120,7 @@ withTempFileName :: FilePath
-> String
-> (FilePath -> IO a) -> IO a
withTempFileName tmpDir template action =
Exception.bracket
Safe.bracket
(openTempFile tmpDir template)
(\(name, _) -> removeExistingFile name)
(\(name, h) -> hClose h >> action name)
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment