e76126e8d1
Here's an example, with the new test: gdbserver :9999 gdb.threads/kill gdb gdb.threads/kill (gdb) b 52 Breakpoint 1 at 0x4007f4: file kill.c, line 52. Continuing. Breakpoint 1, main () at kill.c:52 52 return 0; /* set break here */ (gdb) k Kill the program being debugged? (y or n) y gdbserver :9999 gdb.threads/kill Process gdb.base/watch_thread_num created; pid = 9719 Listening on port 1234 Remote debugging from host 127.0.0.1 Killing all inferiors Segmentation fault (core dumped) Backtrace: (gdb) bt #0 0x00000000004068a0 in find_inferior (list=0x66b060 <all_threads>, func=0x427637 <kill_one_lwp_callback>, arg=0x7fffffffd3fc) at src/gdb/gdbserver/inferiors.c:199 #1 0x00000000004277b6 in linux_kill (pid=15708) at src/gdb/gdbserver/linux-low.c:966 #2 0x000000000041354d in kill_inferior (pid=15708) at src/gdb/gdbserver/target.c:163 #3 0x00000000004107e9 in kill_inferior_callback (entry=0x6704f0) at src/gdb/gdbserver/server.c:2934 #4 0x0000000000406522 in for_each_inferior (list=0x66b050 <all_processes>, action=0x4107a6 <kill_inferior_callback>) at src/gdb/gdbserver/inferiors.c:57 #5 0x0000000000412377 in process_serial_event () at src/gdb/gdbserver/server.c:3767 #6 0x000000000041267c in handle_serial_event (err=0, client_data=0x0) at src/gdb/gdbserver/server.c:3880 #7 0x00000000004189ff in handle_file_event (event_file_desc=4) at src/gdb/gdbserver/event-loop.c:434 #8 0x00000000004181c6 in process_event () at src/gdb/gdbserver/event-loop.c:189 #9 0x0000000000418f45 in start_event_loop () at src/gdb/gdbserver/event-loop.c:552 #10 0x0000000000411272 in main (argc=3, argv=0x7fffffffd8d8) at src/gdb/gdbserver/server.c:3283 The problem is that linux_wait_for_event deletes lwps that have exited (even those not passed in as lwps of interest), while the lwp/thread list is being walked on with find_inferior. find_inferior can handle the current iterated inferior being deleted, but not others. When killing lwps, we don't really care about any of the pending status handling of linux_wait_for_event. We can just waitpid the lwps directly, which is also what GDB does (see linux-nat.c:kill_wait_callback). This way the lwps are not deleted while we're walking the list. They'll be deleted by linux_mourn afterwards. This crash triggers several times when running the testsuite against GDBserver with the native-gdbserver board (target remote), but as GDB can't distinguish between GDBserver crashing and "kill" being sucessful, as in both cases the connection is closed (the 'k' packet doesn't require a reply), and the inferior is gone, that results in no FAIL. The patch adds a generic test that catches the issue with extended-remote mode (and works fine with native testing too). Here's how it fails with the native-extended-gdbserver board without the fix: (gdb) info threads Id Target Id Frame 6 Thread 15367.15374 0x000000373bcbc98d in nanosleep () at ../sysdeps/unix/syscall-template.S:81 5 Thread 15367.15373 0x000000373bcbc98d in nanosleep () at ../sysdeps/unix/syscall-template.S:81 4 Thread 15367.15372 0x000000373bcbc98d in nanosleep () at ../sysdeps/unix/syscall-template.S:81 3 Thread 15367.15371 0x000000373bcbc98d in nanosleep () at ../sysdeps/unix/syscall-template.S:81 2 Thread 15367.15370 0x000000373bcbc98d in nanosleep () at ../sysdeps/unix/syscall-template.S:81 * 1 Thread 15367.15367 main () at .../gdb.threads/kill.c:52 (gdb) kill Kill the program being debugged? (y or n) y Remote connection closed ^^^^^^^^^^^^^^^^^^^^^^^^ (gdb) FAIL: gdb.threads/kill.exp: kill Extended remote should remain connected after the kill. gdb/gdbserver/ 2014-07-11 Pedro Alves <palves@redhat.com> * linux-low.c (kill_wait_lwp): New function, based on kill_one_lwp_callback, but use my_waitpid directly. (kill_one_lwp_callback, linux_kill): Use it. gdb/testsuite/ 2014-07-11 Pedro Alves <palves@redhat.com> * gdb.threads/kill.c: New file. * gdb.threads/kill.exp: New file. |
||
---|---|---|
.. | ||
attach-into-signal.c | ||
attach-into-signal.exp | ||
attach-stopped.c | ||
attach-stopped.exp | ||
bp_in_thread.c | ||
bp_in_thread.exp | ||
clone-new-thread-event.c | ||
clone-new-thread-event.exp | ||
corethreads.c | ||
corethreads.exp | ||
create-fail.c | ||
create-fail.exp | ||
current-lwp-dead.c | ||
current-lwp-dead.exp | ||
dlopen-libpthread-lib.c | ||
dlopen-libpthread.c | ||
dlopen-libpthread.exp | ||
execl.c | ||
execl.exp | ||
execl1.c | ||
fork-child-threads.c | ||
fork-child-threads.exp | ||
fork-thread-pending.c | ||
fork-thread-pending.exp | ||
gcore-thread.exp | ||
hand-call-in-threads.c | ||
hand-call-in-threads.exp | ||
ia64-sigill.c | ||
ia64-sigill.exp | ||
info-threads-cur-sal-2.c | ||
info-threads-cur-sal.c | ||
info-threads-cur-sal.exp | ||
interrupted-hand-call.c | ||
interrupted-hand-call.exp | ||
kill.c | ||
kill.exp | ||
killed.c | ||
killed.exp | ||
leader-exit.c | ||
leader-exit.exp | ||
linux-dp.c | ||
linux-dp.exp | ||
local-watch-wrong-thread.c | ||
local-watch-wrong-thread.exp | ||
Makefile.in | ||
manythreads.c | ||
manythreads.exp | ||
multi-create.c | ||
multi-create.exp | ||
multiple-step-overs.c | ||
multiple-step-overs.exp | ||
no-unwaited-for-left.c | ||
no-unwaited-for-left.exp | ||
non-ldr-exc-1.c | ||
non-ldr-exc-1.exp | ||
non-ldr-exc-2.c | ||
non-ldr-exc-2.exp | ||
non-ldr-exc-3.c | ||
non-ldr-exc-3.exp | ||
non-ldr-exc-4.c | ||
non-ldr-exc-4.exp | ||
pending-step.c | ||
pending-step.exp | ||
print-threads.c | ||
print-threads.exp | ||
pthread_cond_wait.c | ||
pthread_cond_wait.exp | ||
pthreads.c | ||
pthreads.exp | ||
reconnect-signal.c | ||
reconnect-signal.exp | ||
schedlock.c | ||
schedlock.exp | ||
siginfo-threads.c | ||
siginfo-threads.exp | ||
signal-while-stepping-over-bp-other-thread.c | ||
signal-while-stepping-over-bp-other-thread.exp | ||
sigstep-threads.c | ||
sigstep-threads.exp | ||
sigthread.c | ||
sigthread.exp | ||
staticthreads.c | ||
staticthreads.exp | ||
step-over-lands-on-breakpoint.c | ||
step-over-lands-on-breakpoint.exp | ||
step-over-trips-on-watchpoint.c | ||
step-over-trips-on-watchpoint.exp | ||
stepi-random-signal.c | ||
stepi-random-signal.exp | ||
switch-threads.c | ||
switch-threads.exp | ||
thread-execl.c | ||
thread-execl.exp | ||
thread-find.exp | ||
thread-specific-bp.c | ||
thread-specific-bp.exp | ||
thread-specific.c | ||
thread-specific.exp | ||
thread-unwindonsignal.exp | ||
thread_check.c | ||
thread_check.exp | ||
thread_events.c | ||
thread_events.exp | ||
threadapply.c | ||
threadapply.exp | ||
threxit-hop-specific.c | ||
threxit-hop-specific.exp | ||
tls-main.c | ||
tls-nodebug.c | ||
tls-nodebug.exp | ||
tls-shared.c | ||
tls-shared.exp | ||
tls-var-main.c | ||
tls-var.c | ||
tls-var.exp | ||
tls.c | ||
tls.exp | ||
tls2.c | ||
watchpoint-fork-child.c | ||
watchpoint-fork-mt.c | ||
watchpoint-fork-parent.c | ||
watchpoint-fork-st.c | ||
watchpoint-fork.exp | ||
watchpoint-fork.h | ||
watchthreads-reorder.c | ||
watchthreads-reorder.exp | ||
watchthreads.c | ||
watchthreads.exp | ||
watchthreads2.c | ||
watchthreads2.exp | ||
wp-replication.c | ||
wp-replication.exp |