mirror of
https://sourceware.org/git/binutils-gdb.git
synced 2025-01-24 12:35:55 +08:00
[gdb/testsuite] Add check-readmore
Consider the gdb output:
...
27 return SYSCALL_CANCEL (nanosleep, requested_time, remaining);^M
(gdb) ^M
Thread 2 "run-attach-whil" stopped.^M
...
When trying to match the gdb prompt using gdb_test which uses '$gdb_prompt $',
it may pass or fail.
This sort of thing needs to be fixed (see commit b0e2f96b56
), but there's
currently no way to reliably find this type of FAILs.
We have check-read1, but that one actually make the test pass reliably.
We need something like the opposite of check-read1: something that makes
expect read a bit slower, or more exhaustively.
Add a new test target check-readmore that implements this.
There are two methods of implementing this in read1.c:
- the first method waits a bit before doing a read
- the second method does a read and then decides whether to
return or to wait a bit and do another read, and so on.
The second method is potentially faster, has less risc of timeout and could
potentially detect more problems. The first method has a simpler
implementation.
The second method is enabled by default. The default waiting period is 10
miliseconds.
The first method can be enabled using:
...
$ export READMORE_METHOD=1
...
and the waiting period can be specified in miliseconds using:
...
$ export READMORE_SLEEP=9
...
Also a log file can be specified using:
...
$ export READMORE_LOG=$(pwd -P)/LOG
...
Tested on x86_64-linux.
Testing with check-readmore showed these regressions:
...
FAIL: gdb.base/bp-cmds-continue-ctrl-c.exp: run: stop with control-c (continue)
FAIL: gdb.base/bp-cmds-continue-ctrl-c.exp: attach: stop with control-c (continue)
...
I have not been able to find a problem in the test-case, and I think it's the
nature of both the test-case and readmore that makes it run longer. Make
these pass by increasing the alarm timeout from 60 to 120 seconds.
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=27957
This commit is contained in:
parent
f9edf60830
commit
fa9ce2c143
@ -1681,12 +1681,12 @@ check-perf: force
|
||||
$(MAKE) $(TARGET_FLAGS_TO_PASS) check-perf; \
|
||||
else true; fi
|
||||
|
||||
check-read1: force
|
||||
check-read1 check-readmore: 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; \
|
||||
$(MAKE) $(TARGET_FLAGS_TO_PASS) $@; \
|
||||
else true; fi
|
||||
|
||||
check-parallel: force
|
||||
|
@ -39,6 +39,8 @@ CC=@CC@
|
||||
|
||||
EXPECT = `if [ "$${READ1}" != "" ] ; then \
|
||||
echo $${rootme}/expect-read1; \
|
||||
elif [ "$${READMORE}" != "" ] ; then \
|
||||
echo $${rootme}/expect-readmore; \
|
||||
elif [ -f $${rootme}/../../expect/expect ] ; then \
|
||||
echo $${rootme}/../../expect/expect ; \
|
||||
else \
|
||||
@ -161,6 +163,9 @@ check: all $(abs_builddir)/site.exp
|
||||
check-read1: read1.so expect-read1
|
||||
$(MAKE) READ1="1" check
|
||||
|
||||
check-readmore: readmore.so expect-readmore
|
||||
$(MAKE) READMORE="1" check
|
||||
|
||||
# Check whether we need to print the timestamp for each line of
|
||||
# status.
|
||||
TIMESTAMP = $(if $(TS),| $(srcdir)/print-ts.py $(if $(TS_FORMAT),$(TS_FORMAT),),)
|
||||
@ -344,7 +349,7 @@ clean mostlyclean:
|
||||
-rm -f *.dwo *.dwp
|
||||
-rm -rf outputs temp cache
|
||||
-rm -rf gdb.perf/workers gdb.perf/outputs gdb.perf/temp gdb.perf/cache
|
||||
-rm -f read1.so expect-read1
|
||||
-rm -f read1.so expect-read1 readmore.so expect-readmore
|
||||
|
||||
distclean maintainer-clean realclean: clean
|
||||
-rm -f *~ core
|
||||
@ -367,18 +372,22 @@ TAGS: force
|
||||
-
|
||||
|
||||
# Build the expect wrapper script that preloads the read1.so library.
|
||||
expect-read1:
|
||||
expect-read1 expect-readmore:
|
||||
$(ECHO_GEN) \
|
||||
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
|
||||
rm -f $@-tmp; \
|
||||
touch $@-tmp; \
|
||||
echo "# THIS FILE IS GENERATED -*- buffer-read-only: t -*- \n" >>$@-tmp; \
|
||||
echo "# vi:set ro: */\n\n" >>$@-tmp; \
|
||||
echo "# To regenerate this file, run:\n" >>$@-tmp; \
|
||||
echo "# make clean; make/\n" >>$@-tmp; \
|
||||
if [ $@ = expect-read1 ]; then \
|
||||
echo "export LD_PRELOAD=`pwd`/read1.so" >>$@-tmp; \
|
||||
else \
|
||||
echo "export LD_PRELOAD=`pwd`/readmore.so" >>$@-tmp; \
|
||||
fi; \
|
||||
echo 'exec expect "$$@"' >>$@-tmp; \
|
||||
chmod +x $@-tmp; \
|
||||
mv $@-tmp $@
|
||||
|
||||
# Build the read1.so preload library. This overrides the `read'
|
||||
# function, making it read one byte at a time. Running the testsuite
|
||||
@ -386,9 +395,17 @@ expect-read1:
|
||||
read1.so: lib/read1.c
|
||||
$(ECHO_CC) $(CC) -o $@ ${srcdir}/lib/read1.c -Wall -g -shared -fPIC $(CFLAGS)
|
||||
|
||||
# Build the readmore.so preload library. This overrides the `read'
|
||||
# function, making it try harder to read more at a time. Running the
|
||||
# testsuite with this catches racy tests.
|
||||
readmore.so: lib/read1.c
|
||||
$(ECHO_CC) $(CC) -o $@ ${srcdir}/lib/read1.c -Wall -g -shared -fPIC \
|
||||
$(CFLAGS) -DREADMORE
|
||||
|
||||
# Build the read1 machinery.
|
||||
.PHONY: read1
|
||||
.PHONY: read1 readmore
|
||||
read1: read1.so expect-read1
|
||||
readmore: readmore.so expect-readmore
|
||||
|
||||
# Disable implicit make rules.
|
||||
include $(srcdir)/../disable-implicit-rules.mk
|
||||
|
@ -361,7 +361,7 @@ fail, it can also have the effect of making otherwise failing tests pass.
|
||||
This happens f.i. if the test is trying to match a gdb prompt using an end of
|
||||
input marker "${gdb_prompt} $" and there is output after the gdb prompt. This
|
||||
may either pass or fail in normal operation, but using check-read1 will ensure
|
||||
that it passes.
|
||||
that it passes. Use check-readmore to detect this type of failure.
|
||||
|
||||
Testsuite Configuration
|
||||
***********************
|
||||
|
@ -26,7 +26,7 @@ foo (void)
|
||||
int
|
||||
main ()
|
||||
{
|
||||
alarm (60);
|
||||
alarm (120);
|
||||
|
||||
while (1)
|
||||
foo ();
|
||||
|
@ -21,14 +21,62 @@
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
|
||||
/* Wrap 'read', forcing it to return only one byte at a time, if
|
||||
reading from the terminal. */
|
||||
/* Default READMORE method. */
|
||||
#define READMORE_METHOD_DEFAULT 2
|
||||
|
||||
/* Default READMORE sleep time in miliseconds. */
|
||||
#define READMORE_SLEEP_DEFAULT 10
|
||||
|
||||
/* Helper function. Intialize *METHOD according to environment variable
|
||||
READMORE_METHOD, and *SLEEP according to environment variable
|
||||
READMORE_SLEEP. */
|
||||
|
||||
static void
|
||||
init_readmore (int *method, unsigned int *sleep, FILE **log)
|
||||
{
|
||||
char *env = getenv ("READMORE_METHOD");
|
||||
if (env == NULL)
|
||||
*method = READMORE_METHOD_DEFAULT;
|
||||
else if (strcmp (env, "1") == 0)
|
||||
*method = 1;
|
||||
else if (strcmp (env, "2") == 0)
|
||||
*method = 2;
|
||||
else
|
||||
/* Default. */
|
||||
*method = READMORE_METHOD_DEFAULT;
|
||||
|
||||
env = getenv ("READMORE_SLEEP");
|
||||
if (env == NULL)
|
||||
*sleep = READMORE_SLEEP_DEFAULT;
|
||||
else
|
||||
*sleep = atoi (env);
|
||||
|
||||
env = getenv ("READMORE_LOG");
|
||||
if (env == NULL)
|
||||
*log = NULL;
|
||||
else
|
||||
*log = fopen (env, "w");
|
||||
}
|
||||
|
||||
/* Wrap 'read', and modify it's behaviour using READ1 or READMORE style. */
|
||||
|
||||
ssize_t
|
||||
read (int fd, void *buf, size_t count)
|
||||
{
|
||||
static ssize_t (*read2) (int fd, void *buf, size_t count) = NULL;
|
||||
static FILE *log;
|
||||
int readmore;
|
||||
#ifdef READMORE
|
||||
readmore = 1;
|
||||
#else
|
||||
readmore = 0;
|
||||
#endif
|
||||
static int readmore_method;
|
||||
static unsigned int readmore_sleep;
|
||||
if (read2 == NULL)
|
||||
{
|
||||
/* Use setenv (v, "", 1) rather than unsetenv (v) to work around
|
||||
@ -37,8 +85,88 @@ read (int fd, void *buf, size_t count)
|
||||
for existence from another interp". */
|
||||
setenv ("LD_PRELOAD", "", 1);
|
||||
read2 = dlsym (RTLD_NEXT, "read");
|
||||
if (readmore)
|
||||
init_readmore (&readmore_method, &readmore_sleep, &log);
|
||||
}
|
||||
if (count > 1 && isatty (fd) >= 1)
|
||||
count = 1;
|
||||
|
||||
/* Only modify 'read' behaviour when reading from the terminal. */
|
||||
if (isatty (fd) == 0)
|
||||
goto fallback;
|
||||
|
||||
if (!readmore)
|
||||
{
|
||||
/* READ1. Force read to return only one byte at a time. */
|
||||
return read2 (fd, buf, 1);
|
||||
}
|
||||
|
||||
if (readmore_method == 1)
|
||||
{
|
||||
/* READMORE, method 1. Wait a little before doing a read. */
|
||||
usleep (readmore_sleep * 1000);
|
||||
return read2 (fd, buf, count);
|
||||
}
|
||||
|
||||
if (readmore_method == 2)
|
||||
{
|
||||
/* READMORE, method 2. After doing a read, either return or wait
|
||||
a little and do another read, and so on. */
|
||||
ssize_t res, total;
|
||||
int iteration;
|
||||
int max_iterations = -1;
|
||||
|
||||
total = 0;
|
||||
for (iteration = 1; ; iteration++)
|
||||
{
|
||||
res = read2 (fd, (char *)buf + total, count - total);
|
||||
if (log != NULL)
|
||||
fprintf (log,
|
||||
"READ (%d): fd: %d, COUNT: %zd, RES: %zd, ERRNO: %s\n",
|
||||
iteration, fd, count - total, res,
|
||||
res == -1 ? strerror (errno) : "none");
|
||||
if (res == -1)
|
||||
{
|
||||
if (iteration == 1)
|
||||
{
|
||||
/* Error on first read, report. */
|
||||
total = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
if (total > 0
|
||||
&& (errno == EAGAIN || errno == EWOULDBLOCK || errno == EIO))
|
||||
{
|
||||
/* Ignore error, but don't try anymore reading. */
|
||||
errno = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Other error, report back. */
|
||||
total = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
total += res;
|
||||
if (total == count)
|
||||
/* Buf full, no need to do any more reading. */
|
||||
break;
|
||||
|
||||
/* Handle end-of-file. */
|
||||
if (res == 0)
|
||||
break;
|
||||
|
||||
if (iteration == max_iterations)
|
||||
break;
|
||||
|
||||
usleep (readmore_sleep * 1000);
|
||||
}
|
||||
|
||||
if (log)
|
||||
fprintf (log, "READ returning: RES: %zd, ERRNO: %s\n",
|
||||
total, total == -1 ? strerror (errno) : "none");
|
||||
return total;
|
||||
}
|
||||
|
||||
fallback:
|
||||
/* Fallback, regular read. */
|
||||
return read2 (fd, buf, count);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user