Integrate PR 12649's race detector directly in the testsuite machinery

This integrates Jan Kratochvil's nice race reproducer from PR
testsuite/12649 into the testsuite infrustructure directly.

With this, one only has to do either 'make check-read1' or 'make check
READ1="1"' to preload the read1.so library into expect.

Currently only enabled for glibc/GNU systems, and if
build==host==target.

gdb/testsuite/ChangeLog:

	* Makefile.in (EXTRA_RULES, CC): New variables, get from
	configure.
	(EXPECT): Handle READ1 being set.
	(all): Depend on EXTRA_RULES.
	(check-read1, expect-read1, read1.so, read1): New rules.
	* README (Testsuite Parameters): Document the READ1 make variable.
	(Race detection): New section.
	* configure: Regenerate.
	* configure.ac: If build==host==target, and running under a
	GNU/glibc system, add read1 to the extra Makefile rules.
	(EXTRA_RULES): AC_SUBST it.
	* lib/read1.c: New file.

gdb/ChangeLog:

	* Makefile.in (check-read1): New rule.
This commit is contained in:
Pedro Alves 2014-08-20 18:55:54 +01:00
parent 469a34932a
commit 2a31c6236d
8 changed files with 168 additions and 4 deletions

View File

@ -1,3 +1,7 @@
2014-08-20 Pedro Alves <palves@redhat.com>
* Makefile.in (check-read1): New rule.
2014-08-20 Joel Brobecker <brobecker@adacore.com>
* value.c (value_from_contents_and_address): Strip resolved_type's

View File

@ -1098,6 +1098,14 @@ check-perf: force
$(MAKE) $(TARGET_FLAGS_TO_PASS) check-perf; \
else true; fi
check-read1: force
@if [ -f testsuite/Makefile ]; then \
rootme=`pwd`; export rootme; \
rootsrc=`cd $(srcdir); pwd`; export rootsrc; \
cd testsuite; \
$(MAKE) $(TARGET_FLAGS_TO_PASS) check-read1; \
else true; fi
# The idea is to parallelize testing of multilibs, for example:
# make -j3 check//sh-hms-sim/{-m1,-m2,-m3,-m3e,-m4}/{,-nofpu}
# will run 3 concurrent sessions of check, eventually testing all 10

View File

@ -1,3 +1,19 @@
2014-08-20 Pedro Alves <palves@redhat.com>
Jan Kratochvil <jan.kratochvil@redhat.com>
* Makefile.in (EXTRA_RULES, CC): New variables, get from
configure.
(EXPECT): Handle READ1 being set.
(all): Depend on EXTRA_RULES.
(check-read1, expect-read1, read1.so, read1): New rules.
* README (Testsuite Parameters): Document the READ1 make variable.
(Race detection): New section.
* configure: Regenerate.
* configure.ac: If build==host==target, and running under a
GNU/glibc system, add read1 to the extra Makefile rules.
(EXTRA_RULES): AC_SUBST it.
* lib/read1.c: New file.
2014-08-20 Joel Brobecker <brobecker@adacore.com>
* gdb.dwarf2/data-loc.exp: Add additional tests exercising

View File

@ -39,9 +39,17 @@ ALL_SUBDIRS = gdb.ada gdb.arch gdb.asm gdb.base gdb.btrace gdb.cell gdb.cp \
gdb.stabs gdb.reverse gdb.threads gdb.trace gdb.xml \
$(SUBDIRS)
EXPECT = `if [ -f $${rootme}/../../expect/expect ] ; then \
echo $${rootme}/../../expect/expect ; \
else echo expect ; fi`
EXTRA_RULES = @EXTRA_RULES@
CC=@CC@
EXPECT = `if [ "$${READ1}" != "" ] ; then \
echo $${rootme}/expect-read1; \
elif [ -f $${rootme}/../../expect/expect ] ; then \
echo $${rootme}/../../expect/expect ; \
else \
echo expect ; \
fi`
RUNTEST = $(RUNTEST_FOR_TARGET)
@ -84,7 +92,7 @@ TARGET_FLAGS_TO_PASS = \
"RUNTEST=$(RUNTEST)" \
"RUNTESTFLAGS=$(RUNTESTFLAGS)"
all:
all: $(EXTRA_RULES)
@echo "Nothing to be done for all..."
.NOEXPORT:
@ -146,6 +154,9 @@ installcheck:
check: all $(abs_builddir)/site.exp
$(MAKE) $(CHECK_TARGET)
check-read1:
$(MAKE) READ1="1" check
# All the hair to invoke dejagnu. A given invocation can just append
# $(RUNTESTFLAGS)
DO_RUNTEST = \
@ -230,6 +241,7 @@ clean mostlyclean:
-rm -f core.* *.tf *.cl *.py tracecommandsscript copy1.txt zzz-gdbscript
-rm -f *.dwo *.dwp
-rm -rf outputs temp cache
-rm -f read1.so expect-read1
if [ x"${ALL_SUBDIRS}" != x ] ; then \
for dir in ${ALL_SUBDIRS}; \
do \
@ -263,3 +275,27 @@ config.status: configure
TAGS: force
find $(srcdir) -name '*.exp' -print | \
etags --regex='/proc[ \t]+\([^ \t]+\)/\1/' -
# Build the expect wrapper script that preloads the read1.so library.
expect-read1:
@echo Making expect-read1
@rm -f expect-read1-tmp
@touch expect-read1-tmp
@echo "# THIS FILE IS GENERATED -*- buffer-read-only: t -*- \n" >>expect-read1-tmp
@echo "# vi:set ro: */\n\n" >>expect-read1-tmp
@echo "# To regenerate this file, run:\n" >>expect-read1-tmp
@echo "# make clean; make/\n" >>expect-read1-tmp
@echo "export LD_PRELOAD=`pwd`/read1.so" >>expect-read1-tmp
@echo 'exec expect "$$@"' >>expect-read1-tmp
@chmod +x expect-read1-tmp
@mv expect-read1-tmp expect-read1
# Build the read1.so preload library. This overrides the `read'
# function, making it read one byte at a time. Running the testsuite
# with this catches racy tests.
read1.so: lib/read1.c
$(CC) -o $@ ${srcdir}/lib/read1.c -Wall -g -shared -fPIC $(CFLAGS)
# Build the read1 machinery.
.PHONY: read1
read1: read1.so expect-read1

