Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 17 additions & 12 deletions Cabal/src/Distribution/Compat/Internal/TempFile.hs
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,11 @@ module Distribution.Compat.Internal.TempFile

import Distribution.Compat.Exception

import GHC.IORef (IORef, atomicModifyIORef'_, newIORef)
import System.FilePath ((</>))

import System.IO (Handle, openBinaryTempFile, openBinaryTempFileWithDefaultPermissions, openTempFile)
import System.IO.Error (isAlreadyExistsError)
import System.IO.Unsafe (unsafePerformIO)
import System.Posix.Internals (c_getpid)

#if defined(mingw32_HOST_OS) || defined(ghcjs_HOST_OS)
Expand All @@ -28,17 +29,21 @@ openNewBinaryFile = openBinaryTempFileWithDefaultPermissions
createTempDirectory :: FilePath -> String -> IO FilePath
createTempDirectory dir template = do
pid <- c_getpid
findTempName pid
where
findTempName x = do
let relpath = template ++ "-" ++ show x
dirpath = dir </> relpath
r <- tryIO $ mkPrivateDir dirpath
case r of
Right _ -> return relpath
Left e
| isAlreadyExistsError e -> findTempName (x + 1)
| otherwise -> ioError e
let findTempName = do
(counter, _) <- atomicModifyIORef'_ tempDirectoryCounter (+ 1)
let relpath = template ++ "-" ++ show pid ++ show counter
dirpath = dir </> relpath
r <- tryIO $ mkPrivateDir dirpath
case r of
Right _ -> pure relpath
Left e
| isAlreadyExistsError e -> findTempName
| otherwise -> ioError e
findTempName

tempDirectoryCounter :: IORef Word
tempDirectoryCounter = unsafePerformIO $ newIORef 0
{-# NOINLINE tempDirectoryCounter #-}

mkPrivateDir :: String -> IO ()
#if defined(mingw32_HOST_OS) || defined(ghcjs_HOST_OS)
Expand Down
7 changes: 7 additions & 0 deletions changelog.d/pr-11872.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
synopsis: Improve name assigning for temporary folders
packages: [Cabal,cabal-install]
prs: 11872
---

Now `createTempDirectory` from `Distribution.Compat.Internal.TempFile` uses a global counter as a part of temporary folder name template, so that probing is less likely to fail. The change should be invisible for users.
Loading