This is the mail archive of the
gdb-patches@sourceware.org
mailing list for the GDB project.
[patch 6/6] Fix $_siginfo content for multiple threads
- From: Jan Kratochvil <jan dot kratochvil at redhat dot com>
- To: gdb-patches at sourceware dot org
- Date: Tue, 27 Jul 2010 00:51:25 +0200
- Subject: [patch 6/6] Fix $_siginfo content for multiple threads
Hi,
and here is a fix of $_siginfo to contain the real signal information. With
the various resubmits of signals across threads I found when I am interested
in $_siginfo it unfortunately contains incorrect information (commonly about
SIGSTOP).
Thanks,
Jan
gdb/
2010-07-26 Jan Kratochvil <jan.kratochvil@redhat.com>
* linux-nat.c (linux_xfer_siginfo): Remove variables pid and siginfo.
New variable siginfop. Use siginfop instead of siginfo. Drop PID
initialization. Drop PTRACE_GETSIGINFO and PTRACE_SETSIGINFO calls.
(linux_nat_get_siginfo): Update the comment.
gdb/testsuite/
2010-07-26 Jan Kratochvil <jan.kratochvil@redhat.com>
* gdb.threads/siginfo-threads.exp (handle SIGUSR1 nostop print pass)
(handle SIGUSR2 nostop print pass): Set them to stop.
(get pid, catch signal $sigcount, signal $sigcount si_signo)
(signal $sigcount si_code is SI_TKILL, signal $sigcount si_pid): New
tests.
--- a/gdb/linux-nat.c
+++ b/gdb/linux-nat.c
@@ -3993,35 +3993,27 @@ linux_xfer_siginfo (struct target_ops *ops, enum target_object object,
const char *annex, gdb_byte *readbuf,
const gdb_byte *writebuf, ULONGEST offset, LONGEST len)
{
- int pid;
- struct siginfo siginfo;
- gdb_byte inf_siginfo[sizeof (struct siginfo)];
+ siginfo_t *siginfop;
+ gdb_byte inf_siginfo[sizeof (*siginfop)];
gdb_assert (object == TARGET_OBJECT_SIGNAL_INFO);
gdb_assert (readbuf || writebuf);
- pid = GET_LWP (inferior_ptid);
- if (pid == 0)
- pid = GET_PID (inferior_ptid);
-
- if (offset > sizeof (siginfo))
+ if (offset > sizeof (*siginfop))
return -1;
- errno = 0;
- ptrace (PTRACE_GETSIGINFO, pid, (PTRACE_TYPE_ARG3) 0, &siginfo);
- if (errno != 0)
- return -1;
+ siginfop = &TARGET_SIGNAL_SIGINFO (inferior_thread ()->stop_signal);
/* When GDB is built as a 64-bit application, ptrace writes into
- SIGINFO an object with 64-bit layout. Since debugging a 32-bit
+ SIGINFOP an object with 64-bit layout. Since debugging a 32-bit
inferior with a 64-bit GDB should look the same as debugging it
with a 32-bit GDB, we need to convert it. GDB core always sees
the converted layout, so any read/write will have to be done
post-conversion. */
- siginfo_fixup (&siginfo, inf_siginfo, 0);
+ siginfo_fixup (siginfop, inf_siginfo, 0);
- if (offset + len > sizeof (siginfo))
- len = sizeof (siginfo) - offset;
+ if (offset + len > sizeof (*siginfop))
+ len = sizeof (*siginfop) - offset;
if (readbuf != NULL)
memcpy (readbuf, inf_siginfo + offset, len);
@@ -4030,12 +4022,7 @@ linux_xfer_siginfo (struct target_ops *ops, enum target_object object,
memcpy (inf_siginfo + offset, writebuf, len);
/* Convert back to ptrace layout before flushing it out. */
- siginfo_fixup (&siginfo, inf_siginfo, 1);
-
- errno = 0;
- ptrace (PTRACE_SETSIGINFO, pid, (PTRACE_TYPE_ARG3) 0, &siginfo);
- if (errno != 0)
- return -1;
+ siginfo_fixup (siginfop, inf_siginfo, 1);
}
return len;
@@ -5778,7 +5765,10 @@ linux_nat_set_siginfo_fixup (struct target_ops *t,
linux_nat_siginfo_fixup = siginfo_fixup;
}
-/* Return the saved siginfo associated with PTID. */
+/* Return the saved siginfo associated with PTID. This siginfo is for the
+ currently detected stop, before it gets presented to the user. Signal gets
+ moved into thread_info->stop_signal later. */
+
struct siginfo *
linux_nat_get_siginfo (ptid_t ptid)
{
--- a/gdb/testsuite/gdb.threads/siginfo-threads.exp
+++ b/gdb/testsuite/gdb.threads/siginfo-threads.exp
@@ -29,9 +29,40 @@ if ![runto_main] {
# `nostop noprint pass' could in some cases report false PASS due to the
# (preempt 'handle') code path.
-gdb_test "handle SIGUSR1 nostop print pass" "Signal\[ \t\]+Stop\[ \t\]+Print\[ \t\]+Pass to program\[ \t\]+Description\r\nSIGUSR1\[ \t\]+No\[ \t\]+Yes\[ \t\]+Yes\[ \t\]+User defined signal 1"
-gdb_test "handle SIGUSR2 nostop print pass" "Signal\[ \t\]+Stop\[ \t\]+Print\[ \t\]+Pass to program\[ \t\]+Description\r\nSIGUSR2\[ \t\]+No\[ \t\]+Yes\[ \t\]+Yes\[ \t\]+User defined signal 2"
+gdb_test "handle SIGUSR1 stop print pass" "Signal\[ \t\]+Stop\[ \t\]+Print\[ \t\]+Pass to program\[ \t\]+Description\r\nSIGUSR1\[ \t\]+Yes\[ \t\]+Yes\[ \t\]+Yes\[ \t\]+User defined signal 1"
+gdb_test "handle SIGUSR2 stop print pass" "Signal\[ \t\]+Stop\[ \t\]+Print\[ \t\]+Pass to program\[ \t\]+Description\r\nSIGUSR2\[ \t\]+Yes\[ \t\]+Yes\[ \t\]+Yes\[ \t\]+User defined signal 2"
gdb_breakpoint [gdb_get_line_number "break-at-exit"]
+set test "get pid"
+gdb_test_multiple "p getpid ()" $test {
+ -re " = (\[0-9\]+)\r\n$gdb_prompt $" {
+ set pid $expect_out(1,string)
+ pass $test
+ }
+}
+
+for {set sigcount 0} {$sigcount < 4} {incr sigcount} {
+ set test "catch signal $sigcount"
+ gdb_test_multiple "continue" $test {
+ -re "Program received signal SIGUSR(\[12\]), User defined signal \[12\]\\.\r\n.*\r\n$gdb_prompt $" {
+ set sigusr $expect_out(1,string)
+ pass $test
+ }
+ }
+
+ if {$sigusr == 1} {
+ set signo 10
+ } else {
+ set signo 12
+ }
+ gdb_test {p $_siginfo.si_signo} " = $signo" "signal $sigcount si_signo"
+ gdb_test {p $_siginfo.si_code} " = -6" "signal $sigcount si_code is SI_TKILL"
+
+ if {[istarget x86_64-*-linux*] && [is_ilp32_target]} {
+ setup_kfail gdb/11842 *-*-*
+ }
+ gdb_test {p $_siginfo._sifields._kill.si_pid} " = $pid" "signal $sigcount si_pid"
+}
+
gdb_continue_to_breakpoint "break-at-exit" ".*break-at-exit.*"