View File

@ -176,6 +176,47 @@ Example:
If not using GNU make then the value is passed directly to runtest.
If not specified, all tests are run.
READ1
This make (not runtest) variable is used to specify whether the
testsuite preloads the read1.so library into expect. Any non-empty
value means true. See "Race detection" below.
Race detection
**************
The testsuite includes a mechanism that helps detect test races.
For example, say the program running under expect outputs "abcd", and
a test does something like this:
expect {
"a.*c" {
}
"b" {
}
"a" {
}
}
Which case happens to match depends on what expect manages to read
into its internal buffer in one go. If it manages to read three bytes
or more, then the first case matches. If it manages to read two
bytes, then the second case matches. If it manages to read only one
byte, then the third case matches.
To help detect these cases, the race detection mechanism preloads a
library into expect that forces the `read' system call to always
return at most 1 byte.
To enable this, either pass a non-empty value in the READ1 make
variable, or use the check-read1 make target instead of check.
Examples:
make -j10 check-read1 TESTS="*/paginate-*.exp"
make -j10 check READ1="1"
Testsuite Configuration
***********************

View File

@ -591,6 +591,7 @@ ac_includes_default="\
ac_subst_vars='LTLIBOBJS
LIBOBJS
EXTRA_RULES
EGREP
GREP
CPP
@ -3448,6 +3449,15 @@ done
if test "${build}" = "${host}" -a "${host}" = "${target}"; then
case "${host}" in
*gnu*)
EXTRA_RULES=read1
;;
esac
fi
ac_config_files="$ac_config_files Makefile gdb.ada/Makefile gdb.arch/Makefile gdb.asm/Makefile gdb.base/Makefile gdb.btrace/Makefile gdb.cell/Makefile gdb.cp/Makefile gdb.disasm/Makefile gdb.dwarf2/Makefile gdb.dlang/Makefile gdb.fortran/Makefile gdb.gdb/Makefile gdb.go/Makefile gdb.server/Makefile gdb.java/Makefile gdb.hp/Makefile gdb.hp/gdb.objdbg/Makefile gdb.hp/gdb.base-hp/Makefile gdb.hp/gdb.aCC/Makefile gdb.hp/gdb.compat/Makefile gdb.hp/gdb.defects/Makefile gdb.guile/Makefile gdb.linespec/Makefile gdb.mi/Makefile gdb.modula2/Makefile gdb.multi/Makefile gdb.objc/Makefile gdb.opencl/Makefile gdb.opt/Makefile gdb.pascal/Makefile gdb.perf/Makefile gdb.python/Makefile gdb.reverse/Makefile gdb.stabs/Makefile gdb.threads/Makefile gdb.trace/Makefile gdb.xml/Makefile"
cat >confcache <<\_ACEOF

View File

@ -87,6 +87,15 @@ AC_CHECK_HEADERS(pthread.h)
AC_EXEEXT
if test "${build}" = "${host}" -a "${host}" = "${target}"; then
case "${host}" in
*gnu*)
EXTRA_RULES=read1
;;
esac
fi
AC_SUBST(EXTRA_RULES)
AC_OUTPUT([Makefile \
gdb.ada/Makefile \
gdb.arch/Makefile gdb.asm/Makefile gdb.base/Makefile gdb.btrace/Makefile \

40
gdb/testsuite/lib/read1.c Normal file
View File

@ -0,0 +1,40 @@
/* This is part of GDB, the GNU debugger.
Copyright 2011-2014 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 3 of the License, 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 <http://www.gnu.org/licenses/>.
*/
#define _GNU_SOURCE 1
#include <dlfcn.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>
/* Wrap 'read', forcing it to return only one byte at a time, if
reading from the terminal. */
ssize_t
read (int fd, void *buf, size_t count)
{
static ssize_t (*read2) (int fd, void *buf, size_t count) = NULL;
if (read2 == NULL)
{
unsetenv ("LD_PRELOAD");
read2 = dlsym (RTLD_NEXT, "read");
}
if (count > 1 && isatty (fd) >= 1)
count = 1;
return read2 (fd, buf, count);
}