This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[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.*"


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]