Reference: <http://debbugs.gnu.org/cgi/bugreport.cgi?bug=8365>
Hi Sam, and thanks for the report. > FAIL: aclocal6.test (exit: 1) > ============================= > > /home/sds/src/automake-1.11.1/tests:/home/sds/src/top/bin:/usr/lib6 > 4/qt-3.3/bin:/usr/kerberos/bin:/usr/local/bin:/bin:/usr/bin:/usr/NX > /bin:/home/sds/bin:/sbin:/usr/sbin:/usr/NX/bin:/usr/NX/bin:/home/sd > s/bin:/sbin:/usr/sbin:/usr/NX/bin:/home/sds/bin:/sbin:/usr/sbin > aclocal6: running make --version -v | grep GNU > GNU Make 3.81 > === Running test ./aclocal6.test > ++ pwd > /home/sds/src/automake-1.11.1/tests/aclocal6.dir > + set -e > + cat > + cat > + mkdir sub > + : > + mkdir m4 > + echo 'AC_DEFUN([SOME_DEFS], [])' > + echo 'AC_DEFUN([MORE_DEFS], [AC_SUBST([GREPME])])' > + aclocal-1.11 -Werror -I m4 > + autoconf > + automake-1.11 --foreign -Werror -Wall --copy --add-missing > + test -d autom4te.cache > + test_cache='test -d' > + mkdir build > + cd build > + ../configure > checking for a BSD-compatible install... /usr/bin/install -c > checking whether build environment is sane... yes > checking for a thread-safe mkdir -p... /bin/mkdir -p > checking for gawk... gawk > checking whether make sets $(MAKE)... yes > configure: creating ./config.status > config.status: creating Makefile > config.status: creating sub/Makefile > + make > Making all in sub > make[1]: Entering directory > `/home2/sds/src/automake-1.11.1/tests/aclocal6.dir/build/sub' > make[1]: Nothing to be done for `all'. > make[1]: Leaving directory > `/home2/sds/src/automake-1.11.1/tests/aclocal6.dir/build/sub' > make[1]: Entering directory > `/home2/sds/src/automake-1.11.1/tests/aclocal6.dir/build' > make[1]: Nothing to be done for `all-am'. > make[1]: Leaving directory > `/home2/sds/src/automake-1.11.1/tests/aclocal6.dir/build' > + echo 'AC_DEFUN([SOME_DEFS], [MORE_DEFS])' > + echo 'AC_SUBST([METOO])' > + cd sub > + make > cd .. && make am--refresh > make[1]: Entering directory > `/home2/sds/src/automake-1.11.1/tests/aclocal6.dir/build' > CDPATH="${ZSH_VERSION+.}:" && cd .. && /bin/sh > /home/sds/src/automake-1.11.1/tests/aclocal6.dir/missing --run aclocal-1.11 > -I m4 > cd .. && /bin/sh /home/sds/src/automake-1.11.1/tests/aclocal6.dir/missing > --run automake-1.11 --foreign > CDPATH="${ZSH_VERSION+.}:" && cd .. && /bin/sh > /home/sds/src/automake-1.11.1/tests/aclocal6.dir/missing --run autoconf > Correct so far: aclocal.m4 dependencies are modified, so the Automake-generated Makefile re-runs aclocal, autoconf and automake ... > make[1]: Leaving directory > `/home2/sds/src/automake-1.11.1/tests/aclocal6.dir/build' > ... but then it doesn't re-run configure! So that the Makefile(s) are not updated, and consequently ... > make[1]: Entering directory > `/home2/sds/src/automake-1.11.1/tests/aclocal6.dir/build' > make[1]: Leaving directory > `/home2/sds/src/automake-1.11.1/tests/aclocal6.dir/build' > make: Nothing to be done for `all'. > + cd .. > + grep GREPME Makefile > + exit_status=1 > ... this check fails. -*-*- Now, why is configure not re-run? Here is my (longish) tentative explanation, step by step. In what follows, I'll use the abbraviation `TS(f)' to indicate the timestamp (i.e. last modification time) of the file `f'. 01. configure is run for the first time; it concludes its execution creating the `config.status' script and the `Makefile' and `sub/Makefile' files, which are all assured to be created older than configure (see code in sanity.m4:AM_SANITY_CHECK). 02. Since the creations of `config.status', `Makefile' and `sub/Makefile' take place very near, it's quite likely they'll have the same timestamp; let's assume this is indeed the case: [E1] TS(config.status) = TS(Makefile) = TS(sub/Makefile) 03. make is run for the first time; all is up-to-date at this point, so that nothing gets rebuilt -- basically a no-op; 04. the test script modifies the aclocal dependencies `m4/somedef.m4' and `acinclude.m4', *without sleeping* before doing this modification (this lack of a `sleep' is very important; see point 7 below). 05. make is called again right away *from the `sub' subdirectory*; it sees that `m4/somedef.m4' and `acinclude.m4' are newer than `sub/Makefile.in' (which depends on them), and it knows that `sub/Makefile' depends on `sub/Makefile.in'. So a recursive make call is issued, to run the special target `am--refresh' *in the top-level directory*, in order to bring `sub/Makefile.in' up-to-date. 06. This "recursive" make, running in the top-level directory, similarly sees that `m4/somedef.m4' and `acinclude.m4' are newer than `Makefile.in' (which depends on them), and that `Makefile' depends on `Makefile.in'. It also sees that `Makefile' depends on `config.status', which in turn depends on `configure', which in turn depends on `aclocal.m4'. 07. At this point, make issues calls to aclocal, autoconf and automake in order to bring up-to-date the various files that `Makefile' depends on. After the autotools have run, we have: [E3] for each x in { Makefile.in, sub/Makefile.in, configure, aclocal.m4 } for each y in { config.status, sub/Makefile, Makefile, m4/somedef.m4, acinclude.m4 } it is TS(x) >= TS(y) 08. Now, since no explicit call to `sleep' has been issued in any of the preceding steps (from (2) to (7)), it's very well possible (assuming those steps have been executed fast enough, as would mayhap be possible on a fast, lighlty loaded system) that all the files updated until now still have the *same* timestamp of `config.status'. Let's assume this is indeed the case; so we have: [E4] TS(Makefile.in) = TS(sub/Makefile.in) = TS(configure) = = TS(aclocal.m4) = TS(m4/somedef.m4) = TS(acinclude.m4) = = TS(config.status) = TS(Makefile) = TS(sub/Makefile). 09. Reprising the dependency analysis of pass (6), make (in top-level directory) now sees that `config.status' is *not* older than `configure'; so `config.status --recheck' (which would be responsible to re-run configure, and regenerate an updated `config.status') won't be called. Similarly, both `config.status' and `Makefile.in' are *not* older than `Makefile', so Makefile won't be regenerated either (it would have been if .`config.status --recheck' had been run). At this point, the work in the top-level directory is concluded. 10. Back in the `sub' subdirectory, a similar situation arises: now `config.status' and `sub/Makefile.in' are fully up-to-date *for what concerns the timestamps*, thanks to the work done by the top-level Makefile; yet, they are *not* newer than `sub/Makefile' (see [E4]), which consequently doesn't get rebuilt. 11. Failure ensues. D'oh! -*-*- Ralf, does the above explanation sounds sensible to you? If yes, OK to apply the attached trivial patch (to maint) to fix this failure? Sam, have you by chance kept the content of the *.dir directories for the failed tests? If yes, could you please send them to me? (Notice that you might have to send them off-list, as I'm not sure how the policy about size and format of attachements on the automake-patches list is). This way I could verify whether my explanation is correct. Thanks, Stefano
From 2dff1fdaf0f2cf37980307b7413984dfb6ac155b Mon Sep 17 00:00:00 2001 From: Stefano Lattarini <stefano.lattar...@gmail.com> Date: Wed, 30 Mar 2011 18:06:29 +0200 Subject: [PATCH] tests: fix timestamp-related spurious failure in aclocal6.test Related to automake bug#8365. * tests/aclocal6.test: Sleep before modifying m4 files that should trigger remake rules. This fixes an hard-to-hit timestamp-related race condition. Report from Sam Steingold. --- ChangeLog | 9 +++++++++ tests/aclocal6.test | 2 ++ 2 files changed, 11 insertions(+), 0 deletions(-) diff --git a/ChangeLog b/ChangeLog index dae2a48..bafedb1 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +2011-03-30 Stefano Lattarini <stefano.lattar...@gmail.com> + + tests: fix timestamp-related spurious failure in aclocal6.test + Related to automake bug#8365. + * tests/aclocal6.test: Sleep before modifying m4 files that should + trigger remake rules. This fixes an hard-to-hit timestamp-related + race condition. + Report from Sam Steingold. + 2011-03-21 Ralf Wildenhues <ralf.wildenh...@gmx.de> tests: fix unindent to use printf not echo for script. diff --git a/tests/aclocal6.test b/tests/aclocal6.test index ea6bac3..fb3842c 100755 --- a/tests/aclocal6.test +++ b/tests/aclocal6.test @@ -57,6 +57,8 @@ cd build ../configure $MAKE +# Modified configure dependencies must be newer than config.status. +$sleep # Update an aclocal.m4 dependency, then make sure all Makefiles # are updated, even from a sub-directory. echo 'AC_DEFUN([SOME_DEFS], [MORE_DEFS])' > ../m4/somedefs.m4 -- 1.7.2.3