[Cmake-commits] CMake branch, next, updated. v2.8.10.2-1901-g3c378f2

Brad King brad.king at kitware.com
Mon Feb 4 15:16:32 EST 2013


This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "CMake".

The branch, next has been updated
       via  3c378f2f164195d51bdc9e99cf21d63bb89af314 (commit)
       via  59b568e5e8e294345c10789e1b3488391d5cd6f3 (commit)
      from  3fc1c0c005fbafc2d7858b542a1f91ea270ea661 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
http://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=3c378f2f164195d51bdc9e99cf21d63bb89af314
commit 3c378f2f164195d51bdc9e99cf21d63bb89af314
Merge: 3fc1c0c 59b568e
Author:     Brad King <brad.king at kitware.com>
AuthorDate: Mon Feb 4 15:16:30 2013 -0500
Commit:     CMake Topic Stage <kwrobot at kitware.com>
CommitDate: Mon Feb 4 15:16:30 2013 -0500

    Merge topic 'fix-atomic-rename-on-Windows' into next
    
    59b568e Fix cmSystemTools::RenameFile race on Windows


http://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=59b568e5e8e294345c10789e1b3488391d5cd6f3
commit 59b568e5e8e294345c10789e1b3488391d5cd6f3
Author:     Brad King <brad.king at kitware.com>
AuthorDate: Thu Jan 31 11:42:17 2013 -0500
Commit:     Brad King <brad.king at kitware.com>
CommitDate: Mon Feb 4 15:15:21 2013 -0500

    Fix cmSystemTools::RenameFile race on Windows
    
    Since commit d46d8df0 (Re-implemented cmGeneratedFileStream to look like a
    real stream and replace the destination file atomically, 2004-11-03) our
    RenameFile implementation tries to deal with MoveFile not replacing
    read-only files.  In order to avoid the Get/SetFileAttributes pair we used
    stat to test for existence of the destination file.  This has a race in
    which the destination could be created between the test for existence and
    the MoveFile call.
    
    Remove the stat call and use GetFileAttributes to detect whether the file
    exists.  This shortens the race but does not eliminate it.  Use a loop to
    try multiple times in case we lose the race.  While at it, drop Win9x
    support and always use MoveFileEx.

diff --git a/Source/cmSystemTools.cxx b/Source/cmSystemTools.cxx
index c2521d9..525efb4 100644
--- a/Source/cmSystemTools.cxx
+++ b/Source/cmSystemTools.cxx
@@ -1180,46 +1180,35 @@ bool cmSystemTools::CopyFileIfDifferent(const char* source,
 bool cmSystemTools::RenameFile(const char* oldname, const char* newname)
 {
 #ifdef _WIN32
-  /* On Windows the move functions will not replace existing files.
-     Check if the destination exists.  */
-  struct stat newFile;
-  if(stat(newname, &newFile) == 0)
+# ifndef INVALID_FILE_ATTRIBUTES
+#  define INVALID_FILE_ATTRIBUTES ((DWORD)-1)
+# endif
+  /* Windows MoveFileEx may not replace read-only or in-use files.  If it
+     fails then remove the read-only attribute from any existing destination.
+     Try multiple times since we may be racing against another process
+     creating/opening the destination file just before our MoveFileEx.  */
+  int tries = 5;
+  while(!MoveFileEx(oldname, newname, MOVEFILE_REPLACE_EXISTING) && --tries)
     {
-    /* The destination exists.  We have to replace it carefully.  The
-       MoveFileEx function does what we need but is not available on
-       Win9x.  */
-    OSVERSIONINFO osv;
-    DWORD attrs;
-
-    /* Make sure the destination is not read only.  */
-    attrs = GetFileAttributes(newname);
-    if(attrs & FILE_ATTRIBUTE_READONLY)
+    // Try again only if failure was due to access permissions.
+    if(GetLastError() != ERROR_ACCESS_DENIED)
       {
-      SetFileAttributes(newname, attrs & ~FILE_ATTRIBUTE_READONLY);
+      return false;
       }
-
-    /* Check the windows version number.  */
-    osv.dwOSVersionInfoSize = sizeof(osv);
-    GetVersionEx(&osv);
-    if(osv.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS)
+    DWORD attrs = GetFileAttributes(newname);
+    if((attrs != INVALID_FILE_ATTRIBUTES) &&
+       (attrs & FILE_ATTRIBUTE_READONLY))
       {
-      /* This is Win9x.  There is no MoveFileEx implementation.  We
-         cannot quite rename the file atomically.  Just delete the
-         destination and then move the file.  */
-      DeleteFile(newname);
-      return MoveFile(oldname, newname) != 0;
+      // Remove the read-only attribute from the destination file.
+      SetFileAttributes(newname, attrs & ~FILE_ATTRIBUTE_READONLY);
       }
     else
       {
-      /* This is not Win9x.  Use the MoveFileEx implementation.  */
-      return MoveFileEx(oldname, newname, MOVEFILE_REPLACE_EXISTING) != 0;
+      // The file may be temporarily in use so wait a bit.
+      cmSystemTools::Delay(100);
       }
     }
-  else
-    {
-    /* The destination does not exist.  Just move the file.  */
-    return MoveFile(oldname, newname) != 0;
-    }
+  return tries > 0;
 #else
   /* On UNIX we have an OS-provided call to do this atomically.  */
   return rename(oldname, newname) == 0;

-----------------------------------------------------------------------

Summary of changes:


hooks/post-receive
-- 
CMake


More information about the Cmake-commits mailing list