Hello. Thank you for reporting the issue.
The attached patch should fix the problem. It may be a bit of an overkill, perhaps just one of the fixes would suffice, but it seems to work at least. I've re-made your useful script into an Automake test. Since non-deterministic defects may be hard to find and fix, and certainly harder to test if they're fixed, the new version simply runs parallel 'make recheck' a few times "just in case". Without the fix, the test failed in the first or the second run. With the fix, the test (which runs 'make recheck' 5 times) passed 5 times in a row. This *should* be a decent sample. All tests with "check" in the name pass. The test and my patch can, of course, be adapted and further changed. -- Regards - Bogdan ('bogdro') D. (GNU/Linux & FreeDOS) X86 assembly (DOS, GNU/Linux): http://bogdro.evai.pl/index-en.php Soft(EN): http://bogdro.evai.pl/soft http://bogdro.evai.pl/soft4asm www.Xiph.org www.TorProject.org www.LibreOffice.org www.GnuPG.org
From eb64fc56f13955a0b05b89492f48df886311191f Mon Sep 17 00:00:00 2001 From: Bogdan Drozdowski <> Date: Sat, 17 Aug 2024 00:17:35 +0200 Subject: [PATCH] Bug#68860 Fix race condition in recheck --- bin/automake.in | 6 +- lib/am/check.am | 2 +- t/list-of-tests.mk | 1 + t/recheck-race.sh | 135 +++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 141 insertions(+), 3 deletions(-) create mode 100644 t/recheck-race.sh diff --git a/bin/automake.in b/bin/automake.in index a17f45236..1d6c29d1c 100644 --- a/bin/automake.in +++ b/bin/automake.in @@ -4705,12 +4705,14 @@ sub do_check_merge_target () # The check target must depend on the local equivalent of # 'all', to ensure all the primary targets are built. Then it # must build the local check rules. - $output_rules .= "check-am: all-am\n"; + $output_rules .= "check-am: all-am"; if (@check) { - pretty_print_rule ("\t\$(MAKE) \$(AM_MAKEFLAGS)", "\t ", @check); + $output_rules .= " @check"; + #pretty_print_rule ("\t\$(MAKE) \$(AM_MAKEFLAGS)", "\t ", @check); depend ('.MAKE', 'check-am'); } + $output_rules .= "\n"; if (@check_tests) { diff --git a/lib/am/check.am b/lib/am/check.am index e51a771bf..72c71a0f4 100644 --- a/lib/am/check.am +++ b/lib/am/check.am @@ -480,7 +480,7 @@ check-TESTS: %CHECK_DEPS% ## Recheck must depend on $(check_SCRIPTS), $(check_PROGRAMS), etc. ## It must also depend on the 'all' target. See automake bug#11252. -recheck: all %CHECK_DEPS% +recheck: all-am %CHECK_DEPS% ## See comments above in the check-TESTS recipe for why remove ## $(TEST_SUITE_LOG) here. @$(am__rm_f) $(TEST_SUITE_LOG) diff --git a/t/list-of-tests.mk b/t/list-of-tests.mk index e80ace470..f359ba8a1 100644 --- a/t/list-of-tests.mk +++ b/t/list-of-tests.mk @@ -824,6 +824,7 @@ t/parallel-tests-no-spurious-summary.sh \ t/parallel-tests-exit-statuses.sh \ t/parallel-tests-console-output.sh \ t/parallel-tests-once.sh \ +t/recheck-race.sh \ t/tests-environment.sh \ t/am-tests-environment.sh \ t/tests-environment-backcompat.sh \ diff --git a/t/recheck-race.sh b/t/recheck-race.sh new file mode 100644 index 000000000..abeb8c441 --- /dev/null +++ b/t/recheck-race.sh @@ -0,0 +1,135 @@ +#! /bin/sh +# Copyright (C) 2024 Free Software Foundation, Inc. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <https://www.gnu.org/licenses/>. + +# Test for race conditions in 'make recheck'. + +. test-init.sh + +cat > configure.ac <<EOF +AC_INIT([foo], [2]) +AC_CONFIG_SRCDIR([config.h.in]) +AC_CONFIG_HEADERS([config.h]) +AM_INIT_AUTOMAKE([foreign silent-rules parallel-tests]) +AC_LANG([C++]) +AC_PROG_CXX +AC_PROG_CXXCPP +AC_PROG_RANLIB +AC_CONFIG_FILES([Makefile]) +AC_OUTPUT +EOF + +cat > Makefile.am <<EOF +lib_LIBRARIES = libfoo.a +libfoo_a_SOURCES = foo.cc + +check_LIBRARIES = libtest.a +libtest_a_SOURCES = test.cc + +TESTS = one.test two.test +TEST_EXTENSIONS = .test +AM_DEFAULT_SOURCE_EXT = .cc +EXTRA_PROGRAMS = \$(TESTS) + +libtest_a_LIBADD = libfoo.a +LDADD = libtest.a libfoo.a +EOF + +cat > foo.h <<EOF +#ifndef my_foo_h +#define my_foo_h +#include <string> +std::string foo(void); +#endif +EOF + +cat > foo.cc <<EOF +#include <config.h> +#include "foo.h" +std::string foo(void) { return "fu"; } + +EOF + +cat > one.cc <<EOF +#include <config.h> +#include "foo.h" +#include "test.h" +#include <iostream> +#include <string> +int main(int argc, char* argv[]) +{ + init(argc, argv); + std::cout << "Hello World!\n" << foo() << "\n"; + return 0; +} +EOF + +cat > two.cc <<EOF +#include <config.h> +#include "foo.h" +#include "test.h" +#include <iostream> +#include <string> +int main(int argc, char* argv[]) +{ + init(argc, argv); + std::string str = foo(); + if (str != "foo") { + std::cerr << "error: foo(): " << str << "\n"; + return 1; + } + return 0; +} +EOF + +cat > test.h <<EOF +#ifndef my_test_h +#define my_test_h +void init(int argc, char* argv[]); +#endif +EOF + +cat > test.cc <<EOF +#include <config.h> +#include "test.h" +#include "foo.h" +#include <iostream> +void init(int argc, char* argv[]) +{ + std::cout << "init test for " << foo() << "\n"; +} +EOF + +$ACLOCAL +$AUTOCONF +$AUTOHEADER +$AUTOMAKE -a +./configure --enable-silent-rules +$MAKE all -j8 +run_make -M -e FAIL check -j8 + +sed 's,"fu","foo",' < foo.cc > foo.cc-t && mv foo.cc-t foo.cc + +$MAKE recheck -j16 +$MAKE clean all +$MAKE recheck -j16 +$MAKE clean all +$MAKE recheck -j16 +$MAKE clean all +$MAKE recheck -j16 +$MAKE clean all +$MAKE recheck -j16 + +: -- 2.35.1