bug#68808: subsecond mtime discovery code insufficient
Erik A Johnson <[email protected]> Mon, 27 May 2024 20:59:37 +0000
| Newsgroups | gmane.comp.sysutils.automake.bugs |
|---|---|
| Message-ID | <[email protected]> |
Thanks, Karl. I wasn't sure what version was to be patched but it looks like the current git repository has those changes, so I tested that with the macOS make: * fine on the tests that failed previously because of macOS default make having only second resolution * color-tests2.sh and color-tests2-w.sh fail -- logs attached. Erik On May 27, 2024, at 12:34 PM, Karl Berry <[email protected]> wrote: Hi Erik and all - I (finally) made the change below to have automake test for a make that doesn't support subsecond mtimes even when the rest of the system is ok, as you noted happens with the make-3.81 shipped by macOS. I installed make-3.8.1 on my Rocky 9 system, but it did not cause the lossage. So I'm not sure if there's an error in my test (wouldn't surprise me) or if it's something about the mac system specifically. As far as I could tell, the new code does succeed on Rocky 9. So I hope it also succeeds on other current systems where the whole subsecond-mtime thing is intended. Erik, can you either apply this patch (and remake and run the tests), or get the current automake dev sources and try it? If anyone (Zack, Bogdan, Jim, ...) else could look at, and/or try, the new code and see if any problems show up, that would be great. I hope this works and we can start pushing towards the release. --thanks, karl. --- a/m4/sanity.m4 +++ b/m4/sanity.m4 @@ -24,7 +24,7 @@ AS_IF([sleep 0.001 2>/dev/null], [am_cv_sleep_fractional_seconds=true], # nanosecond, matching clock_gettime. However, it is probably not # possible to delay execution of a shell script for less than one # millisecond, due to process creation overhead and scheduling -# granularity, so we don't check for anything finer than that. +# granularity, so we don't check for anything finer than that. (See below.) AC_DEFUN([_AM_FILESYSTEM_TIMESTAMP_RESOLUTION], [dnl AC_REQUIRE([_AM_SLEEP_FRACTIONAL_SECONDS]) AC_CACHE_CHECK([filesystem timestamp resolution], am_cv_filesystem_timestamp_resolution, [dnl @@ -34,6 +34,9 @@ am_cv_filesystem_timestamp_resolution=2 # Only try to go finer than 1s if sleep can do it. am_try_resolutions=1 if $am_cv_sleep_fractional_seconds; then + # Even a millisecond often causes a bunch of false positives, + # so just try a hundredth of a second. The time saved between .001 and + # .01 is not terribly consequential. am_try_resolutions="0.01 0.1 $am_try_resolutions" fi @@ -48,12 +51,13 @@ rm -f conftest.ts? : > conftest.ts3 # Make sure ls -t actually works. Do 'set' in a subshell so we don't -# clobber the current shell's arguments. +# clobber the current shell's arguments. (Outer-level square brackets +# are for m4; be careful, it's easy to get confused.) if ( set X `[ls -t conftest.ts[12]]` && { - test "$[*]" != "X conftest.ts1 conftest.ts2" || - test "$[*]" != "X conftest.ts2 conftest.ts1"; + test "$[]*" != "X conftest.ts1 conftest.ts2" || + test "$[]*" != "X conftest.ts2 conftest.ts1"; } ); then :; else # If neither matched, then we have a broken ls. This can happen @@ -64,7 +68,7 @@ if ( ["Bad output from ls -t: \"`[ls -t conftest.ts[12]]`\""], [AS_MESSAGE_LOG_FD]) AC_MSG_FAILURE([ls -t produces unexpected output. -Make sure there is not a broken alias in your environment.]) +Make sure there is not a broken ls alias in your environment.]) fi for am_try_res in $am_try_resolutions; do @@ -84,11 +88,47 @@ for am_try_res in $am_try_resolutions; do test "$[]2" = conftest.ts3 && test "$[]3" = conftest.ts2 && test "$[]4" = conftest.ts1); then - am_cv_filesystem_timestamp_resolution=$am_try_res - break + # + # Ok, ls -t worked. We have one more thing to check: make. + # It can happen that everything else supports the subsecond mtimes, + # but make doesn't, notably on macOS, which ships make 3.81 from + # 2006 (the last one released under GPLv2). https://urldefense.com/v3/__https://bugs.gnu.org/68808__;!!LIr3w8kk_Xxm!rq87CiefTKIMZV02HfASxRvKLnpaw6kZk70cv22sBPSJkGDk112T-JXYGUYvKK_BgnEp19HKx-M5RVFS$ + # + # So, first let's create a Makefile: + rm -f conftest.mk + echo 'conftest.ts1: conftest.ts2' >conftest.mk + echo ' touch conftest.ts2' >>conftest.mk + # + # Now, running + # touch conftest.ts1; touch conftest.ts2; make + # should touch ts1 because ts2 is newer. This could happen by luck, + # but most often, it will fail if make's support is insufficient. So + # test for several consecutive successes. + # + # (We reuse conftest.ts[12] because we still want to modify existing + # files, not create new ones, per above.) + n=0 + make_ok=true + until test $n -eq 4; do + echo one > conftest.ts1 + sleep $am_try_res + echo two > conftest.ts2 # ts2 should now be newer than ts1 + if make -f conftest.mk | grep 'up to date' >/dev/null; then + make_ok=false + break # out of $n loop + fi + n=`expr $n + 1` + done + if $make_ok; then + # Everything we know to check worked out, so call this resolution good. + am_cv_filesystem_timestamp_resolution=$am_try_res + break # out of resolution loop + fi + # Otherwise, we'll go on to check the next resolution. fi done rm -f conftest.ts? +# (end _am_filesystem_timestamp_resolution) ])]) # AM_SANITY_CHECK compile finished at Mon May 27 10:01:57 2024
color-tests2.log
(application/octet-stream, 2.8 KB)
am-test-lib.sh: Running from installcheck: no am-test-lib.sh: Test Protocol: none am-test-lib.sh: PATH = /tmp/johnsone/automake_git/automake/bin:/tmp/johnsone/automake_git/automake/t/ax:.:/Users/johnsone/bin/osx:/Users/johnsone/bin:/Library/Frameworks/Python.framework/Versions/3.12/bin:/Library/Frameworks/Python.framework/Versions/2.7/bin:/usr/local/bin:/System/Cryptexes/App/usr/bin:/usr/bin:/bin:/usr/sbin:/sbin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/local/bin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/bin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/appleinternal/bin:/opt/X11/bin:/Library/Apple/usr/bin:/Library/TeX/texbin:/Applications/VMware Fusion.app/Contents/Public ++ pwd /tmp/johnsone/automake_git/automake/t/color-tests2.dir + red='\[0;31m' + grn='\[0;32m' + lgn='\[1;32m' + blu='\[1;34m' + mgn='\[0;35m' + std='\[m' + set +e + expect -c 'exit 77' + test 77 -eq 77 + cat + cat + MAKE=make + expect -f expect-check spawn make stdout is a tty + rm -f expect-check Makefile + cat + cat + cat + cat + cat + cat + cp fail xfail + cp pass xpass + chmod +x pass fail skip xpass xfail error + aclocal-1.16 -Werror + autoconf + automake-1.16 --foreign -Werror -Wall --add-missing parallel-tests: installing './test-driver' + cat + for vpath in false : + false + srcdir=. + ./configure checking for a BSD-compatible install... /usr/bin/install -c checking whether sleep supports fractional seconds... true checking filesystem timestamp resolution... 1 checking whether build environment is sane... yes checking for a race-free mkdir -p... mkdir -p checking for gawk... no checking for mawk... no checking for nawk... no checking for awk... awk checking whether make sets $(MAKE)... yes checking whether make supports nested variables... yes checking xargs -n works... yes checking that generated files are newer than configure... done configure: creating ./config.status config.status: creating Makefile + our_make TERM=ansi + set MAKE=make TERM=ansi + env MAKE=make TERM=ansi expect -f ./expect-make + cat stdout spawn make -e check make pass fail skip xpass xfail error make[1]: Nothing to be done for `pass'. make[1]: Nothing to be done for `fail'. make[1]: Nothing to be done for `skip'. make[1]: Nothing to be done for `xpass'. make[1]: Nothing to be done for `xfail'. make[1]: Nothing to be done for `error'. make check-TESTS [0;32mPASS[m: pass + test_color + cat stdout + grep '^\[0;32mPASS\[m: .*pass' [0;32mPASS[m: pass + cat stdout + grep '^\[0;31mFAIL\[m: .*fail' + am_exit_trap 1 + exit_status=1 + set +e + cd /tmp/johnsone/automake_git/automake + test none = tap + case $am_explicit_skips in + test 1 -eq 0 + keep_testdirs=yes + am_keeping_testdirs + case $keep_testdirs in + return 0 + set +x FAIL t/color-tests2.sh (exit status: 1)
color-tests2-w.log
(application/octet-stream, 2.8 KB)
./t/color-tests2-w.sh: will source ./t/color-tests2.sh am-test-lib.sh: Running from installcheck: no am-test-lib.sh: Test Protocol: none am-test-lib.sh: PATH = /tmp/johnsone/automake_git/automake/bin:/tmp/johnsone/automake_git/automake/t/ax:.:/Users/johnsone/bin/osx:/Users/johnsone/bin:/Library/Frameworks/Python.framework/Versions/3.12/bin:/Library/Frameworks/Python.framework/Versions/2.7/bin:/usr/local/bin:/System/Cryptexes/App/usr/bin:/usr/bin:/bin:/usr/sbin:/sbin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/local/bin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/bin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/appleinternal/bin:/opt/X11/bin:/Library/Apple/usr/bin:/Library/TeX/texbin:/Applications/VMware Fusion.app/Contents/Public +++ pwd /tmp/johnsone/automake_git/automake/t/color-tests2-w.dir ++ red='\[0;31m' ++ grn='\[0;32m' ++ lgn='\[1;32m' ++ blu='\[1;34m' ++ mgn='\[0;35m' ++ std='\[m' ++ set +e ++ expect -c 'exit 77' ++ test 77 -eq 77 ++ cat ++ cat ++ MAKE=make ++ expect -f expect-check spawn make stdout is a tty ++ rm -f expect-check Makefile ++ cat ++ cat ++ cat ++ cat ++ cat ++ cat ++ cp fail xfail ++ cp pass xpass ++ chmod +x pass fail skip xpass xfail error ++ aclocal-1.16 -Werror ++ autoconf ++ automake-1.16 --foreign -Werror -Wall --add-missing ++ cat ++ for vpath in false : ++ false ++ srcdir=. ++ ./configure checking for a BSD-compatible install... /usr/bin/install -c checking whether sleep supports fractional seconds... true checking filesystem timestamp resolution... 1 checking whether build environment is sane... yes checking for a race-free mkdir -p... mkdir -p checking for gawk... no checking for mawk... no checking for nawk... no checking for awk... awk checking whether make sets $(MAKE)... yes checking whether make supports nested variables... yes checking xargs -n works... yes checking that generated files are newer than configure... done configure: creating ./config.status config.status: creating Makefile ++ our_make TERM=ansi ++ set MAKE=make TERM=ansi ++ env MAKE=make TERM=ansi expect -f ./expect-make ++ cat stdout spawn make -e check make pass fail skip xpass xfail error make[1]: Nothing to be done for `pass'. make[1]: Nothing to be done for `fail'. make[1]: Nothing to be done for `skip'. make[1]: Nothing to be done for `xpass'. make[1]: Nothing to be done for `xfail'. make[1]: Nothing to be done for `error'. make check-TESTS [0;32mPASS[m: pass ++ test_color ++ cat stdout ++ grep '^\[0;32mPASS\[m: .*pass' [0;32mPASS[m: pass ++ cat stdout ++ grep '^\[0;31mFAIL\[m: .*fail' + am_exit_trap 1 + exit_status=1 + set +e + cd /tmp/johnsone/automake_git/automake + test none = tap + case $am_explicit_skips in + test 1 -eq 0 + keep_testdirs=yes + am_keeping_testdirs + case $keep_testdirs in + return 0 + set +x FAIL t/color-tests2-w.sh (exit status: 1)