Fix bug 297078 gdbserver signal handling problems caused by diff vki nr/gdb nr and
non reset of "C-ontinued" signal
* To allow vki signame to be used in debuglog:
- pub_core_signals.h : added prototype for Char *VG_(signame)
- m_signals.c : changed static const Char *signame(Int sigNo)
to const Char *VG_(signame)(Int sigNo)
* valgrind-low.c : when the signal to report to gdb has
been reported, clear it so that it is not reported anymore
afterwards.
* m_gdbserver.c: when checking in pass_signals if signal
can be passed without gdb interaction, do a conversion
from vki nr to gdb nr when indexing
(as pass_signals[] is indexed by gdb_nr).
* various gdbserver files:
- used vki_ prefix for some args and variables to clarify
- better debuglog tracing
* modified nlpasssigalrm.vgtest to test SIGCHLD signal
handling followed by a break (to see SIGTRAP is properly
given to gdb).
git-svn-id: svn://svn.valgrind.org/valgrind/trunk@12470 a5019735-40e9-0310-863c-91ae7b9d1cf9
diff --git a/NEWS b/NEWS
index e221491..1f4bd55 100644
--- a/NEWS
+++ b/NEWS
@@ -78,7 +78,8 @@
294190 --vgdb-error=xxx can be out of sync with errors shown to the user
295799 Missing \n with get_vbits in gdbserver when line is % 80 and there are some unaddressable bytes
n-i-bz s390x: Shadow registers can now be examined using vgdb
-
+297078 gdbserver signal handling problems caused by diff vki nr/gdb nr
+ and non reset of "C-ontinued" signal
Release 3.7.0 (5 November 2011)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
diff --git a/coregrind/m_gdbserver/m_gdbserver.c b/coregrind/m_gdbserver/m_gdbserver.c
index 36e0b27..f3d3d50 100644
--- a/coregrind/m_gdbserver/m_gdbserver.c
+++ b/coregrind/m_gdbserver/m_gdbserver.c
@@ -42,6 +42,7 @@
#include "pub_core_libcassert.h"
#include "pub_tool_libcbase.h"
#include "pub_core_libcsignal.h"
+#include "pub_core_signals.h"
#include "pub_tool_machine.h" // VG_(fnptr_to_fnentry)
#include "pub_tool_debuginfo.h"
#include "pub_core_scheduler.h"
@@ -835,9 +836,14 @@
return ret;
}
-Bool VG_(gdbserver_report_signal) (Int sigNo, ThreadId tid)
+Bool VG_(gdbserver_report_signal) (Int vki_sigNo, ThreadId tid)
{
- dlog(1, "signal %d tid %d\n", sigNo, tid);
+ dlog(1, "VG core calling VG_(gdbserver_report_signal) "
+ "vki_nr %d %s gdb_nr %d %s tid %d\n",
+ vki_sigNo, VG_(signame)(vki_sigNo),
+ target_signal_from_host (vki_sigNo),
+ target_signal_to_name(target_signal_from_host (vki_sigNo)),
+ tid);
/* if gdbserver is currently not connected, then signal
is to be given to the process */
@@ -848,19 +854,19 @@
/* if gdb has informed gdbserver that this signal can be
passed directly without informing gdb, then signal is
to be given to the process. */
- if (pass_signals[sigNo]) {
+ if (pass_signals[target_signal_from_host(vki_sigNo)]) {
dlog(1, "pass_signals => pass\n");
return True;
}
/* indicate to gdbserver that there is a signal */
- gdbserver_signal_encountered (sigNo);
+ gdbserver_signal_encountered (vki_sigNo);
/* let gdbserver do some work, e.g. show the signal to the user */
call_gdbserver (tid, signal_reason);
/* ask gdbserver what is the final decision */
- if (gdbserver_deliver_signal (sigNo)) {
+ if (gdbserver_deliver_signal (vki_sigNo)) {
dlog(1, "gdbserver deliver signal\n");
return True;
} else {
diff --git a/coregrind/m_gdbserver/server.c b/coregrind/m_gdbserver/server.c
index 84a2e1b..2736419 100644
--- a/coregrind/m_gdbserver/server.c
+++ b/coregrind/m_gdbserver/server.c
@@ -34,7 +34,7 @@
unsigned long thread_from_wait;
unsigned long old_thread_from_wait;
-int pass_signals[TARGET_SIGNAL_LAST];
+int pass_signals[TARGET_SIGNAL_LAST]; /* indexed by gdb signal nr */
/* for a gdbserver integrated in valgrind, resuming the process consists
in returning the control to valgrind.
@@ -412,7 +412,8 @@
if (to == NULL) to = end;
decode_address (&sig, from, to - from);
pass_signals[(int)sig] = 1;
- dlog(1, "pass_signal %d\n", (int)sig);
+ dlog(1, "pass_signal gdb_nr %d %s\n",
+ (int)sig, target_signal_to_name(sig));
from = to;
if (*from == ';') from++;
}
diff --git a/coregrind/m_gdbserver/server.h b/coregrind/m_gdbserver/server.h
index dc1b128..a88bc03 100644
--- a/coregrind/m_gdbserver/server.h
+++ b/coregrind/m_gdbserver/server.h
@@ -230,19 +230,19 @@
gdbserver by calling call_gdbserver.
On return, call gdbserver_deliver_signal to effectively
deliver the signal or not. */
-extern void gdbserver_signal_encountered (Int sigNo);
+extern void gdbserver_signal_encountered (Int vki_sigNo);
/* between these two calls, call call_gdbserver */
/* If gdbserver_deliver_signal True, then gdb did not ask
to ignore the signal, so signal can be delivered to the guest. */
-extern Bool gdbserver_deliver_signal (Int sigNo);
+extern Bool gdbserver_deliver_signal (Int vki_sigNo);
/* To optimise signal handling, gdb can instruct gdbserver to
- not stop on some signals. In the below, a 1 indicates the signal
+ not stop on some signals. In the below, a 1 indicates the gdb_nr signal
has to be passed directly to the guest, without asking gdb.
A 0 indicates gdb has to be consulted to see if signal has
or has not to be passed. The gdb consultation is to
be done using the above two functions. */
-extern int pass_signals[];
+extern int pass_signals[]; /* indexed by gdb signal nr */
#include "target.h"
diff --git a/coregrind/m_gdbserver/valgrind-low.c b/coregrind/m_gdbserver/valgrind-low.c
index 5d3f708..59f5284 100644
--- a/coregrind/m_gdbserver/valgrind-low.c
+++ b/coregrind/m_gdbserver/valgrind-low.c
@@ -438,17 +438,17 @@
*/
static CORE_ADDR resume_pc;
-static int signal_to_report;
+static int vki_signal_to_report;
-void gdbserver_signal_encountered (Int sigNo)
+void gdbserver_signal_encountered (Int vki_sigNo)
{
- signal_to_report = sigNo;
+ vki_signal_to_report = vki_sigNo;
}
-static int signal_to_deliver;
-Bool gdbserver_deliver_signal (Int sigNo)
+static int vki_signal_to_deliver;
+Bool gdbserver_deliver_signal (Int vki_sigNo)
{
- return sigNo == signal_to_deliver;
+ return vki_sigNo == vki_signal_to_deliver;
}
static
@@ -479,10 +479,12 @@
and with a signal TRAP (i.e. a breakpoint), unless there is
a signal to report. */
*ourstatus = 'T';
- if (signal_to_report == 0)
+ if (vki_signal_to_report == 0)
sig = TARGET_SIGNAL_TRAP;
- else
- sig = target_signal_from_host(signal_to_report);
+ else {
+ sig = target_signal_from_host(vki_signal_to_report);
+ vki_signal_to_report = 0;
+ }
if (vgdb_interrupted_tid != 0)
tst = VG_(get_ThreadState) (vgdb_interrupted_tid);
@@ -523,7 +525,7 @@
C2v(stopped_data_address));
VG_(set_watchpoint_stop_address) ((Addr) 0);
}
- signal_to_deliver = resume_info->sig;
+ vki_signal_to_deliver = resume_info->sig;
stepping = resume_info->step;
resume_pc = (*the_low_target.get_pc) ();
diff --git a/coregrind/m_signals.c b/coregrind/m_signals.c
index 4112c53..f73b8f3 100644
--- a/coregrind/m_signals.c
+++ b/coregrind/m_signals.c
@@ -240,8 +240,6 @@
static void sigvgkill_handler ( Int sigNo, vki_siginfo_t *info,
struct vki_ucontext * );
-static const Char *signame(Int sigNo);
-
/* Maximum usable signal. */
Int VG_(max_signal) = _VKI_NSIG;
@@ -1080,18 +1078,18 @@
bad_signo_reserved:
if (VG_(showing_core_errors)() && !VG_(clo_xml)) {
VG_(umsg)("Warning: ignored attempt to set %s handler in sigaction();\n",
- signame(signo));
+ VG_(signame)(signo));
VG_(umsg)(" the %s signal is used internally by Valgrind\n",
- signame(signo));
+ VG_(signame)(signo));
}
return VG_(mk_SysRes_Error)( VKI_EINVAL );
bad_sigkill_or_sigstop:
if (VG_(showing_core_errors)() && !VG_(clo_xml)) {
VG_(umsg)("Warning: ignored attempt to set %s handler in sigaction();\n",
- signame(signo));
+ VG_(signame)(signo));
VG_(umsg)(" the %s signal is uncatchable\n",
- signame(signo));
+ VG_(signame)(signo));
}
return VG_(mk_SysRes_Error)( VKI_EINVAL );
}
@@ -1272,7 +1270,7 @@
if (VG_(clo_trace_signals))
VG_(dmsg)("delivering signal %d (%s) to thread %d: "
"on ALT STACK (%p-%p; %ld bytes)\n",
- sigNo, signame(sigNo), tid, tst->altstack.ss_sp,
+ sigNo, VG_(signame)(sigNo), tid, tst->altstack.ss_sp,
(UChar *)tst->altstack.ss_sp + tst->altstack.ss_size,
(Word)tst->altstack.ss_size );
@@ -1300,7 +1298,7 @@
}
-static const Char *signame(Int sigNo)
+const Char *VG_(signame)(Int sigNo)
{
static Char buf[20];
@@ -1524,7 +1522,7 @@
VG_(umsg)(
"\n"
"Process terminating with default action of signal %d (%s)%s\n",
- sigNo, signame(sigNo), core ? ": dumping core" : "");
+ sigNo, VG_(signame)(sigNo), core ? ": dumping core" : "");
/* Be helpful - decode some more details about this fault */
if (is_signal_from_kernel(tid, sigNo, info->si_code)) {
@@ -1669,7 +1667,7 @@
if (VG_(clo_trace_signals))
VG_(dmsg)("delivering signal %d (%s):%d to thread %d\n",
- sigNo, signame(sigNo), info->si_code, tid );
+ sigNo, VG_(signame)(sigNo), info->si_code, tid );
if (sigNo == VG_SIGVGKILL) {
/* If this is a SIGVGKILL, we're expecting it to interrupt any
@@ -2186,7 +2184,7 @@
signal and what we should do about it, we really can't
continue unless we get it. */
VG_(umsg)("Signal %d (%s) appears to have lost its siginfo; "
- "I can't go on.\n", sigNo, signame(sigNo));
+ "I can't go on.\n", sigNo, VG_(signame)(sigNo));
VG_(printf)(
" This may be because one of your programs has consumed your ration of\n"
" siginfo structures. For more information, see:\n"
@@ -2338,7 +2336,7 @@
*/
VG_(dmsg)("VALGRIND INTERNAL ERROR: Valgrind received "
"a signal %d (%s) - exiting\n",
- sigNo, signame(sigNo));
+ sigNo, VG_(signame)(sigNo));
VG_(dmsg)("si_code=%x; Faulting address: %p; sp: %#lx\n",
info->si_code, info->VKI_SIGINFO_si_addr,
diff --git a/coregrind/pub_core_signals.h b/coregrind/pub_core_signals.h
index dae2c3f..f2188f1 100644
--- a/coregrind/pub_core_signals.h
+++ b/coregrind/pub_core_signals.h
@@ -40,6 +40,9 @@
/* Highest signal the kernel will let us use */
extern Int VG_(max_signal);
+/* Returns the name of the vki signal sigNo */
+extern const Char *VG_(signame)(Int sigNo);
+
/* Use high signals because native pthreads wants to use low */
#define VG_SIGVGKILL (VG_(max_signal)-0)
#define VG_SIGVGRTUSERMAX (VG_(max_signal)-1)
diff --git a/gdbserver_tests/nlpasssigalrm.stdinB.gdb b/gdbserver_tests/nlpasssigalrm.stdinB.gdb
index ee2b4e1..a8f14c7 100644
--- a/gdbserver_tests/nlpasssigalrm.stdinB.gdb
+++ b/gdbserver_tests/nlpasssigalrm.stdinB.gdb
@@ -2,6 +2,8 @@
target remote | ./vgdb --wait=60 --vgdb-prefix=./vgdb-prefix-nlpasssigalrm
echo vgdb launched process attached\n
monitor v.set vgdb-error 999999
+break passsigalrm.c:43
+break passsigalrm.c:44
#
#
# ensure SIGALRM can be passed directly to the process, without
@@ -14,4 +16,9 @@
# Tell the 2nd can be given directly
handle SIGALRM nostop noprint pass
continue
+# Here, we expect to stop on the breakme
+p breakme
+continue
+p breakme
+continue
quit
diff --git a/gdbserver_tests/nlpasssigalrm.stdoutB.exp b/gdbserver_tests/nlpasssigalrm.stdoutB.exp
index a04d2a1..98eac29 100644
--- a/gdbserver_tests/nlpasssigalrm.stdoutB.exp
+++ b/gdbserver_tests/nlpasssigalrm.stdoutB.exp
@@ -1,3 +1,5 @@
+Breakpoint 1 at 0x........: file passsigalrm.c, line 43.
+Breakpoint 2 at 0x........: file passsigalrm.c, line 44.
Signal Stop Print Pass to program Description
SIGALRM Yes Yes Yes Alarm clock
Continuing.
@@ -6,3 +8,11 @@
Signal Stop Print Pass to program Description
SIGALRM No No Yes Alarm clock
Continuing.
+Breakpoint 1, main (argc=1, argv=0x........) at passsigalrm.c:43
+43 breakme++;
+$1 = 0
+Continuing.
+Breakpoint 2, main (argc=1, argv=0x........) at passsigalrm.c:44
+44 return 0;
+$2 = 1
+Continuing.
diff --git a/gdbserver_tests/passsigalrm.c b/gdbserver_tests/passsigalrm.c
index a625eb6..6493a85 100644
--- a/gdbserver_tests/passsigalrm.c
+++ b/gdbserver_tests/passsigalrm.c
@@ -1,13 +1,16 @@
#include <stdio.h>
#include <signal.h>
#include <unistd.h>
-static int sigalrm_received = 0;
+#include <stdlib.h>
+static int sigalrm_received = 0;
static void sigalrm_handler(int signr)
{
sigalrm_received++;
}
+static int breakme = 0;
+
int main (int argc, char *argv[])
{
struct sigaction sa;
@@ -36,5 +39,7 @@
fprintf (stderr, "wrong 2nd: unexpected value %d sigalrm_received\n",
sigalrm_received);
+ system("../tests/true");
+ breakme++;
return 0;
}