diff --git a/gdb/testsuite/gdb.mi/mi-break.exp b/gdb/testsuite/gdb.mi/mi-break.exp
index c517ce886f..bfbb3d9961 100644
--- a/gdb/testsuite/gdb.mi/mi-break.exp
+++ b/gdb/testsuite/gdb.mi/mi-break.exp
@@ -398,8 +398,6 @@ proc test_explicit_breakpoints {} {
 proc test_break {mi_mode} {
     global srcdir subdir binfile
 
-    mi_gdb_exit
-
     if {$mi_mode == "separate"} {
 	set start_ops "separate-mi-tty"
     } else {
@@ -427,6 +425,8 @@ proc test_break {mi_mode} {
     test_abreak_creation
 
     test_explicit_breakpoints
+
+    mi_gdb_exit
 }
 
 if [gdb_debug_enabled] {
diff --git a/gdb/testsuite/gdb.mi/mi-exec-run.exp b/gdb/testsuite/gdb.mi/mi-exec-run.exp
index eb4e00d881..6cb8810733 100644
--- a/gdb/testsuite/gdb.mi/mi-exec-run.exp
+++ b/gdb/testsuite/gdb.mi/mi-exec-run.exp
@@ -50,8 +50,6 @@ proc test {inftty_mode mi_mode force_fail} {
     global gdb_spawn_id gdb_main_spawn_id mi_spawn_id inferior_spawn_id
     global decimal
 
-    mi_gdb_exit
-
     set start_ops {}
     if {$inftty_mode == "separate"} {
 	lappend start_ops "separate-inferior-tty"
@@ -142,6 +140,8 @@ proc test {inftty_mode mi_mode force_fail} {
 	    switch_gdb_spawn_id $mi_spawn_id
 	}
     }
+
+    mi_gdb_exit
 }
 
 # Create a not-executable copy of the program, in order to exercise
diff --git a/gdb/testsuite/gdb.mi/mi-watch.exp b/gdb/testsuite/gdb.mi/mi-watch.exp
index 23cc178d71..7dea2f735f 100644
--- a/gdb/testsuite/gdb.mi/mi-watch.exp
+++ b/gdb/testsuite/gdb.mi/mi-watch.exp
@@ -143,8 +143,6 @@ proc test_watchpoint_all {mi_mode type} {
 	return
     }
 
-    mi_gdb_exit
-
     if {$mi_mode == "separate"} {
 	set start_ops "separate-mi-tty"
     } else {
@@ -172,6 +170,8 @@ proc test_watchpoint_all {mi_mode type} {
     #test_rwatch_creation_and_listing
     #test_awatch_creation_and_listing
     test_watchpoint_triggering
+
+    mi_gdb_exit
 }
 
 if [gdb_debug_enabled] {
diff --git a/gdb/testsuite/gdb.mi/new-ui-mi-sync.exp b/gdb/testsuite/gdb.mi/new-ui-mi-sync.exp
index 5560a8be96..d019007394 100644
--- a/gdb/testsuite/gdb.mi/new-ui-mi-sync.exp
+++ b/gdb/testsuite/gdb.mi/new-ui-mi-sync.exp
@@ -43,8 +43,6 @@ proc do_test {sync_command} {
     global gdb_spawn_id gdb_main_spawn_id mi_spawn_id inferior_spawn_id
     global gdb_prompt mi_gdb_prompt
 
-    mi_gdb_exit
-
     if {[mi_gdb_start "separate-mi-tty"] != 0} {
 	fail "could not start gdb"
 	return
@@ -113,6 +111,8 @@ proc do_test {sync_command} {
 	mi_gdb_test "" "456\\^.*state=\"stopped\".*" \
 	    "got -thread-info output and thread is stopped"
     }
+
+    mi_gdb_exit
 }
 
 foreach_with_prefix sync-command {"run" "continue"} {
diff --git a/gdb/testsuite/gdb.mi/user-selected-context-sync.exp b/gdb/testsuite/gdb.mi/user-selected-context-sync.exp
index 621b4c5163..992c67ab50 100644
--- a/gdb/testsuite/gdb.mi/user-selected-context-sync.exp
+++ b/gdb/testsuite/gdb.mi/user-selected-context-sync.exp
@@ -385,8 +385,6 @@ proc_with_prefix test_setup { mode } {
 
     set any "\[^\r\n\]*"
 
-    mi_gdb_exit
-
     save_vars { GDBFLAGS } {
 	if { $mode == "non-stop" } {
 	    set GDBFLAGS [concat $GDBFLAGS " -ex \"set non-stop 1\""]
@@ -1277,4 +1275,6 @@ foreach_with_prefix mode { "all-stop" "non-stop" } {
 	test_cli_in_mi_thread $mode $exec_mode
 	test_cli_in_mi_frame $mode $exec_mode
     }
+
+    mi_gdb_exit
 }
diff --git a/gdb/testsuite/lib/gdb.exp b/gdb/testsuite/lib/gdb.exp
index 3a1f053cf8..8bf3a7b461 100644
--- a/gdb/testsuite/lib/gdb.exp
+++ b/gdb/testsuite/lib/gdb.exp
@@ -1523,6 +1523,32 @@ proc gdb_reinitialize_dir { subdir } {
     }
 }
 
+#
+# show msg + a time stamp.
+#
+proc timed_log { msg } {
+    global verbose
+    # Set vvv to 0 if you want to always see such timed logs.
+    set vvv 3
+    if { $verbose >= $vvv } {
+	verbose "$msg [clock format [clock seconds] -format %H:%M:%S]" $vvv
+    }
+}
+
+#
+# There is a quirk encountered in dejagnu/expect/tcl when doing a
+# 'clean GDB quit': when a GDB has created detached inferiors,
+# after GDB has exit (and is defunct), the 'gdb_expect' in
+# default_gdb_exit does not see the GDB 'eof' till the exit of the
+# detached children.  If a child stays alive a long time, then a test
+# can take much longer and/or cause time outs in the default_gdb_exit.
+# The reason for this 'eof wait time' is that the children are keeping
+# the pty opened.
+# So, for tests that are launching such detached processes, either they
+# must be killed before exiting GDB, or the test program must close
+# fd 0/1/2, to ensure the child has closed the pty.
+# See e.g. gdb.base/pie-fork.exp and pie-fork.c.
+
 #
 # gdb_exit -- exit the GDB, killing the target program if necessary
 #
-- 
2.20.1


From af3dc7de0d39266816f0cfc62f1234dd075f886d Mon Sep 17 00:00:00 2001
From: Philippe Waroquiers <philippe.waroquiers@skynet.be>
Date: Sun, 6 Jan 2019 22:12:14 +0100
Subject: [PATCH 2/4] Close fd 0/1/2 in detached processes.

There is a quirk encountered in dejagnu/expect/tcl when doing a
'clean GDB quit': when a GDB has created detached inferiors,
after GDB has exit (and is defunct), the 'gdb_expect' in
default_gdb_exit does not see the GDB 'eof' till the exit of the
detached children.  If a child stays alive a long time, then a test
can take much longer and/or cause time outs in the default_gdb_exit.
The reason for this 'eof wait time' is that the children are keeping
the pty opened.
So, for tests that are launching such detached processes, either they
must be killed before exiting GDB, or the test program must close
fd 0/1/2, to ensure the child has closed the pty.
See e.g. gdb.base/pie-fork.exp qnd pie-fork.c.

gdb/testsuite/ChangeLog

2018-12-24  Philippe Waroquiers  <philippe.waroquiers@skynet.be>

	* gdb.base/dprintf-detach.c (main): Close 0/1/2.
	gdb.base/jit-main.c (MAIN): Likewise.
	gdb.base/pie-fork.c (main): Likewise.
	gdb.base/watchpoint-hw-attach.c (main): Likewise.
	gdb.threads/threadapply.c (main): Likewise.
	gdb.threads/watchpoint-fork-child.c (close_fds): New function
	to close 0/1/2.
	(forkoff): Call close_fds in parent and child case.
---
 gdb/testsuite/gdb.base/dprintf-detach.c           |  4 ++++
 gdb/testsuite/gdb.base/jit-main.c                 |  5 +++++
 gdb/testsuite/gdb.base/pie-fork.c                 |  4 ++++
 gdb/testsuite/gdb.base/watchpoint-hw-attach.c     |  4 ++++
 gdb/testsuite/gdb.threads/threadapply.c           |  5 +++++
 gdb/testsuite/gdb.threads/watchpoint-fork-child.c | 11 +++++++++++
 6 files changed, 33 insertions(+)

diff --git a/gdb/testsuite/gdb.base/dprintf-detach.c b/gdb/testsuite/gdb.base/dprintf-detach.c
index 598243efc9..73a84cf955 100644
--- a/gdb/testsuite/gdb.base/dprintf-detach.c
+++ b/gdb/testsuite/gdb.base/dprintf-detach.c
@@ -28,6 +28,10 @@ main (void)
 {
   int i;
 
+  /* Closing FDs for a fast GDB quit.  See gdb.exp default_gdb_exit.  */
+  close (0);
+  close (1);
+  close (2);
   for (i = 0; i < 30; i++)
     function ();
 }
diff --git a/gdb/testsuite/gdb.base/jit-main.c b/gdb/testsuite/gdb.base/jit-main.c
index c8e177cc99..19dfc6d661 100644
--- a/gdb/testsuite/gdb.base/jit-main.c
+++ b/gdb/testsuite/gdb.base/jit-main.c
@@ -207,6 +207,11 @@ MAIN (int argc, char *argv[])
       __jit_debug_register_code ();
     }
 
+  /* Closing FDs for a fast GDB quit.  See gdb.exp default_gdb_exit.  */
+  close (0);
+  close (1);
+  close (2);
+
   WAIT_FOR_GDB; i = 0;  /* gdb break here 1 */
 
   /* Now unregister them all in reverse order.  */
diff --git a/gdb/testsuite/gdb.base/pie-fork.c b/gdb/testsuite/gdb.base/pie-fork.c
index 519959537d..2171f32bfe 100644
--- a/gdb/testsuite/gdb.base/pie-fork.c
+++ b/gdb/testsuite/gdb.base/pie-fork.c
@@ -28,6 +28,10 @@ break_here (void)
 int
 main ()
 {
+  /* Closing FDs for a fast GDB quit.  See gdb.exp default_gdb_exit.  */
+  close (0);
+  close (1);
+  close (2);
   fork ();
   break_here ();
   return 0;
diff --git a/gdb/testsuite/gdb.base/watchpoint-hw-attach.c b/gdb/testsuite/gdb.base/watchpoint-hw-attach.c
index 50cc3b0458..8d094c7460 100644
--- a/gdb/testsuite/gdb.base/watchpoint-hw-attach.c
+++ b/gdb/testsuite/gdb.base/watchpoint-hw-attach.c
@@ -31,6 +31,10 @@ main (void)
   unsigned int counter = 1;
   int mypid = getpid ();
 
+  /* Closing FDs for a fast GDB quit.  See gdb.exp default_gdb_exit.  */
+  close (0);
+  close (1); /* This makes the below printf fail, but we do not mind.  */
+  close (2);
   /* Wait for the debugger to attach, but not indefinitely so this
      test program is not left hanging around.  */
   for (counter = 0; !should_continue && counter < 100; counter++)
diff --git a/gdb/testsuite/gdb.threads/threadapply.c b/gdb/testsuite/gdb.threads/threadapply.c
index 7bf1f8f759..08e4820ad0 100644
--- a/gdb/testsuite/gdb.threads/threadapply.c
+++ b/gdb/testsuite/gdb.threads/threadapply.c
@@ -35,6 +35,11 @@ int main() {
     void *thread_result;
     long i;
 
+    /* Closing FDs for a fast GDB quit.  See gdb.exp default_gdb_exit.  */
+    close (0);
+    close (1);
+    close (2);
+
     for (i = 0; i < NUM; i++)
       {
 	args[i] = 1; /* Init value.  */
diff --git a/gdb/testsuite/gdb.threads/watchpoint-fork-child.c b/gdb/testsuite/gdb.threads/watchpoint-fork-child.c
index 90c9671c80..f86d5b1c79 100644
--- a/gdb/testsuite/gdb.threads/watchpoint-fork-child.c
+++ b/gdb/testsuite/gdb.threads/watchpoint-fork-child.c
@@ -28,6 +28,15 @@
 
 /* `pid_t' may not be available.  */
 
+static void
+close_fds (void)
+{
+  /* Closing FDs for a fast GDB quit.  See gdb.exp default_gdb_exit.  */
+  close (0);
+  close (1);
+  close (2);
+}
+
 static volatile int usr1_got;
 
 static void
@@ -60,6 +69,7 @@ forkoff (int nr)
       assert (0);
     default:
       printf ("parent%d: %d\n", nr, (int) child);
+      close_fds ();
 
       /* Sleep for a while to possibly get incorrectly ATTACH_THREADed by GDB
 	 tracing the child fork with no longer valid thread/lwp entries of the
@@ -96,6 +106,7 @@ forkoff (int nr)
       _exit (0);
     case 0:
       printf ("child%d: %d\n", nr, (int) getpid ());
+      close_fds ();
 
       /* Let the parent signal us about its success.  Be careful of races.  */
 
-- 
2.20.1


From c50f9dd00b8cf5c8c80e0fec02648af22e2c7557 Mon Sep 17 00:00:00 2001
From: Philippe Waroquiers <philippe.waroquiers@skynet.be>
Date: Sun, 2 Dec 2018 16:18:37 +0100
Subject: [PATCH 3/4] Add FORCE_LOCAL_GDB_QUIT_WAIT testsuite parameter.

This patch helps to run GDB testsuite under valgrind, by ensuring
that the valgrind output completely goes into the gdb.log file
(approach suggested by Pedro on irc).

By default, dejagnu terminates a local GDB by closing the pty
that GDB uses.  GDB then exits directly.

However, when GDB is run in a wrapper/tool (such as valgrind) that
does more output after the end of the test, this way of killing GDB
means the wrapper/tool output is dropped, as the pty on which the
wrapper/tool writes its output will be closed before the tool
has finished producing its results.

testsuite/ChangeLog

2019-01-06  Philippe Waroquiers  <philippe.waroquiers@skynet.be>

	* lib/gdb.exp (default_gdb_exit): If FORCE_LOCAL_GDB_QUIT_WAIT
	is set, terminates GDB by sending an interrupt (in case GDB
	not yet expecting a quit command) then send the quit command,
	and wait for GDB to cause an eof.
        * lib/mi-support.exp (mi_uncatched_gdb_exit): Likewise.
	* README: Describe new FORCE_LOCAL_GDB_QUIT_WAIT variable.
---
 gdb/testsuite/README             | 15 ++++++
 gdb/testsuite/lib/gdb.exp        | 85 +++++++++++++++++++++++++++++++-
 gdb/testsuite/lib/mi-support.exp | 49 +++++++++++++++++-
 3 files changed, 146 insertions(+), 3 deletions(-)

diff --git a/gdb/testsuite/README b/gdb/testsuite/README
index 4795df1f75..40ef3bec6d 100644
--- a/gdb/testsuite/README
+++ b/gdb/testsuite/README
@@ -317,6 +317,21 @@ For example, to turn on gdbserver debugging, you can do:
 
 	make check GDBSERVER_DEBUG="debug,replay"
 
+FORCE_LOCAL_GDB_QUIT_WAIT
+
+In a local setup (GDB running locally), this variable tells dejagnu
+to terminate GDB by sending a quit command to it, and then wait for
+GDB to terminate.  This is a.o. useful when running GDB under valgrind
+to ensure that the valgrind results produced at the end of execution
+(such as the leak search) are properly saved to the gdb.log file.
+Example of usage:
+	make check RUNTESTFLAGS="GDB=gdb_valgrind\ $PWD/gdb FORCE_LOCAL_GDB_QUIT_WAIT=1" FORCE_PARALLEL="1" -j3
+
+
+Note: GDB is best run under valgrind with a bunch of specific options, so you
+might use a wrapper script (e.g. gdb_valgrind) that sets the appropriate
+options to run GDB.
+
 Race detection
 **************
 
diff --git a/gdb/testsuite/lib/gdb.exp b/gdb/testsuite/lib/gdb.exp
index 8bf3a7b461..d44b9fe25e 100644
--- a/gdb/testsuite/lib/gdb.exp
+++ b/gdb/testsuite/lib/gdb.exp
@@ -1554,13 +1554,16 @@ proc timed_log { msg } {
 #
 proc default_gdb_exit {} {
     global GDB
+    global gdb_prompt
     global INTERNAL_GDBFLAGS GDBFLAGS
+    global FORCE_LOCAL_GDB_QUIT_WAIT
     global verbose
     global gdb_spawn_id inferior_spawn_id
     global inotify_log_file
 
     gdb_stop_suppressing_tests
 
+
     if ![info exists gdb_spawn_id] {
 	return
     }
@@ -1593,8 +1596,86 @@ proc default_gdb_exit {} {
 	}
     }
 
-    if ![is_remote host] {
-	remote_close host
+    if {![is_remote host] } {
+	# If FORCE_LOCAL_GDB_QUIT_WAIT, do our best to capture the full output
+	# of the launched GDB.
+	# This is in particular needed when running GDB under valgrind,
+	# as valgrind produces some output after the dejagnu test is
+	# terminated.
+	if { [info exists FORCE_LOCAL_GDB_QUIT_WAIT] } {
+	    set gdb_pid [spawn_id_get_pid $gdb_spawn_id]
+	    timed_log "clean quit $gdb_spawn_id $gdb_pid"
+	    send_gdb "\003"
+	    gdb_expect 30 {
+		-re ".*Quit\r\n$gdb_prompt $" { }
+		-re ".*Quit" { }
+		timeout { fail "force quit interrupt timeout" }
+		eof { }
+	    }
+
+	    timed_log "before quit"
+	    send_gdb "quit\n"
+	    set sigterm_done 0
+	    gdb_expect 30 {
+		-re "y or n.*" {
+		    send_gdb "y\n"
+		    exp_continue
+		}
+		-re "DOSEXIT code" { }
+		-re "Remote connection closed" {
+		    # This is needed e.g. for gdb.server/server-exec-info.exp.
+		    # This test calls monitor exit, which causes gdbserver
+		    # to kill the process and exit after showing the msg:
+		    #
+		    # Killing process(es): 32498
+		    #
+		    # But after that, GDB shows the below:
+		    #
+		    # (gdb) monitor exit
+		    # (gdb) quit
+		    # A debugging session is active.
+		    #
+		    #	Inferior 1 [process 32498] will be killed.
+		    #
+		    # Quit anyway? (y or n) y
+		    # Remote connection closed
+		    # (gdb)
+		    #
+		    # So GDB has not understood clearly that the process
+		    # has been killed, and does not obey the quit anyway ???
+		    send_gdb "quit\n"
+		    exp_continue
+		}
+		eof { timed_log "eof" }
+		timeout {
+		    # In case a clean quit does time out, let's kill GDB.
+		    # When running GDB under valgrind + gdb.multi/multi-arch-exec.exp
+		    # and the computer is highly loaded (e.g. running with -j X with
+		    # X > nr_cores), the test blocks and kill -TERM does not kill GDB
+		    # for unclear reasons : when this happens, the inferior is in state
+		    # D (Disk sleep).  So, in case SIGTERM does not work, use SIGKILL
+		    # to let the testsuite finish under valgrind.
+		    if  { $sigterm_done == 0 } {
+			fail "force quit timeout"
+			set gdb_pid [spawn_id_get_pid $gdb_spawn_id]
+			remote_exec host "kill -TERM $gdb_pid"
+			set sigterm_done 1
+			exp_continue
+		    } else {
+			fail "force quit timeout (KILL)"
+			set gdb_pid [spawn_id_get_pid $gdb_spawn_id]
+			remote_exec host "kill -KILL $gdb_pid"
+		    }
+		}
+	    }
+	    if [info exists gdb_spawn_id] {
+		timed_log "before wait"
+		wait -i $gdb_spawn_id
+		timed_log "after wait"
+	    }
+	} else {
+	    remote_close host
+	}
     }
     unset gdb_spawn_id
     unset inferior_spawn_id
diff --git a/gdb/testsuite/lib/mi-support.exp b/gdb/testsuite/lib/mi-support.exp
index dcb472b1d6..328f0c9b53 100644
--- a/gdb/testsuite/lib/mi-support.exp
+++ b/gdb/testsuite/lib/mi-support.exp
@@ -55,6 +55,8 @@ proc mi_gdb_exit {} {
 proc mi_uncatched_gdb_exit {} {
     global GDB
     global INTERNAL_GDBFLAGS GDBFLAGS
+    global FORCE_LOCAL_GDB_QUIT_WAIT
+    global async
     global verbose
     global gdb_spawn_id gdb_main_spawn_id
     global mi_spawn_id inferior_spawn_id
@@ -91,7 +93,52 @@ proc mi_uncatched_gdb_exit {} {
     }
 
     if ![is_remote host] {
-	remote_close host
+	# The logic here should be similar to gdb.exp (default_gdb_exit).
+	# See comments/explanations in gdb.exp.
+
+	if { [info exists FORCE_LOCAL_GDB_QUIT_WAIT] } {
+
+	    # # Send the interrupt request.
+	    # if { $async } {
+	    # 	mi_gdb_test "888-exec-interrupt" "888\\^done" "interrupt"
+	    # } else {
+	    # 	send_gdb "\003"
+	    # }
+	    # mi_expect_interrupt
+	    # ??? no idea how to properly interrupt in mi mode.
+	    # ??? and should we interrupt in mi mode ?
+
+	    # Some mi tests (such as as mi-watch.exp) have both a
+	    # 'normal UI' and a separate 'mi' UI. In such a case,
+	    # the 'eof' is only detected on $gdb_main_spawn_id.
+	    # Without switching to $gdb_main_spawn_id, we get a timeout error.
+	    # Also, when using such a separate mi UI, the pid of $mi_spawn_id
+	    # is 0, so in case of timeout, better kill the main pid.
+
+	    send_gdb "999-gdb-exit\n"
+	    gdb_expect 30 {
+		-re "y or n.*" {
+		    send_gdb "y\n"
+		    exp_continue
+		}
+		-re "Undefined command.*$gdb_prompt $" {
+		    send_gdb "quit\n"
+		    exp_continue
+		}
+		-re "DOSEXIT code" { }
+		-i $gdb_main_spawn_id
+		eof { }
+		timeout {
+		    fail "mi force quit timeout"
+		    set gdb_pid [spawn_id_get_pid $gdb_main_spawn_id]
+		    remote_exec host "kill -TERM $gdb_pid"
+		}
+	    }
+	    # Without the below wait, we have lingering gdb defunct processes.
+	    wait -i $gdb_main_spawn_id
+	} else {
+	    remote_close host
+	}
     }
     unset gdb_spawn_id
     unset gdb_main_spawn_id
-- 
2.20.1


From f9d3aef8e97fdaf8983d8770e56da0869b762a17 Mon Sep 17 00:00:00 2001
From: Philippe Waroquiers <philippe.waroquiers@skynet.be>
Date: Thu, 19 Sep 2019 21:12:38 +0200
Subject: [PATCH 4/4] Various scripts (not ok to merge) to help running GDB
 tests under valgrind

A.o. contains some hardcoded dirname iso of GDB relative paths ...
---
 gdb/contrib/gdb_rerun_test             | 100 +++++++++++
 gdb/contrib/gdb_valgrind               |  83 +++++++++
 gdb/contrib/gdb_valgrind_memcheck.supp | 230 +++++++++++++++++++++++++
 3 files changed, 413 insertions(+)
 create mode 100755 gdb/contrib/gdb_rerun_test
 create mode 100755 gdb/contrib/gdb_valgrind
 create mode 100644 gdb/contrib/gdb_valgrind_memcheck.supp

diff --git a/gdb/contrib/gdb_rerun_test b/gdb/contrib/gdb_rerun_test
new file mode 100755
index 0000000000..b1c94b1c58
--- /dev/null
+++ b/gdb/contrib/gdb_rerun_test
@@ -0,0 +1,100 @@
+#! /bin/sh
+
+# rerun one or more gdb tests
+# Usage:
+#   gdb_rerun_test [-j X] <other usages>
+#     -jX means to use X cpus to run the tests (default 1).
+#
+#   gdb_rerun_test [-j X] [-m [ADDITIONAL_VALGRIND_OPTS...]] [TESTS_TO_RERUN...]
+#     -m option means to run under valgrind/memcheck
+#         By default, reruns all tests.
+#         Note: this automatically uses  FORCE_LOCAL_GDB_QUIT_WAIT=1
+#
+#   gdb_rerun_test [-j X] -s [TESTS_TO_RERUN...]
+#      -s option means to run gdb under strace -o v.out
+#         Note: this automatically uses  FORCE_LOCAL_GDB_QUIT_WAIT=1
+#
+#   gdb_rerun_test [-j X] -d [TESTS_TO_RERUN...]
+#      -d means to activate the tcl --debug option
+#
+#   gdb_rerun_test [-j X] -f [TESTS_TO_RERUN...]
+#     -f option means to run with FORCE_LOCAL_GDB_QUIT_WAIT=1
+#
+#   gdb_rerun_test [-j X] [TESTS_TO_RERUN...]
+#     Re-runs all or the specified tests.
+#
+# e.g.
+#    gdb_rerun_test -m gdb.base/break-always.exp
+#    gdb_rerun_test -m "gdb.base/info_qt.exp gdb.ada/info_auto_lang.exp"
+#    gdb_rerun_test -j 3 -m "$(cd ../obvious/gdb/testsuite; echo */*break*exp)"
+
+if [ -d gdb/testsuite ]
+then
+    RESDIR=gdb/
+    cd gdb
+elif [ -d testsuite ]
+then
+    RESDIR=""
+elif [ $(basename $PWD) = testsuite ]
+then
+    RESDIR=../ 
+    cd ..
+else
+    echo "no idea where to go in $PWD to rerun " "$@"
+    exit 1
+fi
+
+if [ ! -f  testsuite/gdb.sum.ref ]
+then
+    mv testsuite/gdb.sum testsuite/gdb.sum.ref
+    mv testsuite/gdb.log testsuite/gdb.log.ref
+fi
+if [ "$1" = "-j"  ]
+then
+   JOPT="$1 $2"
+   shift
+   shift
+else
+   JOPT="-j 1"
+fi
+    
+if [ "$1" = "-m"  ]
+then
+    shift
+    export GDB_VALGRIND_OPTS="$GDB_VALGRIND_OPTS"
+    while :
+    do
+        case $1 in
+            -*) GDB_VALGRIND_OPTS="$GDB_VALGRIND_OPTS $1"
+                # echo found arg $1
+                shift
+                ;;
+            *)  break
+                ;;
+        esac
+    done
+    # You can add backslash --init-command=<somefile> after $PWD/gdb if special GDB actions are needed.
+    make check $JOPT RUNTESTFLAGS="GDB=gdb_valgrind\ $PWD/gdb FORCE_LOCAL_GDB_QUIT_WAIT=1" FORCE_PARALLEL="1" TESTS="$@" 
+elif [ "$1" = "-s"  ]
+then
+    shift
+    make $JOPT check RUNTESTFLAGS="GDB=strace\ -o\ v.out\ $PWD/gdb FORCE_LOCAL_GDB_QUIT_WAIT=1" TESTS="$@"
+elif [ "$1" = "-d"  ]
+then
+    shift
+    make $JOPTcheck RUNTESTFLAGS="FORCE_LOCAL_GDB_QUIT_WAIT=1 --debug" TESTS="$@"
+    # can also add --strace 10 to see the tcl code.
+elif [ "$1" = "-f"  ]
+then
+    shift
+    make $JOPT check RUNTESTFLAGS="FORCE_LOCAL_GDB_QUIT_WAIT=1" TESTS="$@"
+else
+    make $JOPT check TESTS="$@"
+fi
+
+echo "look results in ${RESDIR}testsuite/gdb.rerun.sum gemacs ${RESDIR}testsuite/gdb.rerun.log &"
+mv testsuite/gdb.sum testsuite/gdb.rerun.sum
+mv testsuite/gdb.log testsuite/gdb.rerun.log
+
+mv testsuite/gdb.sum.ref testsuite/gdb.sum
+mv testsuite/gdb.log.ref testsuite/gdb.log
diff --git a/gdb/contrib/gdb_valgrind b/gdb/contrib/gdb_valgrind
new file mode 100755
index 0000000000..c149a24c73
--- /dev/null
+++ b/gdb/contrib/gdb_valgrind
@@ -0,0 +1,83 @@
+#! /bin/bash
+
+#  gdb_valgrind helper script, to run GDB under valgrind.
+#
+#  Usage:    gdb_valgrind  [additional_valgrind_args...] <path_to_your_gdb>/gdb  [gdb_args...]
+
+
+# I use lvalgrind to point at the very latest git valgrind version.
+# Use it if found in PATH.
+which lvalgrind > /dev/null
+if [[ $? -eq 0 ]]
+then
+    my_valgrind=lvalgrind
+else
+    my_valgrind=valgrind
+fi
+
+
+# We do not want to run GDB under valgrind just to get GDB version,
+# so detect this special case:
+prog=""
+for lastarg in $@
+do
+    if [[ $prog == "" && "$lastarg"  != -* ]]
+    then
+        prog=$lastarg
+    fi
+done
+if [[ "$lastarg"  == "--version" ]]
+then
+    $my_valgrind --version
+    $prog --version
+    exit 0
+fi
+
+# Allowing to add or override valgrind options ...
+GDB_VALGRIND_OPTS="$GDB_VALGRIND_OPTS"
+
+export PYTHONMALLOC=malloc
+exec setarch $(arch) --addr-no-randomize $my_valgrind \
+  --memcheck:suppressions=/home/philippe/python/rel/Python-3.7.4/Misc/valgrind-python.supp \
+  --memcheck:suppressions=/home/philippe/penv/bin/gdb_valgrind_memcheck.supp \
+  --memcheck:leak-check=full --memcheck:show-leak-kinds=definite \
+  --error-markers=VALGRIND_GDB_ERROR_BEGIN,VALGRIND_GDB_ERROR_END \
+  --num-callers=40 --trace-children=no --child-silent-after-fork=yes \
+  $GDB_VALGRIND_OPTS "$@"
+
+
+# To run all tests under valgrind:
+#     cd gdb  # to be in build_xxxxx/gdb
+#     make check RUNTESTFLAGS="GDB=gdb_valgrind\ $PWD/gdb FORCE_LOCAL_GDB_QUIT_WAIT=1" FORCE_PARALLEL="1" -j3
+
+
+# You might want to add as additional valgrind arguments:
+# 
+#     --track-origins=yes
+# to chase a nasty 'use of uninitialised' bug.
+#
+#     --vgdb-error=1 # or other number
+# to debug GDB when valgrind detects an error
+# (you better suspend expect when you debug GDB, to avoid having expect timeout-ing GDB)
+#
+#    --gen-suppressions=all --log-file=supp.out
+# to generate suppression entries.
+
+
+
+# You might need to edit <build_dir>/gdb/testsuite/site.exp and add at the end:
+#     set gdb_test_timeout 120
+# if you have timeouts ...
+
+
+
+# To see 'non leaks (the more severe?)' errors:
+#     grep -n -A1 -ie '== VALGRIND_GDB_ERROR_BEGIN' $(find . -name 'gdb.log' | grep -v testsuite/gdb.log) | grep -v -e definitely -e ERROR_BEGIN -e --
+#
+# To see all tests definitely leaking, sorted by most blocked leaked last:
+#     grep -n -e 'definitely lost: ' -e 'indirectly lost:' $(find . -name 'gdb.log' | grep -v testsuite/gdb.log) |  grep -v -e ' 0 bytes' | sort -n -k7 -k4 | more
+#
+# To get the first line of all errors:
+#     grep -n -A1 -ie '== VALGRIND_GDB_ERROR_BEGIN' $(find . -name 'gdb.log' | grep -v testsuite/gdb.log) | grep -v -e ERROR_BEGIN -e --
+
+# ---------------- end gdb_valgrind
diff --git a/gdb/contrib/gdb_valgrind_memcheck.supp b/gdb/contrib/gdb_valgrind_memcheck.supp
new file mode 100644
index 0000000000..ae915633b5
--- /dev/null
+++ b/gdb/contrib/gdb_valgrind_memcheck.supp
@@ -0,0 +1,230 @@
+# Suppression entries when running GDB under valgrind+memcheck
+# based on a run on Debian/x86_64.
+
+# GDB PR 24980
+# ==22059== VALGRIND_GDB_ERROR_BEGIN
+# ==22059== Conditional jump or move depends on uninitialised value(s)
+# ==22059==    at 0x773EE4: rl_redisplay (display.c:710)
+# ==22059==    by 0x760416: readline_internal_setup (readline.c:447)
+# ==22059==    by 0x7790AF: _rl_callback_newline (callback.c:100)
+# ==22059==    by 0x545A67: gdb_rl_callback_handler_install(char const*) (event-top.c:319)
+# ==22059==    by 0x545BDE: display_gdb_prompt(char const*) (event-top.c:409)
+# ==22059==    by 0x5E6AC2: captured_command_loop() (main.c:328)
+# ==22059==    by 0x5E79A4: captured_main (main.c:1171)
+# ==22059==    by 0x5E79A4: gdb_main(captured_main_args*) (main.c:1186)
+# ==22059==    by 0x4122D4: main (gdb.c:32)
+# ==22059== 
+{
+   readline PR 24980/cond
+   Memcheck:Cond
+   fun:rl_redisplay
+   fun:readline_internal_setup
+}
+
+
+
+#################################### Leak suppressions.
+
+#  ui m_gdb_stdout and m_gdb_stderr of ui::ui are leaked (several times).
+#  ----------------------------------------------------------------------
+#
+#  A first value is allocated when the main_ui is created at this stacktrace:
+# ==14033== VALGRIND_GDB_ERROR_BEGIN
+# ==14033== 24 bytes in 1 blocks are definitely lost in loss record 346 of 3,164
+# ==14033==    at 0x4C2C48C: operator new(unsigned long) (vg_replace_malloc.c:334)
+# ==14033==    by 0x664941: ui::ui(_IO_FILE*, _IO_FILE*, _IO_FILE*) (top.c:269)
+# ==14033==    by 0x552131: captured_main_1 (main.c:521)
+# ==14033==    by 0x552131: captured_main (main.c:1167)
+# ==14033==    by 0x552131: gdb_main(captured_main_args*) (main.c:1193)
+# ==14033==    by 0x29B317: main (gdb.c:32)
+# ==14033== 
+# ==14033== VALGRIND_GDB_ERROR_END
+{
+   definite_leak/ui::ui struct ui_file/allocated at startup in main_ui
+   Memcheck:Leak
+   match-leak-kinds: definite
+   fun:_Znwm
+   fun:_ZN2uiC1EP8_IO_FILES1_S1_
+   fun:captured_main_1
+   fun:captured_main
+   fun:_Z8gdb_mainP18captured_main_args
+   fun:main
+}
+# These are then leaked when gdb_setup_readline is called:
+# the gdb_stdout/gdb_stderr are replaced
+# by    new stdio_file (ui->outstream/errstream);
+# Note: gdb_stdout/gdb_stderr are macros defined in
+# calling functions current_ui_gdb_stdout/stderr _ptr generated @top.c:103:
+#   e.g.  (*current_ui_gdb_stdout_ptr ())
+# Previous values are leaked.  If freeing the previous values, it causes
+# dangling pointers with mi-interpreter.
+# The logic of ui, streams, and gdb_stdout/gdb_stderr is really mysterious
+# to me.
+
+# Similarly, other places allocating a ui will have their 'struct ui_file'
+# leaked:
+# ==23079==    at 0x4C2C4CC: operator new(unsigned long) (vg_replace_malloc.c:344)
+# ==23079==    by 0x66D5E1: ui::ui(_IO_FILE*, _IO_FILE*, _IO_FILE*) (top.c:269)
+# ==23079==    by 0x66D829: new_ui_command(char const*, int) (top.c:355)
+{
+   definite_leak/ui::ui struct ui_file/allocated by new-ui command
+   Memcheck:Leak
+   match-leak-kinds: definite
+   fun:_Znwm
+   fun:_ZN2uiC1EP8_IO_FILES1_S1_
+   fun:_ZL14new_ui_commandPKci
+}
+
+# And then, the struct ui_file allocated in gdb_setup_readline will themselves
+# be leaked, if gdb_setup_readline is called repetitively for the same ui;
+# ==23079==    at 0x4C2C4CC: operator new(unsigned long) (vg_replace_malloc.c:344)
+# ==23079==    by 0x4B8FF1: gdb_setup_readline(int) (event-top.c:1183)
+{
+   definite_leak/ui::ui struct ui_file/allocated by gdb_setup_readline
+   Memcheck:Leak
+   match-leak-kinds: definite
+   fun:_Znwm
+   fun:_Z18gdb_setup_readlinei
+}
+
+# Each time a user-defined command is created, the name is xstrdup-ed.
+# Not a leak, unless this user-defined command is redefined.
+# The name cannot easily be xfree-d, as do_define_command can redefine
+# builtin commands and/or builtin aliases, or already redefined commands
+# or aliases.  Sometimes, these commands were initially defined with a
+# static string.
+# So, no easy way to see if name should or should not be freed.
+# The proper solution would be to always duplicate the name in add_cmd,
+# and always free it there, if add_cmd sees we redefine a command.
+# Not worth doing, as nobody will re-define thousands of commands.
+# ==12800==    at 0x4C2BE6D: malloc (vg_replace_malloc.c:309)
+# ==12800==    by 0x41B967: xmalloc (common-utils.c:44)
+# ==12800==    by 0x76D799: xstrdup (xstrdup.c:34)
+# ==12800==    by 0x410211: do_define_command(char const*, int, std::shared_ptr<command_line> const*) (cli-script.c:1435)
+{
+   definite_leak/ui::ui struct ui_file/allocated by gdb_setup_readline
+   Memcheck:Leak
+   match-leak-kinds: definite
+   fun:malloc
+   fun:xmalloc
+   fun:xstrdup
+   fun:_ZL17do_define_commandPKciPKSt10shared_ptrI12command_lineE
+}
+
+#################################### Error suppressions.
+
+####### Guile Garbage collection errors.
+
+{
+   GC_push_all_eager/cond
+   Memcheck:Cond
+   fun:GC_push_all_eager
+}
+
+{
+   GC_mark_from/value8
+   Memcheck:Value8
+   fun:GC_mark_from
+}
+
+{
+   GC_mark_from/cond
+   Memcheck:Cond
+   fun:GC_mark_from
+}
+
+{
+   GC_mark_and_push_stack/value8
+   Memcheck:Value8
+   fun:GC_mark_and_push_stack
+}
+
+{
+   GC_mark_and_push_stack/cond
+   Memcheck:Cond
+   fun:GC_mark_and_push_stack
+}
+
+{
+   libunistring_freea_CC_scm_from_stringn/cond
+   Memcheck:Cond
+   fun:libunistring_freea
+   fun:libunistring_mem_iconveha
+   fun:u32_conv_from_encoding
+   fun:scm_from_stringn
+}
+
+{
+   libunistring_freea_CC_scm_ungetc/cond
+   Memcheck:Cond
+   fun:libunistring_freea
+   fun:libunistring_mem_iconveha
+   fun:u32_conv_to_encoding
+   fun:scm_ungetc
+}
+
+{
+   GC_find_header/cond
+   Memcheck:Cond
+   fun:GC_find_header
+}
+
+{
+   GC_find_header/value8
+   Memcheck:Value8
+   fun:GC_find_header
+}
+
+
+
+
+{
+   GC_base/value8
+   Memcheck:Value8
+   fun:GC_base
+}
+
+{
+   GC_base/cond
+   Memcheck:Cond
+   fun:GC_base
+}
+
+{
+   GC_header_cache_miss/value8
+   Memcheck:Value8
+   fun:GC_header_cache_miss
+}
+
+{
+   GC_header_cache_miss/cond
+   Memcheck:Cond
+   fun:GC_header_cache_miss
+}
+
+{
+   GC_add_to_black_list_normal/value8
+   Memcheck:Value8
+   fun:GC_add_to_black_list_normal
+}
+
+{
+   GC_add_to_black_list_stack/value8
+   Memcheck:Value8
+   fun:GC_add_to_black_list_stack
+}
+
+{
+   GC_is_black_listed/cond
+   Memcheck:Cond
+   fun:GC_is_black_listed
+}
+
+{
+   GC_promote_black_lists/cond
+   Memcheck:Cond
+   fun:GC_promote_black_lists
+}
+
+
+# ---------------- end gdb_valgrind_memcheck.supp
