lit/TestRunner.py: [Win32] Introduce WinWaitReleased(f), to wait for file handles...
authorNAKAMURA Takumi <geek4civic@gmail.com>
Mon, 28 Nov 2011 01:55:01 +0000 (01:55 +0000)
committerNAKAMURA Takumi <geek4civic@gmail.com>
Mon, 28 Nov 2011 01:55:01 +0000 (01:55 +0000)
When wait() has finished, opened handles (especially writing stdout to file) might not be released immediately.
To wait for released, poll to attempt renaming.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@145222 91177308-0d34-0410-b5e6-96231b3b80d8

utils/lit/lit/TestRunner.py

index f5f7c19891b32f4033f850e0dff043b89ddd7f7e..b450c33df622304b8e1bb936912336e1bacac545 100644 (file)
@@ -23,6 +23,41 @@ kUseCloseFDs = not kIsWindows
 # Use temporary files to replace /dev/null on Windows.
 kAvoidDevNull = kIsWindows
 
+def RemoveForce(f):
+    try:
+        os.remove(f)
+    except OSError:
+        pass
+
+def WinRename(f_o, f_n):
+    import time
+    retry_cnt = 256
+    while (True):
+        try:
+            os.rename(f_o, f_n)
+            break
+        except WindowsError, (winerror, strerror):
+            retry_cnt = retry_cnt - 1
+            if retry_cnt <= 0:
+                raise
+            elif winerror == 32: # ERROR_SHARING_VIOLATION
+                time.sleep(0.01)
+            else:
+                raise
+
+def WinWaitReleased(f):
+    import random
+    t = "%s%06d" % (f, random.randint(0, 999999))
+    RemoveForce(t)
+    try:
+        WinRename(f, t) # rename
+        WinRename(t, f) # restore
+    except WindowsError, (winerror, strerror):
+        if winerror == 3: # ERROR_PATH_NOT_FOUND
+            pass
+        else:
+            raise
+
 def executeCommand(command, cwd=None, env=None):
     p = subprocess.Popen(command, cwd=cwd,
                          stdin=subprocess.PIPE,
@@ -68,6 +103,7 @@ def executeShCmd(cmd, cfg, cwd, results):
     input = subprocess.PIPE
     stderrTempFiles = []
     opened_files = []
+    written_files = []
     named_temp_files = []
     # To avoid deadlock, we use a single stderr stream for piped
     # output. This is null until we have seen some output using
@@ -124,6 +160,8 @@ def executeShCmd(cmd, cfg, cwd, results):
                     if r[1] == 'a':
                         r[2].seek(0, 2)
                     opened_files.append(r[2])
+                    if r[1] in 'aw':
+                        written_files.append(r[0])
                 result = r[2]
             final_redirects.append(result)
 
@@ -224,6 +262,11 @@ def executeShCmd(cmd, cfg, cwd, results):
         else:
             exitCode = res
 
+    # Make sure written_files is released by other (child) processes.
+    if (kIsWindows):
+        for f in written_files:
+            WinWaitReleased(f)
+
     # Remove any named temporary files we created.
     for f in named_temp_files:
         try: