summaryrefslogtreecommitdiff
path: root/gdb/linux-proc.c
diff options
context:
space:
mode:
authorDaniel Jacobowitz <dan@debian.org>2003-09-07 18:49:44 +0000
committerDaniel Jacobowitz <dan@debian.org>2003-09-07 18:49:44 +0000
commite3e82f623df0e38161b6ec7fce3959af8e602394 (patch)
tree1c31497422970acdf515e976148fd74854312ce0 /gdb/linux-proc.c
parent68c3d55d3c3b6f435291efbdfdfa14de244d5215 (diff)
downloadgdb-e3e82f623df0e38161b6ec7fce3959af8e602394.tar.gz
* lin-lwp.c (detach_callback): Don't call stop_wait_callback.
(stop_wait_callback): Handle !lp->signalled also. (lin_lwp_has_pending, flush_callback): New functions. (lin_lwp_wait): Call flush_callback. * linux-proc.c (linux_proc_add_line_to_sigset): New function. (linux_proc_pending_signals): New function. * linux-nat.h (linux_proc_pending_signals): Add prototype.
Diffstat (limited to 'gdb/linux-proc.c')
-rw-r--r--gdb/linux-proc.c83
1 files changed, 83 insertions, 0 deletions
diff --git a/gdb/linux-proc.c b/gdb/linux-proc.c
index 6d9be056816..2f290c49acb 100644
--- a/gdb/linux-proc.c
+++ b/gdb/linux-proc.c
@@ -35,6 +35,8 @@
#include "cli/cli-decode.h" /* for add_info */
#include "gdb_string.h"
+#include <signal.h>
+
#include "linux-nat.h"
#ifndef O_LARGEFILE
@@ -622,3 +624,84 @@ linux_proc_xfer_memory (CORE_ADDR addr, char *myaddr, int len, int write,
close (fd);
return ret;
}
+
+/* Parse LINE as a signal set and add its set bits to SIGS. */
+
+static void
+linux_proc_add_line_to_sigset (const char *line, sigset_t *sigs)
+{
+ int len = strlen (line) - 1;
+ const char *p;
+ int signum;
+
+ if (line[len] != '\n')
+ error ("Could not parse signal set: %s", line);
+
+ p = line;
+ signum = len * 4;
+ while (len-- > 0)
+ {
+ int digit;
+
+ if (*p >= '0' && *p <= '9')
+ digit = *p - '0';
+ else if (*p >= 'a' && *p <= 'f')
+ digit = *p - 'a' + 10;
+ else
+ error ("Could not parse signal set: %s", line);
+
+ signum -= 4;
+
+ if (digit & 1)
+ sigaddset (sigs, signum + 1);
+ if (digit & 2)
+ sigaddset (sigs, signum + 2);
+ if (digit & 4)
+ sigaddset (sigs, signum + 3);
+ if (digit & 8)
+ sigaddset (sigs, signum + 4);
+
+ p++;
+ }
+}
+
+/* Find process PID's pending signals from /proc/pid/status and set SIGS
+ to match. */
+
+void
+linux_proc_pending_signals (int pid, sigset_t *pending, sigset_t *blocked, sigset_t *ignored)
+{
+ FILE *procfile;
+ char buffer[MAXPATHLEN], fname[MAXPATHLEN];
+ int signum;
+
+ sigemptyset (pending);
+ sigemptyset (blocked);
+ sigemptyset (ignored);
+ sprintf (fname, "/proc/%d/status", pid);
+ procfile = fopen (fname, "r");
+ if (procfile == NULL)
+ error ("Could not open %s", fname);
+
+ while (fgets (buffer, MAXPATHLEN, procfile) != NULL)
+ {
+ /* Normal queued signals are on the SigPnd line in the status
+ file. However, 2.6 kernels also have a "shared" pending queue
+ for delivering signals to a thread group, so check for a ShdPnd
+ line also.
+
+ Unfortunately some Red Hat kernels include the shared pending queue
+ but not the ShdPnd status field. */
+
+ if (strncmp (buffer, "SigPnd:\t", 8) == 0)
+ linux_proc_add_line_to_sigset (buffer + 8, pending);
+ else if (strncmp (buffer, "ShdPnd:\t", 8) == 0)
+ linux_proc_add_line_to_sigset (buffer + 8, pending);
+ else if (strncmp (buffer, "SigBlk:\t", 8) == 0)
+ linux_proc_add_line_to_sigset (buffer + 8, blocked);
+ else if (strncmp (buffer, "SigIgn:\t", 8) == 0)
+ linux_proc_add_line_to_sigset (buffer + 8, ignored);
+ }
+
+ fclose (procfile);
+}