aboutsummaryrefslogtreecommitdiff
path: root/gdb/gdbserver/linux-low.c
diff options
context:
space:
mode:
authorDaniel Jacobowitz <drow@false.org>2004-10-16 17:42:00 +0000
committerDaniel Jacobowitz <drow@false.org>2004-10-16 17:42:00 +0000
commitfd5008162e2dc522e4fea16de38a355f7e1a43be (patch)
tree5df2b32d3dbdef7b9996bdbf0b9a408e481774ea /gdb/gdbserver/linux-low.c
parentf6de3c42a31e268abe5f03ea860742829db2f677 (diff)
downloadgdb-fd5008162e2dc522e4fea16de38a355f7e1a43be.zip
gdb-fd5008162e2dc522e4fea16de38a355f7e1a43be.tar.gz
gdb-fd5008162e2dc522e4fea16de38a355f7e1a43be.tar.bz2
* linux-i386-low.c (ps_get_thread_area): New.
* linux-x86-64-low.c (ps_get_thread_area): New. * linux-low.c: Include <sys/syscall.h>. (linux_kill_one_process): Don't kill the first thread here. (linux_kill): Kill the first thread here. (kill_lwp): New function. (send_sigstop, linux_send_signal): Use it. * proc-service.c: Clean up #ifdefs. (fpregset_info): Delete. (ps_lgetregs): Update and enable implementation. (ps_lsetregs, ps_lgetfpregs, ps_lsetfpregs): Remove disabled implementations. * remote-utils.c (struct sym_cache, symbol_cache): New. (input_interrupt): Print a clearer message. (async_io_enabled): New variable. (enable_async_io, disable_async_io): Use it. Update comments. (look_up_one_symbol): Use the symbol cache. * thread-db.c (thread_db_look_up_symbols): New function. (thread_db_init): Update comments. Call thread_db_look_up_symbols.
Diffstat (limited to 'gdb/gdbserver/linux-low.c')
-rw-r--r--gdb/gdbserver/linux-low.c52
1 files changed, 49 insertions, 3 deletions
diff --git a/gdb/gdbserver/linux-low.c b/gdb/gdbserver/linux-low.c
index 5733180..9c41fbb 100644
--- a/gdb/gdbserver/linux-low.c
+++ b/gdb/gdbserver/linux-low.c
@@ -35,6 +35,7 @@
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
+#include <sys/syscall.h>
/* ``all_threads'' is keyed by the LWP ID - it should be the thread ID instead,
however. This requires changing the ID in place when we go from !using_threads
@@ -223,6 +224,13 @@ linux_kill_one_process (struct inferior_list_entry *entry)
struct process_info *process = get_thread_process (thread);
int wstat;
+ /* We avoid killing the first thread here, because of a Linux kernel (at
+ least 2.6.0-test7 through 2.6.8-rc4) bug; if we kill the parent before
+ the children get a chance to be reaped, it will remain a zombie
+ forever. */
+ if (entry == all_threads.head)
+ return;
+
do
{
ptrace (PTRACE_KILL, pid_of (process), 0, 0);
@@ -235,7 +243,21 @@ linux_kill_one_process (struct inferior_list_entry *entry)
static void
linux_kill (void)
{
+ struct thread_info *thread = (struct thread_info *) all_threads.head;
+ struct process_info *process = get_thread_process (thread);
+ int wstat;
+
for_each_inferior (&all_threads, linux_kill_one_process);
+
+ /* See the comment in linux_kill_one_process. We did not kill the first
+ thread in the list, so do so now. */
+ do
+ {
+ ptrace (PTRACE_KILL, pid_of (process), 0, 0);
+
+ /* Make sure it died. The loop is most likely unnecessary. */
+ wstat = linux_wait_for_event (thread);
+ } while (WIFSTOPPED (wstat));
}
static void
@@ -709,6 +731,30 @@ retry:
return ((unsigned char) WSTOPSIG (w));
}
+/* Send a signal to an LWP. For LinuxThreads, kill is enough; however, if
+ thread groups are in use, we need to use tkill. */
+
+static int
+kill_lwp (int lwpid, int signo)
+{
+ static int tkill_failed;
+
+ errno = 0;
+
+#ifdef SYS_tkill
+ if (!tkill_failed)
+ {
+ int ret = syscall (SYS_tkill, lwpid, signo);
+ if (errno != ENOSYS)
+ return ret;
+ errno = 0;
+ tkill_failed = 1;
+ }
+#endif
+
+ return kill (lwpid, signo);
+}
+
static void
send_sigstop (struct inferior_list_entry *entry)
{
@@ -728,7 +774,7 @@ send_sigstop (struct inferior_list_entry *entry)
if (debug_threads)
fprintf (stderr, "Sending sigstop to process %d\n", process->head.id);
- kill (process->head.id, SIGSTOP);
+ kill_lwp (process->head.id, SIGSTOP);
process->sigstop_sent = 1;
}
@@ -1388,10 +1434,10 @@ linux_send_signal (int signum)
struct process_info *process;
process = get_thread_process (current_inferior);
- kill (process->lwpid, signum);
+ kill_lwp (process->lwpid, signum);
}
else
- kill (signal_pid, signum);
+ kill_lwp (signal_pid, signum);
}
/* Copy LEN bytes from inferior's auxiliary vector starting at OFFSET