[Top][All Lists]

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

Re: AC_PROG_MKDIR_P documentation

From: Paul Eggert
Subject: Re: AC_PROG_MKDIR_P documentation
Date: Fri, 26 May 2006 19:56:16 -0700
User-agent: Gnus/5.1008 (Gnus v5.10.8) Emacs/21.4 (gnu/linux)

Stepan Kasal <address@hidden> writes:

> Well, I have probably missed something.

No, you're pretty much on target.  Thanks.  I installed this:

2006-05-26  Paul Eggert  <address@hidden>

        * doc/autoconf.texi (Particular Programs, Limitations of Usual Tools):
        Use better wording to talk about AC_PROG_MKDIR_P's thread-safety.
        Don't use the term "thread-safe" to talk about mkdir race
        conditions, since the problem is more a process than a thread
        issue.  Problem reported by Stepan Kasal in:
        * lib/autoconf/programs.m4 (AC_PROG_MKDIR_P): Use code that mimics
        the test for 'install' more closely.  Look at MKDIR_P first.
        Look in the PATH, and at /opt/sfw/bin.
        Look for a 'gmkdir' program as well (Solaris 10 /opt/sfw/bin/gmkdir).
        Don't bother to try mkdir -p, since we already check mkdir --version;
        just look at the version number.  (There's no easy way to check
        for race-free implementations.)
        * tests/ (autoconf: subdirectories): Adjust to above
        changes, since MKDIR_P now might end in "/mkdir -p".

--- doc/autoconf.texi   27 May 2006 00:05:36 -0000      1.1027
+++ doc/autoconf.texi   27 May 2006 02:47:53 -0000
@@ -3526,15 +3526,17 @@ not found in standard @command{install} 
 @ovindex MKDIR_P
 Set output variable @code{MKDIR_P} to a program that ensures that for
 each argument, a directory named by this argument exists, creating it
-and its parent directories if needed.  The program is checked to make
-sure that it is thread-safe (@pxref{Limitations of Usual Tools}).
+and its parent directories if needed, and without race conditions when
+two instances of the program attempt to make the same directory at
+nearly the same time.
 This macro uses the @samp{mkdir -p} command if possible.  Otherwise, it
 falls back on invoking @command{install-sh} with the @option{-d} option,
 so your package should
 contain @file{install-sh} as described under @code{AC_PROG_INSTALL}.
 A @file{install-sh} file that predates Autoconf 2.60 or Automake 1.10
-won't be thread-safe, so if you want to support parallel installs from
+is vulnerable to race conditions, so if you want to support parallel
+installs from
 different packages into the same directory you need to make sure you
 have an up-to-date @file{install-sh}.  In particular, be careful about
 using @samp{autoreconf -if} if your Automake predates Automake 1.10.
@@ -3543,9 +3545,10 @@ This macro is related to the @code{AS_MK
 in M4sh}), but it sets an output variable intended for use in other
 files, whereas @code{AS_MKDIR_P} is intended for use in scripts like
 @command{configure}.  Also, @code{AS_MKDIR_P} does not accept options,
-but if you are willing to assume Posix 1003.2-1992 or later, a
address@hidden can use the @option{-m} option, e.g., a makefile might
+but @code{MKDIR_P} can use the @option{-m} option, e.g., a makefile might
 invoke @code{$(MKDIR_P) -m 0 dir} to create an inaccessible directory.
+Finally, @code{AS_MKDIR_P} does not check for race condition
+vulnerability, whereas @code{AC_PROG_MKDIR_P} does.
 @end defmac
 @defmac AC_PROG_LEX
@@ -13155,21 +13158,22 @@ should succeed when @file{foo} is a symb
 directory.  The @acronym{GNU} Core Utilities 5.1.0 @command{mkdir}
 succeeds, but Solaris @command{mkdir} fails.
