Skip to content

Commit a4e7c4e

Browse files
committed
Prevent files from being partially read from the cache
1 parent ebe6e9b commit a4e7c4e

File tree

2 files changed

+20
-4
lines changed

2 files changed

+20
-4
lines changed

SCons/CacheDir.py

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,20 @@ def CacheRetrieveFunc(target, source, env):
5555
if fs.islink(cachefile):
5656
fs.symlink(fs.readlink(cachefile), t.get_internal_path())
5757
else:
58-
env.copy_from_cache(cachefile, t.get_internal_path())
58+
try:
59+
env.copy_from_cache(cachefile, t.get_internal_path())
60+
except:
61+
try:
62+
# In case file was partially retrieved (and now corrupt)
63+
# delete it to avoid poisoning commands like 'ar' that
64+
# read from the initial state of the file they are writing
65+
# to.
66+
t.fs.unlink(t.get_internal_path())
67+
except:
68+
pass
69+
70+
raise
71+
5972
try:
6073
os.utime(cachefile, None)
6174
except OSError:
@@ -70,7 +83,7 @@ def CacheRetrieveString(target, source, env):
7083
cd = env.get_CacheDir()
7184
cachedir, cachefile = cd.cachepath(t)
7285
if t.fs.exists(cachefile):
73-
return "Retrieved `%s' from cache" % t.get_internal_path()
86+
return "Retrieving `%s' from cache" % t.get_internal_path()
7487
return None
7588

7689
CacheRetrieve = SCons.Action.Action(CacheRetrieveFunc, CacheRetrieveString)

SCons/Taskmaster.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -223,10 +223,13 @@ def execute(self):
223223
cached_targets.append(t)
224224
if len(cached_targets) < len(self.targets):
225225
# Remove targets before building. It's possible that we
226-
# partially retrieved targets from the cache, leaving
227-
# them in read-only mode. That might cause the command
226+
# retrieved a subset of targets from the cache, leaving
227+
# them in an inconsistent state. That might cause the command
228228
# to fail.
229229
#
230+
# Note that retrieve_from_cache() ensures no single target can
231+
# be partially retrieved (file left in corrupt state).
232+
#
230233
for t in cached_targets:
231234
try:
232235
t.fs.unlink(t.get_internal_path())

0 commit comments

Comments
 (0)