Fix a memory leak introduced in the last release

The problem was this line:

	cleanup = and <$> sequence (map snd v)

That caused all of v to be held onto until the end, when the cleanup action
was run.

I could not seem to find a bang pattern that avoided the leak, so I
resorted to a IORef, rather clunky, but not a performance problem because
it will only be written once per git ls-files, so typically just 1 time.

This commit was sponsored by Mark Reidenbach on Patreon.
This commit is contained in:
Joey Hess 2020-10-13 16:31:01 -04:00
parent c703c6f295
commit 9a5cd96f0d
No known key found for this signature in database
GPG key ID: DB12DB0FF05F8F38
4 changed files with 30 additions and 14 deletions

View file

@ -48,6 +48,7 @@ import CmdLine.Action
import Control.Concurrent.Async
import System.Posix.Types
import Data.IORef
data AnnexedFileSeeker = AnnexedFileSeeker
{ startAction :: SeekInput -> RawFilePath -> Key -> CommandStart
@ -416,18 +417,24 @@ seekFilteredKeys seeker listfs = do
seekHelper :: (a -> RawFilePath) -> WarnUnmatchWhen -> ([LsFiles.Options] -> [RawFilePath] -> Git.Repo -> IO ([a], IO Bool)) -> WorkTreeItems -> Annex ([(SeekInput, a)], IO Bool)
seekHelper c ww a (WorkTreeItems l) = do
os <- seekOptions ww
inRepo $ \g -> combinelists <$> forM (segmentXargsOrdered l)
(runSegmentPaths' mk c (\fs -> a os fs g) . map toRawFilePath)
v <- liftIO $ newIORef []
r <- inRepo $ \g -> concat . concat <$> forM (segmentXargsOrdered l)
(runSegmentPaths' mk c (\fs -> go v os fs g) . map toRawFilePath)
return (r, cleanupall v)
where
mk (Just i) f = (SeekInput [fromRawFilePath i], f)
-- This is not accurate, but it only happens when there are a
-- great many input WorkTreeItems.
mk Nothing f = (SeekInput [fromRawFilePath (c f)], f)
combinelists v =
let r = concat $ concat $ map fst v
cleanup = and <$> sequence (map snd v)
in (r, cleanup)
go v os fs g = do
(l, cleanup) <- a os fs g
liftIO $ modifyIORef' v (cleanup:)
return l
cleanupall v = do
cleanups <- readIORef v
and <$> sequence cleanups
seekHelper _ _ _ NoWorkTreeItems = return ([], pure True)
data WarnUnmatchWhen = WarnUnmatchLsFiles | WarnUnmatchWorkTreeItems