autoconf-patches
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Try to update config.cache atomically; respect symlinks.


From: Ralf Wildenhues
Subject: Try to update config.cache atomically; respect symlinks.
Date: Sat, 14 Aug 2010 08:32:30 +0200
User-agent: Mutt/1.5.20 (2010-04-22)

This patch fixes a long-standing issue GCC has with Autoconf: cache
files are not updated atomically.  (This was IIUC the primary reason
GCC introduced per-configure cache files.)

Anyway.  The double mv to target directory aims to provide atomicity
even when moving between mount points.  To hopefully prevent portability
issues on systems with file name limitations, I prepended $$ not .$$ to
the temporary name.  Since it might be cut off at 8.3, it may not be
unique any more, but luckily concurrency isn't such an issue on DJGPP.
;-)

There's a small chance of a leftover file in the directory where the
cache file resides, when a signal arrives at the right time.  Not sure
if that's worth changing the exit trap, that wasn't done for the
'confcache' file either; but of course, the latter would be cleaned up
after another configure run.  OTOH, the exit trap could then open up a
symlink attack upon '--cache-file=/tmp/config.cache'.

Further, 'info Autoconf --index mv' describes that there may be a
warning when moving from /tmp (e.g., build in /tmp, cache file in
$HOME); oh well.

I added the 'test ! -f' to the 'test -h' just in case somebody manages
to use a fifo or socket as cache file.

No testsuite addition for the atomic semantics.  I have no idea how to
devise such a test, nor how to reliably (and safely! see /tmp discussion
above) select a usable destination on another mount point.

Thanks,
Ralf

    Try to update config.cache atomically; respect symlinks.
    
    * lib/autoconf/general.m4 (AC_CACHE_SAVE): Use `mv -f' to update
    the cache file if it is a regular file and not a symlink.  Move
    first to temporary name in the target directory if not in the
    current directory for atomicity across mount points.
    * tests/base.at (AC_CACHE_CHECK): Try symlinked cache file.
    * NEWS: Update.

diff --git a/NEWS b/NEWS
index b017a43..5264db9 100644
--- a/NEWS
+++ b/NEWS
@@ -8,6 +8,11 @@ GNU Autoconf NEWS - User visible changes.
 ** Autotest testsuites should not contain long text lines any more, and be
    portable even when very many test groups are used.
 
+** Symlinked config.cache files are supported; configure now tries to
+   update non-symlinked cache files atomically, so that concurrent configure
+   runs do not leave behind broken cache files.  It is still unspecified
+   which subset or union of results is cached though.
+
 
 * Major changes in Autoconf 2.67 (2010-07-21) [stable]
   Released by Eric Blake, based on git versions 2.66.*.
diff --git a/lib/autoconf/general.m4 b/lib/autoconf/general.m4
index 8e9c8cf..49ca5ca 100644
--- a/lib/autoconf/general.m4
+++ b/lib/autoconf/general.m4
@@ -2001,9 +2001,22 @@ _AC_CACHE_DUMP() |
      :end'] >>confcache
 if diff "$cache_file" confcache >/dev/null 2>&1; then :; else
   if test -w "$cache_file"; then
-    test "x$cache_file" != "x/dev/null" &&
+    if test "x$cache_file" != "x/dev/null"; then
       AC_MSG_NOTICE([updating cache $cache_file])
-    cat confcache >$cache_file
+      if test ! -f "$cache_file" || test -h "$cache_file"; then
+       cat confcache >"$cache_file"
+      else
+dnl Try to update the cache file atomically even on different mount points;
+dnl at the same time, avoid filename limitation issues in the common case.
+        case $cache_file in #(
+        */* | ?:*)
+         mv -f confcache "$cache_file"$$ &&
+         mv -f "$cache_file"$$ "$cache_file" ;; #(
+        *)
+         mv -f confcache "$cache_file" ;;
+       esac
+      fi
+    fi
   else
     AC_MSG_NOTICE([not updating unwritable cache $cache_file])
   fi
diff --git a/tests/base.at b/tests/base.at
index 3733c65..240986a 100644
--- a/tests/base.at
+++ b/tests/base.at
@@ -454,6 +454,13 @@ AT_CHECK_CONFIGURE([], [], [stdout])
 AT_CHECK([grep cache stdout], [1])
 AT_CHECK([LC_ALL=C ls -t config.cache a-stamp-file | sed 1q | grep 
config.cache], [1])
 
+# Using a symlinked cache file works.
+: > cache
+rm -f config.cache
+AS_LN_S([cache], [config.cache])
+AT_CHECK_CONFIGURE([-C])
+AT_CHECK([test -s cache || test ! -h config.cache])
+
 # config.site can specify a site-wide cache, accumulating information.
 # Also test that we don't run afoul of sourcing a file with leading -.
 AT_DATA([-config.site],



reply via email to

[Prev in Thread] Current Thread [Next in Thread]