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:
parent
c703c6f295
commit
9a5cd96f0d
4 changed files with 30 additions and 14 deletions
|
@ -1,6 +1,7 @@
|
||||||
git-annex (8.20201008) UNRELEASED; urgency=medium
|
git-annex (8.20201008) UNRELEASED; urgency=medium
|
||||||
|
|
||||||
* Fix build on Windows with network-3.
|
* Fix build on Windows with network-3.
|
||||||
|
* Fix a memory leak introduced in the last release.
|
||||||
|
|
||||||
-- Joey Hess <id@joeyh.name> Thu, 08 Oct 2020 10:48:17 -0400
|
-- Joey Hess <id@joeyh.name> Thu, 08 Oct 2020 10:48:17 -0400
|
||||||
|
|
||||||
|
|
|
@ -48,6 +48,7 @@ import CmdLine.Action
|
||||||
|
|
||||||
import Control.Concurrent.Async
|
import Control.Concurrent.Async
|
||||||
import System.Posix.Types
|
import System.Posix.Types
|
||||||
|
import Data.IORef
|
||||||
|
|
||||||
data AnnexedFileSeeker = AnnexedFileSeeker
|
data AnnexedFileSeeker = AnnexedFileSeeker
|
||||||
{ startAction :: SeekInput -> RawFilePath -> Key -> CommandStart
|
{ 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 :: (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
|
seekHelper c ww a (WorkTreeItems l) = do
|
||||||
os <- seekOptions ww
|
os <- seekOptions ww
|
||||||
inRepo $ \g -> combinelists <$> forM (segmentXargsOrdered l)
|
v <- liftIO $ newIORef []
|
||||||
(runSegmentPaths' mk c (\fs -> a os fs g) . map toRawFilePath)
|
r <- inRepo $ \g -> concat . concat <$> forM (segmentXargsOrdered l)
|
||||||
|
(runSegmentPaths' mk c (\fs -> go v os fs g) . map toRawFilePath)
|
||||||
|
return (r, cleanupall v)
|
||||||
where
|
where
|
||||||
mk (Just i) f = (SeekInput [fromRawFilePath i], f)
|
mk (Just i) f = (SeekInput [fromRawFilePath i], f)
|
||||||
-- This is not accurate, but it only happens when there are a
|
-- This is not accurate, but it only happens when there are a
|
||||||
-- great many input WorkTreeItems.
|
-- great many input WorkTreeItems.
|
||||||
mk Nothing f = (SeekInput [fromRawFilePath (c f)], f)
|
mk Nothing f = (SeekInput [fromRawFilePath (c f)], f)
|
||||||
|
|
||||||
combinelists v =
|
go v os fs g = do
|
||||||
let r = concat $ concat $ map fst v
|
(l, cleanup) <- a os fs g
|
||||||
cleanup = and <$> sequence (map snd v)
|
liftIO $ modifyIORef' v (cleanup:)
|
||||||
in (r, cleanup)
|
return l
|
||||||
|
|
||||||
|
cleanupall v = do
|
||||||
|
cleanups <- readIORef v
|
||||||
|
and <$> sequence cleanups
|
||||||
seekHelper _ _ _ NoWorkTreeItems = return ([], pure True)
|
seekHelper _ _ _ NoWorkTreeItems = return ([], pure True)
|
||||||
|
|
||||||
data WarnUnmatchWhen = WarnUnmatchLsFiles | WarnUnmatchWorkTreeItems
|
data WarnUnmatchWhen = WarnUnmatchLsFiles | WarnUnmatchWorkTreeItems
|
||||||
|
|
|
@ -235,15 +235,11 @@ segmentPaths' f c (i:is) new =
|
||||||
- than it would be to run the action separately with each path. In
|
- than it would be to run the action separately with each path. In
|
||||||
- the case of git file list commands, that assumption tends to hold.
|
- the case of git file list commands, that assumption tends to hold.
|
||||||
-}
|
-}
|
||||||
runSegmentPaths :: (a -> RawFilePath) -> ([RawFilePath] -> IO ([a], v)) -> [RawFilePath] -> IO ([[a]], v)
|
runSegmentPaths :: (a -> RawFilePath) -> ([RawFilePath] -> IO [a]) -> [RawFilePath] -> IO [[a]]
|
||||||
runSegmentPaths c a paths = do
|
runSegmentPaths c a paths = segmentPaths c paths <$> a paths
|
||||||
(l, cleanup) <- a paths
|
|
||||||
return (segmentPaths c paths l, cleanup)
|
|
||||||
|
|
||||||
runSegmentPaths' :: (Maybe RawFilePath -> a -> r) -> (a -> RawFilePath) -> ([RawFilePath] -> IO ([a], v)) -> [RawFilePath] -> IO ([[r]], v)
|
runSegmentPaths' :: (Maybe RawFilePath -> a -> r) -> (a -> RawFilePath) -> ([RawFilePath] -> IO [a]) -> [RawFilePath] -> IO [[r]]
|
||||||
runSegmentPaths' si c a paths = do
|
runSegmentPaths' si c a paths = segmentPaths' si c paths <$> a paths
|
||||||
(l, cleanup) <- a paths
|
|
||||||
return (segmentPaths' si c paths l, cleanup)
|
|
||||||
|
|
||||||
{- Converts paths in the home directory to use ~/ -}
|
{- Converts paths in the home directory to use ~/ -}
|
||||||
relHome :: FilePath -> IO String
|
relHome :: FilePath -> IO String
|
||||||
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
[[!comment format=mdwn
|
||||||
|
username="joey"
|
||||||
|
subject="""comment 8"""
|
||||||
|
date="2020-10-13T19:52:50Z"
|
||||||
|
content="""
|
||||||
|
[[!commit f624876dc21fed141eee368c86f4b209852ab91c]] is where seekHelper
|
||||||
|
went bad. Fixed that.
|
||||||
|
|
||||||
|
git-annex is still allocating 120 mb in this situation, though the
|
||||||
|
profile now shows a max memory use of 4 mb. Still don't understand that, so
|
||||||
|
this remains open.
|
||||||
|
"""]]
|
Loading…
Reference in a new issue