From aa4a2459e603646a86ab09bdf7ea669a0664cc65 Mon Sep 17 00:00:00 2001 From: Paul Eggert Date: Sat, 27 May 2006 02:54:33 +0000 Subject: [PATCH] * 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: http://lists.gnu.org/archive/html/autoconf-patches/2006-05/msg00088.html * 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/tools.at (autoconf: subdirectories): Adjust to above changes, since MKDIR_P now might end in "/mkdir -p". --- ChangeLog | 16 ++++++++++++++++ doc/autoconf.texi | 30 +++++++++++++++++------------- lib/autoconf/programs.m4 | 35 ++++++++++++++++++++++++++--------- tests/tools.at | 2 +- 4 files changed, 60 insertions(+), 23 deletions(-) diff --git a/ChangeLog b/ChangeLog index faa80919..8fa10243 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,21 @@ 2006-05-26 Paul Eggert + * 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: + http://lists.gnu.org/archive/html/autoconf-patches/2006-05/msg00088.html + * 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/tools.at (autoconf: subdirectories): Adjust to above + changes, since MKDIR_P now might end in "/mkdir -p". + * doc/autoconf.texi (autoheader Invocation): Mention that the first arg of AC_DEFINE_UNQUOTED must not be a literal. Problem reported by Ben Pfaff in diff --git a/doc/autoconf.texi b/doc/autoconf.texi index 4da7c3f9..f928cc5a 100644 --- a/doc/autoconf.texi +++ b/doc/autoconf.texi @@ -3526,15 +3526,17 @@ not found in standard @command{install} programs, there is no reason to use @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_MKDIR_P} macro (@pxref{Programming 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 -@code{MKDIR_P} 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 symbolic link to an already-existing 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 -@file{a/}, then the other will try to create @file{a/} and die with a -@code{File exists} error. At least Solaris 10, Net@acronym{BSD} 1.6, and Open@acronym{BSD} -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, +Net@acronym{BSD} 1.6, and Open@acronym{BSD} 3.4 are vulnerable to race +conditions. The @acronym{GNU} Core Utilities (since @samp{fileutils} -version 4.0c), Free@acronym{BSD} 5.0, and Net@acronym{BSD}-current are +version 4.1), Free@acronym{BSD} 5.0, and Net@acronym{BSD}-current 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} diff --git a/lib/autoconf/programs.m4 b/lib/autoconf/programs.m4 index 98b1dafb..f796d2f8 100644 --- a/lib/autoconf/programs.m4 +++ b/lib/autoconf/programs.m4 @@ -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_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT])dnl AC_REQUIRE_AUX_FILE([install-sh])dnl 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' -else - 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 fi dnl Do special magic for MKDIR_P instead of AC_SUBST, to get dnl relative names right. diff --git a/tests/tools.at b/tests/tools.at index be6f3b68..c4a141be 100644 --- a/tests/tools.at +++ b/tests/tools.at @@ -347,7 +347,7 @@ AT_DATA([install-sh]) AT_CHECK_AUTOCONF AT_CHECK_CONFIGURE -AT_CHECK([grep '/mkdir -p' sub/foo], 1) +AT_CHECK([[grep '^[^/].*/mkdir -p' sub/foo]], 1) AT_CLEANUP -- 2.11.4.GIT