Retry deletion of temporary files to avoid race conditions on Windows.

Differential Revision: http://reviews.llvm.org/D18912

llvm-svn: 265948
This commit is contained in:
Adrian McCarthy 2016-04-11 15:21:01 +00:00
parent a45d3e439f
commit 121571b7ce
1 changed files with 15 additions and 12 deletions

View File

@ -1049,23 +1049,13 @@ class Base(unittest2.TestCase):
# it silently replaces the destination. Ultimately this means that atomic renames are not
# guaranteed to be possible on Windows, but we need this to work anyway, so just remove the
# destination first if it already exists.
os.remove(dst)
remove_file(dst)
os.rename(src, dst)
else:
# success! (and we don't want log files) delete log files
for log_file in log_files_for_this_test:
try:
os.unlink(log_file)
except:
# We've seen consistent unlink failures on Windows, perhaps because the
# just-created log file is being scanned by anti-virus. Empirically, this
# sleep-and-retry approach allows tests to succeed much more reliably.
# Attempts to figure out exactly what process was still holding a file handle
# have failed because running instrumentation like Process Monitor seems to
# slow things down enough that the problem becomes much less consistent.
time.sleep(0.5)
os.unlink(log_file)
remove_file(log_file)
# ====================================================
# Config. methods supported through a plugin interface
@ -1996,4 +1986,17 @@ class TestBase(Base):
@classmethod
def RemoveTempFile(cls, file):
if os.path.exists(file):
remove_file(file)
# On Windows, the first attempt to delete a recently-touched file can fail
# because of a race with antimalware scanners. This function will detect a
# failure and retry.
def remove_file(file, num_retries = 1, sleep_duration = 0.5):
for i in range(num_retries+1):
try:
os.remove(file)
return True
except:
time.sleep(sleep_duration)
continue
return False