-Not all @code{mkdir -p} implementations are thread-safe.  When it is not
-and you call @code{mkdir -p a/b} and @code{mkdir -p a/c} at the same
-time, both will detect that @file{a/} is missing, one will create
address@hidden/}, then the other will try to create @file{a/} and die with a
address@hidden exists} error.  At least Solaris 10, address@hidden 1.6, and 
-3.4 have an unsafe @code{mkdir -p}.  The @acronym{GNU} Core Utilities
+Traditional @code{mkdir -p} implementations suffer from race conditions.
+For example, if you invoke @code{mkdir -p a/b} and @code{mkdir -p a/c}
+at the same time, both processes might detect that @file{a} is missing,
+one might create @file{a}, then the other might try to create @file{a}
+and fail with a @code{File exists} diagnostic.  At least Solaris 10,
address@hidden 1.6, and address@hidden 3.4 are vulnerable to race
+conditions.  The @acronym{GNU} Core Utilities
 (since @samp{fileutils}
-version 4.0c), address@hidden 5.0, and address@hidden are
+version 4.1), address@hidden 5.0, and address@hidden are
 known to have a
 race-free @code{mkdir -p}.  This possible race is harmful in parallel
 builds when several @file{Makefile} rules call @code{mkdir -p} to
 construct directories.  You may use
 @code{install-sh -d} as a safe replacement, provided this script is
 recent enough; the copy shipped with Autoconf 2.60 and Automake 1.10 is
-OK, but copies from older versions are not thread-safe either.
+OK, but copies from older versions are vulnerable.
 @item @command{mktemp}
--- lib/autoconf/programs.m4    26 May 2006 22:29:50 -0000      1.57
+++ lib/autoconf/programs.m4    27 May 2006 02:47:53 -0000
@@ -627,7 +627,7 @@ AC_SUBST(INSTALL_DATA)dnl
 # concurrently, both version can detect that a/ is missing, but only
 # one can create it and the other will error out.  Consequently we
 # restrict ourselves to GNU mkdir (using the --version option ensures
-# this.)
+# this).
 # Automake used to define mkdir_p as `mkdir -p .', in order to
 # allow $(mkdir_p) to be used without argument.  As in
@@ -657,14 +657,31 @@ AC_DEFUN([AC_PROG_MKDIR_P],
 AC_MSG_CHECKING([for a thread-safe mkdir -p])
-if mkdir -p --version . >/dev/null 2>&1 && test ! -d ./--version; then
-  MKDIR_P='mkdir -p'
-  for ac_d in ./-p ./--version
-  do
-    test -d $ac_d && rmdir $ac_d
-  done
-  MKDIR_P="$ac_install_sh -d"
+if test -z "$MKDIR_P"; then
+  AC_CACHE_VAL([ac_cv_path_mkdir],
+    [_AS_PATH_WALK([$PATH$PATH_SEPARATOR/opt/sfw/bin],
+      [for ac_prog in mkdir gmkdir; do
+        for ac_exec_ext in '' $ac_executable_extensions; do
+          AS_EXECUTABLE_P(["$as_dir/$ac_prog$ac_exec_ext"]) || continue
+          case `"$as_dir/$ac_prog$ac_exec_ext" --version 2>&1` in #(
+            'mkdir (GNU coreutils) '* | \
+            'mkdir (coreutils) '* | \
+            'mkdir (fileutils) '4.1*)
+              ac_cv_path_mkdir=$as_dir/$ac_prog$ac_exec_ext
+              break 3;;
+          esac
+        done
+       done])])
+  if test "${ac_cv_path_mkdir+set}" = set; then
+    MKDIR_P="$ac_cv_path_mkdir -p"
+  else
+    # As a last resort, use the slow shell script.  Don't cache a
+    # value for MKDIR_P within a source directory, because that will
+    # break other packages using the cache if that directory is
+    # removed, or if the value is a relative name.
+    test -d ./--version && rmdir ./--version
+    MKDIR_P="$ac_install_sh -d"
+  fi
 dnl Do special magic for MKDIR_P instead of AC_SUBST, to get
 dnl relative names right.
Index: tests/
RCS file: /cvsroot/autoconf/autoconf/tests/,v
retrieving revision 1.85
diff -p -u -r1.85
--- tests/      22 May 2006 15:54:09 -0000      1.85
+++ tests/      27 May 2006 02:47:53 -0000
@@ -347,7 +347,7 @@ AT_DATA([install-sh])
-AT_CHECK([grep '/mkdir -p' sub/foo], 1)
+AT_CHECK([[grep '^[^/].*/mkdir -p' sub/foo]], 1)

reply via email to

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