diff options
author | Gary V. Vaughan <gary@gnu.org> | 2004-09-16 14:57:02 +0000 |
---|---|---|
committer | Gary V. Vaughan <gary@gnu.org> | 2004-09-16 14:57:02 +0000 |
commit | 0e0104aa456bd86f59f15afbeff12699a35d8110 (patch) | |
tree | c2d23a3d55659caa40d61531bf3f3629b9c1a0fb | |
parent | 7955f590bb4ad0f8990cf33e6ad08baca1c66e88 (diff) | |
download | libtool-0e0104aa456bd86f59f15afbeff12699a35d8110.tar.gz |
My most recent `2004-09-02 Gary V. Vaughan' patch for mkdir_p
below is horrendously broken since it makes the installed libtool
try to run the mkinstalldirs or install-sh helper scripts. This
patch fixes the `make -j' mkdir race condition internally:
* libtoolize.in (func_mkdir_p): New slice and dice algorithm
to build the directory tree one dir at a time, ignoring errors
until the end incase they are transient due to a concurrent
identical mkdir.
* tests/defs (func_mkdir_p): Ditto.
* config/ltmain.in (func_mkdir_p): Ditto, except that ltmain.in
uses $echo rather than $ECHO, and uses $show and $run to interact
correctly with the command line.
* configure.ac (AM_INIT_AUTOMAKE): 1.8 is sufficient again.
* Makefile.am (edit): Don't substitute automake's $(mkdir_p).
* NEWS: Updated.
-rw-r--r-- | ChangeLog | 19 | ||||
-rw-r--r-- | Makefile.am | 1 | ||||
-rw-r--r-- | NEWS | 5 | ||||
-rw-r--r-- | config/ltmain.in | 58 | ||||
-rw-r--r-- | configure.ac | 2 | ||||
-rw-r--r-- | libtoolize.in | 91 | ||||
-rw-r--r-- | tests/defs | 51 |
7 files changed, 158 insertions, 69 deletions
@@ -1,3 +1,22 @@ +2004-09-16 Gary V. Vaughan <gary@gnu.org> + + My most recent `2004-09-02 Gary V. Vaughan' patch for mkdir_p + below is horrendously broken since it makes the installed libtool + try to run the mkinstalldirs or install-sh helper scripts. This + patch fixes the `make -j' mkdir race condition internally: + + * libtoolize.in (func_mkdir_p): New slice and dice algorithm + to build the directory tree one dir at a time, ignoring errors + until the end incase they are transient due to a concurrent + identical mkdir. + * tests/defs (func_mkdir_p): Ditto. + * config/ltmain.in (func_mkdir_p): Ditto, except that ltmain.in + uses $echo rather than $ECHO, and uses $show and $run to interact + correctly with the command line. + * configure.ac (AM_INIT_AUTOMAKE): 1.8 is sufficient again. + * Makefile.am (edit): Don't substitute automake's $(mkdir_p). + * NEWS: Updated. + 2004-09-15 Bob Friesenhahn <bfriesen@simple.dallas.tx.us> * libltdl/loaders/loadlibrary.c: Compilation fixes (originally diff --git a/Makefile.am b/Makefile.am index b911b2bc..37f6e8f4 100644 --- a/Makefile.am +++ b/Makefile.am @@ -30,7 +30,6 @@ edit = sed \ -e 's,@pkgdatadir\@,$(pkgdatadir),g' \ -e 's,@aclocaldir\@,$(aclocaldir),g' \ -e 's,@host_triplet\@,$(host_triplet),g' \ - -e 's,@mkdir_p\@,$(mkdir_p),g' \ -e "s,@configure_input\@,Generated from $$input; do not edit by hand,g" timestamp = set -- `$(MKSTAMP) < $(top_srcdir)/ChangeLog`; \ @@ -6,9 +6,8 @@ New in 1.9d: 2004-??-??; CVS version 1.9c, Libtool team: back to pic objects. * When compiling C glue code with $LTCC, libtool now saves the setting of $compiler_flags from the C tag, and passes those flags to $LTCC. -* libtool uses automake's $(mkdir_p), and can support `make -j' on - multi-processor hosts if automake discovered a multithreadable mkdir. If - it still doesn't work for you, install GNU mkdir (in GNU coreutils). +* libtool no longer dies when concurrently creating directories with + `make -j' on multi-processor hosts. * Return type, and name parameter of lt_dlloader_remove are no longer `const'. * Name parameter of lt_dlloader_find is no longer 'const'. diff --git a/config/ltmain.in b/config/ltmain.in index 08fac5ea..135710d5 100644 --- a/config/ltmain.in +++ b/config/ltmain.in @@ -86,7 +86,7 @@ DUALCASE=1; export DUALCASE # for MKS sh (unset CDPATH) >/dev/null 2>&1 && unset CDPATH -: ${MKDIR_P="@mkdir_p@"} +: ${MKDIR="mkdir"} : ${RM="rm -f"} : ${MV="mv -f"} @@ -157,7 +157,7 @@ magic="%%%MAGIC variable%%%" Xsed="${SED}"' -e 1s/^X//' sed_quote_subst='s/\([\\`\\"$\\\\]\)/\\\1/g' # test EBCDIC or ASCII -case `echo A|tr A '\301'` in +case `$echo A|tr A '\301'` in A) # EBCDIC based system SP2NL="tr '\100' '\n'" NL2SP="tr '\r\n' '\100\100'" @@ -715,27 +715,47 @@ Otherwise, only FILE itself is deleted using RM." # func_mkdir_p directory-path -# Use automake's best guess at a multithreadable mkdir command to create -# DIRECTORY-PATH in a way that shouldn't interfere with `make -j'. -func_mkdir_p () { +# Make sure the entire path to DIRECTORY-PATH is available. +func_mkdir_p () +{ my_directory_path="$1" - my_status= + my_dir_list= - test -f "$my_directory_path" && { - $show "${RM}r $my_directory_path" - $run ${RM}r "$my_directory_path" - } + if test -n "$my_directory_path"; then - $show "$MKDIR_P $my_directory_path" - test -n "$my_directory_path" && { - $run $MKDIR_P "$my_directory_path" - my_status=$? + # Protect directory names starting with `-' + case $my_directory_path in + -*) my_directory_path="./$my_directory_path" ;; + esac - # Bail out if $MKDIR_P failed to create a directory. - test "$my_status" -ne $EXIT_SUCCESS && \ - test ! -d "$my_directory_path" && \ - exit $my_status - } + # While some portion of DIR does not yet exist... + while test ! -d "$my_directory_path"; do + # ...make a list in topmost first order. Use a colon delimited + # list incase some portion of path contains whitespace. + my_dir_list="$my_directory_path:$my_dir_list" + + # If the last portion added has no slash in it, the list is done + case $my_directory_path in */*) ;; *) break ;; esac + + # ...otherwise throw away the child directory and loop + my_directory_path=`$echo "$my_directory_path" | $SED "$dirname"` + done + my_dir_list=`$echo $my_dir_list | $SED 's,:*$,,'` + + save_mkdir_p_IFS="$IFS"; IFS=':' + for my_dir in $my_dir_list; do + IFS="$save_mkdir_p_IFS" + # mkdir can fail with a `File exist' error if two processes + # try to create one of the directories concurrently. Don't + # stop in that case! + $MKDIR "$my_dir" 2>/dev/null || : + done + IFS="$save_mkdir_p_IFS" + fi + + # Bail out if we (or some other process) failed to create a directory. + test -d "$my_directory_path" || \ + func_fatal_error "Failed to create \`$1'" } diff --git a/configure.ac b/configure.ac index a52de30c..0e13cd99 100644 --- a/configure.ac +++ b/configure.ac @@ -112,7 +112,7 @@ AC_SUBST([package_revision]) dnl These are bootstrap requirements, once built, libtool may work with dnl much older releases of autoconf and automake. See release notes. -AM_INIT_AUTOMAKE([1.9 gnits dist-bzip2]) ## We use parallel $(mkdir_p) +AM_INIT_AUTOMAKE([1.8 gnits dist-bzip2]) ## We use auto-m4_including dnl Make sure config.status is regenerated when the version timestamp changes AC_SUBST([CONFIG_STATUS_DEPENDENCIES], ['$(top_builddir)/stamp-vcl']) diff --git a/libtoolize.in b/libtoolize.in index 0c1cdef8..9087bd3b 100644 --- a/libtoolize.in +++ b/libtoolize.in @@ -75,8 +75,9 @@ DUALCASE=1; export DUALCASE # for MKS sh (unset CDPATH) >/dev/null 2>&1 && unset CDPATH : ${CP="cp -f"} +: ${ECHO="echo"} : ${LN_S="@LN_S@"} -: ${MKDIR_P="@mkdir_p@"} +: ${MKDIR="mkdir"} : ${RM="rm -f"} : ${SED="@SED@"} @@ -91,13 +92,13 @@ basename="s,^.*/,,g" progpath="$0" # The name of this program: -progname=`echo "$progpath" | $SED "$basename"` +progname=`$ECHO "$progpath" | $SED "$basename"` PROGRAM=libtoolize # Make sure we have an absolute path for reexecution: case $progpath in [\\/]*|[A-Za-z]:\\*) ;; - *) progdir=`echo "$progpath" | $SED "$dirname"` + *) progdir=`$ECHO "$progpath" | $SED "$dirname"` progdir=`cd "$progdir" && pwd` progpath="$progdir/$progname" ;; @@ -137,7 +138,7 @@ configure_ac=configure.in # Echo program name prefixed message. func_echo () { - echo $progname: ${1+"$@"} + $ECHO $progname: ${1+"$@"} } # func_verbose arg... @@ -151,7 +152,7 @@ func_verbose () # Echo program name prefixed message to standard error. func_error () { - echo $progname: ${1+"$@"} 1>&2 + $ECHO $progname: ${1+"$@"} 1>&2 } # func_fatal_error arg... @@ -189,8 +190,8 @@ func_usage () s/\$progname/'$progname'/; p; }; d' < "$progpath" - echo - echo "run \`$progname --help | more' for full usage" + $ECHO + $ECHO "run \`$progname --help | more' for full usage" exit $EXIT_SUCCESS } @@ -248,10 +249,10 @@ func_version () --dry-run|-n) if $opt_dry_run; then :; else opt_dry_run=: - RM="echo $RM" - test -n "$LN_S" && LN_S="echo $LN_S" - CP="echo $CP" - MKDIR_P="echo $MKDIR_P" + RM="$ECHO $RM" + test -n "$LN_S" && LN_S="$ECHO $LN_S" + CP="$ECHO $CP" + MKDIR="$ECHO $MKDIR" fi libtoolize_flags="${libtoolize_flags} --dry-run" ;; @@ -284,15 +285,15 @@ func_version () # Separate optargs to long options: --ltdl=*) - arg=`echo "$opt" | $SED "$my_sed_long_arg"` - opt=`echo "$opt" | $SED "$my_sed_long_opt"` + arg=`$ECHO "$opt" | $SED "$my_sed_long_arg"` + opt=`$ECHO "$opt" | $SED "$my_sed_long_opt"` set -- "$opt" "$arg" ${1+"$@"} ;; # Separate non-argument short options: -c*|-i*|-f*|-n*|-q*|-v*) - rest=`echo "$opt" |$SED "$my_sed_single_rest"` - opt=`echo "$opt" |$SED "$my_sed_single_opt"` + rest=`$ECHO "$opt" |$SED "$my_sed_single_rest"` + opt=`$ECHO "$opt" |$SED "$my_sed_single_opt"` set -- "$opt" "-$rest" ${1+"$@"} ;; @@ -308,25 +309,47 @@ func_version () # func_mkdir_p directory-path -# Use automake's best guess at a multithreadable mkdir command to create -# DIRECTORY-PATH in a way that shouldn't interfere with `make -j'. -func_mkdir_p () { +# Make sure the entire path to DIRECTORY-PATH is available. +func_mkdir_p () +{ my_directory_path="$1" - my_status= + my_dir_list= if test -n "$my_directory_path"; then - test -f "$my_directory_path" && { - ${RM}r "$my_directory_path" - } - $MKDIR_P "$my_directory_path" - my_status=$? + # Protect directory names starting with `-' + case $my_directory_path in + -*) my_directory_path="./$my_directory_path" ;; + esac + + # While some portion of DIR does not yet exist... + while test ! -d "$my_directory_path"; do + # ...make a list in topmost first order. Use a colon delimited + # list incase some portion of path contains whitespace. + my_dir_list="$my_directory_path:$my_dir_list" - # Bail out if $MKDIR_P failed to create a directory. - test "$my_status" -ne $EXIT_SUCCESS && \ - test ! -d "$my_directory_path" && \ - exit $my_status + # If the last portion added has no slash in it, the list is done + case $my_directory_path in */*) ;; *) break ;; esac + + # ...otherwise throw away the child directory and loop + my_directory_path=`$ECHO "$my_directory_path" | $SED "$dirname"` + done + my_dir_list=`$ECHO $my_dir_list | $SED 's,:*$,,'` + + save_mkdir_p_IFS="$IFS"; IFS=':' + for my_dir in $my_dir_list; do + IFS="$save_mkdir_p_IFS" + # mkdir can fail with a `File exist' error if two processes + # try to create one of the directories concurrently. Don't + # stop in that case! + $MKDIR "$my_dir" 2>/dev/null || : + done + IFS="$save_mkdir_p_IFS" fi + + # Bail out if we (or some other process) failed to create a directory. + test -d "$my_directory_path" || \ + func_fatal_error "Failed to create \`$1'" } @@ -339,7 +362,7 @@ func_copy () my_destfile="$2" my_return_status=1 - func_mkdir_p `echo "$my_destfile" | $SED "$dirname"` + func_mkdir_p `$ECHO "$my_destfile" | $SED "$dirname"` $RM "$my_destfile" if $opt_link && $LN_S "$my_srcfile" "$my_destfile"; then @@ -385,8 +408,8 @@ func_copy_all_files () while test -n "$my_srcdirs"; do IFS="$my_save_IFS" - my_srcdir=`echo "$my_srcdirs" | sed 's,:.*,,g'` - my_srcdirs=`echo "$my_srcdirs" | sed 's,:*[^:][^:]*:*,,'` + my_srcdir=`$ECHO "$my_srcdirs" | sed 's,:.*,,g'` + my_srcdirs=`$ECHO "$my_srcdirs" | sed 's,:*[^:][^:]*:*,,'` for my_filename in `cd "$my_srcdir" && ls`; do @@ -397,7 +420,7 @@ func_copy_all_files () # Add to the appropriate list if test -f "$my_srcdir/$my_filename"; then - my_srcfile=`echo "$my_srcdir/$my_filename" |sed "s,^$my_basedir/*,,"` + my_srcfile=`$ECHO "$my_srcdir/$my_filename" |sed "s,^$my_basedir/*,,"` my_srcfiles="$my_srcfiles${my_srcfiles:+:}$my_srcfile" elif $my_opt_recurse && test -d "$my_srcdir/$my_filename"; then my_srcdirs="$my_srcdirs${my_srcdirs:+:}$my_srcdir/$my_filename" @@ -571,7 +594,7 @@ func_included_files () /^m4_include(\[.*\])$/ { s,^m4_include(\[\(.*\)\])$,\1,; p; }; d' - test -f "$my_searchfile" && echo "$my_searchfile" + test -f "$my_searchfile" && $ECHO "$my_searchfile" # Only recurse when we don't care if all the variables we use get # trashed, since they are in global scope. @@ -606,7 +629,7 @@ func_serial () # If the file has no serial number, we assume it's ancient. test -n "$my_serial" || my_serial=0 - echo $my_serial + $ECHO $my_serial } # func_serial_update srcfile destfile [macro_regex] [old_macro_regex] @@ -45,7 +45,7 @@ DUALCASE=1; export DUALCASE # for MKS sh : ${GREP="grep"} : ${LIBTOOL="../libtool"} : ${MAKE="make"} -: ${MKDIR="mkdir"} # FIXME: Use @mkdir_p@ substitution for make -j +: ${MKDIR="mkdir"} : ${SED="sed"} : ${SHELL="${CONFIG_SHELL-/bin/sh}"} @@ -184,19 +184,48 @@ func_grep () $GREP "$1" "$2" >/dev/null 2>&1 } -# func_mkdir_p dir -# Make sure the entire path to DIR is available. +# func_mkdir_p directory-path +# Make sure the entire path to DIRECTORY-PATH is available. func_mkdir_p () { - my_dir=$1 - my_dirs= + my_directory_path="$1" + my_dir_list= + + if test -n "$my_directory_path"; then + + # Protect directory names starting with `-' + case $my_directory_path in + -*) my_directory_path="./$my_directory_path" ;; + esac + + # While some portion of DIR does not yet exist... + while test ! -d "$my_directory_path"; do + # ...make a list in topmost first order. Use a colon delimited + # list incase some portion of path contains whitespace. + my_dir_list="$my_directory_path:$my_dir_list" + + # If the last portion added has no slash in it, the list is done + case $my_directory_path in */*) ;; *) break ;; esac + + # ...otherwise throw away the child directory and loop + my_directory_path=`$ECHO "$my_directory_path" | $SED "$dirname"` + done + my_dir_list=`$ECHO $my_dir_list | $SED 's,:*$,,'` + + save_mkdir_p_IFS="$IFS"; IFS=':' + for my_dir in $my_dir_list; do + IFS="$save_mkdir_p_IFS" + # mkdir can fail with a `File exist' error if two processes + # try to create one of the directories concurrently. Don't + # stop in that case! + $MKDIR "$my_dir" 2>/dev/null || : + done + IFS="$save_mkdir_p_IFS" + fi - while test ! -d "$my_dir"; do - my_dirs="$my_dir $my_dirs" - case $my_dir in */*) ;; *) break ;; esac - my_dir=`$ECHO "$my_dir" | $SED "$dirname"` - done - test ! -n "$my_dirs" || $MKDIR $my_dirs + # Bail out if we (or some other process) failed to create a directory. + test -d "$my_directory_path" || \ + func_fatal_error "Failed to create \`$1'" } # func_mkprefixdir |