This is the mail archive of the
gdb-patches@sourceware.org
mailing list for the GDB project.
[non-stop] 02/10 Don't trim ptids on fork/exec
- From: Pedro Alves <pedro at codesourcery dot com>
- To: gdb-patches at sourceware dot org
- Date: Sun, 15 Jun 2008 22:03:53 +0100
- Subject: [non-stop] 02/10 Don't trim ptids on fork/exec
With the previous patch installed, we hit an assertion inside
is_running on the follow-* tests. Here is a backtrace:
#0 internal_error (file=0x830eadf "../../src/gdb/thread.c", line=515,
string=0x830eac1 "%s: Assertion `%s' failed.")
at ../../src/gdb/utils.c:817
#1 0x08142650 in is_executing (ptid={pid = 13049, lwp = 0, tid = 0})
at ../../src/gdb/thread.c:515
#2 0x08140dc3 in get_selected_block (addr_in_block=0x0)
at ../../src/gdb/stack.c:1647
#3 0x0812df2a in decode_objc (argptr=0xffe590fc, funfirstline=1,
file_symtab=0x0, canonical=0x0,
saved_arg=0x8438088 "main") at ../../src/gdb/linespec.c:1125
#4 0x0812d691 in decode_line_1 (argptr=0xffe590fc, funfirstline=1,
default_symtab=0x0, default_line=0,
canonical=0x0, not_found_ptr=0xffe59104) at ../../src/gdb/linespec.c:746
#5 0x080f6e96 in breakpoint_re_set_one (bint=0x84382b0)
at ../../src/gdb/breakpoint.c:7435
#6 0x08143ff8 in catch_errors (func=0x80f6d71 <breakpoint_re_set_one>,
func_args=0x84382b0,
errstring=0x84143d8 "Error in re-setting breakpoint 1: ", mask=6)
at ../../src/gdb/exceptions.c:509
#7 0x080f710e in breakpoint_re_set () at ../../src/gdb/breakpoint.c:7577
#8 0x08128255 in clear_symtab_users () at ../../src/gdb/symfile.c:2837
#9 0x08124d75 in new_symfile_objfile (objfile=0x851e508, mainline=1, verbo=0)
at ../../src/gdb/symfile.c:978
#10 0x081250f1 in symbol_file_add_with_addrs_or_offsets (abfd=0x848e700,
from_tty=0, addrs=0x0, offsets=0x0,
num_offsets=0, mainline=1, flags=0) at ../../src/gdb/symfile.c:1137
#11 0x08125149 in symbol_file_add_from_bfd (abfd=0x848e700, from_tty=0,
addrs=0x0, mainline=1, flags=0)
at ../../src/gdb/symfile.c:1156
#12 0x08125182 in symbol_file_add (
name=0x84662c8 "/home/pedro/gdb/nonstop_head/build-32/gdb/testsuite/gdb.base/execd-prog",
from_tty=0, addrs=0x0,
mainline=1, flags=0) at ../../src/gdb/symfile.c:1169
#13 0x081251d5 in symbol_file_add_main_1 (
args=0x84662c8 "/home/pedro/gdb/nonstop_head/build-32/gdb/testsuite/gdb.base/execd-prog",
from_tty=0, flags=0)
at ../../src/gdb/symfile.c:1191
#14 0x081251a4 in symbol_file_add_main (
args=0x84662c8 "/home/pedro/gdb/nonstop_head/build-32/gdb/testsuite/gdb.base/execd-prog",
from_tty=0)
at ../../src/gdb/symfile.c:1185
#15 0x08135152 in follow_exec (pid=13049,
execd_pathname=0x84662c8 "/home/pedro/gdb/nonstop_head/build-32/gdb/testsuite/gdb.base/execd-prog")
at ../../src/gdb/infrun.c:423
#16 0x08137078 in handle_inferior_event (ecs=0xffe59490)
at ../../src/gdb/infrun.c:1935
The issue is that the thread module should never see an inferior_ptid
not listed in the thread list if there are threads in the thread
list. We accept that an ptid is not listed iff there are no
threads listed, so targets that don't yet register the main
thread in the thread/task list continue working.
Now, the assert triggers, because, across an exec and a fork, we're
transfering a ptid to the core with only that has the pid member filled.
A problem similar to the other crash across an exec when doing an
"info thread" we just fixed recently (execl.exp).
From infrun.c:handle_inferior_event:
(gdb)
1923
1924 case TARGET_WAITKIND_EXECD:
1925 if (debug_infrun)
1926 fprintf_unfiltered (gdb_stdlog, "infrun:
TARGET_WAITKIND_EXECD\n");
1927 stop_signal = TARGET_SIGNAL_TRAP;
1928
1929 pending_follow.execd_pathname =
1930 savestring (ecs->ws.value.execd_pathname,
1931 strlen (ecs->ws.value.execd_pathname));
1932
(gdb)
1933 /* This causes the eventpoints and symbol table to be reset.
Must
1934 do this now, before trying to determine whether to stop. */
1935 follow_exec (PIDGET (inferior_ptid),
pending_follow.execd_pathname);
1936 xfree (pending_follow.execd_pathname);
The fix is to not trim the ptids the targets report.
The patch touches inf-ttrace.c to adapt to the new interface, but
unfortunatelly, I have no HPUX access to test it. If someone
could do a spin there for me, it would be really appreciated.
win32-nat.c was also touched. I've tested the whole series
on cygwin, although this hunk in question should be obvious --
related_pid is not used at all in either cygwin or mingw32, so
setting it is a nop really -- it is only defined on on
TARGET_WAITKIND_FORK|EXEC, but we don't support those on cygwin
or mingw.
--
Pedro Alves
2008-06-15 Pedro Alves <pedro@codesourcery.com>
* target.h (struct target_waitstatus): Store related_pid as a ptid.
(inferior_has_forked, inferior_has_vforked, inferior_has_execd):
Take a ptid_t.
* breakpoint.h (struct breakpoint): Change forked_inferior_pid
type to ptid.
* breakpoint.c (print_it_typical, bpstat_check_location)
(print_one_breakpoint_location, set_raw_breakpoint_without_location)
(create_fork_vfork_event_catchpoint): Adjust.
* infrun.c (fork_event): Change parent_pid and child_pid types to
ptid.
(follow_exec, inferior_has_forked, inferior_has_vforked)
(inferior_has_execd): Take a ptid_t and don't trim it.
* linux-thread-db.c (thread_db_wait): Don't trim the returned ptid.
* linux-nat.c (linux_child_follow_fork): Adjust.
* inf-ptrace.c (inf_ptrace_wait): Adjust.
* inf-ttrace.c (inf_ttrace_wait): Adjust.
* win32-nat.c (get_win32_debug_event): Don't set related_pid.
---
gdb/breakpoint.c | 19 ++++++++++---------
gdb/breakpoint.h | 2 +-
gdb/inf-ptrace.c | 4 ++--
gdb/inf-ttrace.c | 15 ++++++++++++---
gdb/infrun.c | 26 +++++++++++++-------------
gdb/linux-nat.c | 9 +++++----
gdb/target.h | 12 ++++++------
gdb/win32-nat.c | 4 ++--
8 files changed, 51 insertions(+), 40 deletions(-)
Index: src/gdb/target.h
===================================================================
--- src.orig/gdb/target.h 2008-06-10 11:50:57.000000000 +0100
+++ src/gdb/target.h 2008-06-10 11:52:11.000000000 +0100
@@ -91,13 +91,13 @@ enum target_waitkind
(e.g. it called load(2) on AIX). */
TARGET_WAITKIND_LOADED,
- /* The program has forked. A "related" process' ID is in
+ /* The program has forked. A "related" process' PTID is in
value.related_pid. I.e., if the child forks, value.related_pid
is the parent's ID. */
TARGET_WAITKIND_FORKED,
- /* The program has vforked. A "related" process's ID is in
+ /* The program has vforked. A "related" process's PTID is in
value.related_pid. */
TARGET_WAITKIND_VFORKED,
@@ -140,7 +140,7 @@ struct target_waitstatus
{
int integer;
enum target_signal sig;
- int related_pid;
+ ptid_t related_pid;
char *execd_pathname;
int syscall_id;
}
@@ -688,11 +688,11 @@ int target_write_memory_blocks (VEC(memo
/* From infrun.c. */
-extern int inferior_has_forked (int pid, int *child_pid);
+extern int inferior_has_forked (ptid_t pid, ptid_t *child_pid);
-extern int inferior_has_vforked (int pid, int *child_pid);
+extern int inferior_has_vforked (ptid_t pid, ptid_t *child_pid);
-extern int inferior_has_execd (int pid, char **execd_pathname);
+extern int inferior_has_execd (ptid_t pid, char **execd_pathname);
/* From exec.c */
Index: src/gdb/breakpoint.h
===================================================================
--- src.orig/gdb/breakpoint.h 2008-06-10 11:49:22.000000000 +0100
+++ src/gdb/breakpoint.h 2008-06-10 11:52:11.000000000 +0100
@@ -439,7 +439,7 @@ struct breakpoint
/* Process id of a child process whose forking triggered this
catchpoint. This field is only valid immediately after this
catchpoint has triggered. */
- int forked_inferior_pid;
+ ptid_t forked_inferior_pid;
/* Filename of a program whose exec triggered this catchpoint.
This field is only valid immediately after this catchpoint has
Index: src/gdb/breakpoint.c
===================================================================
--- src.orig/gdb/breakpoint.c 2008-06-10 11:52:00.000000000 +0100
+++ src/gdb/breakpoint.c 2008-06-10 11:52:11.000000000 +0100
@@ -2313,7 +2313,7 @@ print_it_typical (bpstat bs)
annotate_catchpoint (b->number);
printf_filtered (_("\nCatchpoint %d (forked process %d), "),
b->number,
- b->forked_inferior_pid);
+ ptid_get_pid (b->forked_inferior_pid));
return PRINT_SRC_AND_LOC;
break;
@@ -2321,7 +2321,7 @@ print_it_typical (bpstat bs)
annotate_catchpoint (b->number);
printf_filtered (_("\nCatchpoint %d (vforked process %d), "),
b->number,
- b->forked_inferior_pid);
+ ptid_get_pid (b->forked_inferior_pid));
return PRINT_SRC_AND_LOC;
break;
@@ -2813,17 +2813,17 @@ bpstat_check_location (const struct bp_l
return 0;
if ((b->type == bp_catch_fork)
- && !inferior_has_forked (PIDGET (inferior_ptid),
+ && !inferior_has_forked (inferior_ptid,
&b->forked_inferior_pid))
return 0;
if ((b->type == bp_catch_vfork)
- && !inferior_has_vforked (PIDGET (inferior_ptid),
+ && !inferior_has_vforked (inferior_ptid,
&b->forked_inferior_pid))
return 0;
if ((b->type == bp_catch_exec)
- && !inferior_has_execd (PIDGET (inferior_ptid), &b->exec_pathname))
+ && !inferior_has_execd (inferior_ptid, &b->exec_pathname))
return 0;
return 1;
@@ -3651,10 +3651,11 @@ print_one_breakpoint_location (struct br
if (addressprint)
ui_out_field_skip (uiout, "addr");
annotate_field (5);
- if (b->forked_inferior_pid != 0)
+ if (!ptid_equal (b->forked_inferior_pid, null_ptid))
{
ui_out_text (uiout, "process ");
- ui_out_field_int (uiout, "what", b->forked_inferior_pid);
+ ui_out_field_int (uiout, "what",
+ ptid_get_pid (b->forked_inferior_pid));
ui_out_spaces (uiout, 1);
}
break;
@@ -4323,7 +4324,7 @@ set_raw_breakpoint_without_location (enu
b->frame_id = null_frame_id;
b->dll_pathname = NULL;
b->triggered_dll_pathname = NULL;
- b->forked_inferior_pid = 0;
+ b->forked_inferior_pid = null_ptid;
b->exec_pathname = NULL;
b->ops = NULL;
b->condition_not_parsed = 0;
@@ -4696,7 +4697,7 @@ create_fork_vfork_event_catchpoint (int
b->addr_string = NULL;
b->enable_state = bp_enabled;
b->disposition = tempflag ? disp_del : disp_donttouch;
- b->forked_inferior_pid = 0;
+ b->forked_inferior_pid = null_ptid;
update_global_location_list ();
Index: src/gdb/infrun.c
===================================================================
--- src.orig/gdb/infrun.c 2008-06-10 11:52:00.000000000 +0100
+++ src/gdb/infrun.c 2008-06-10 11:52:11.000000000 +0100
@@ -297,8 +297,8 @@ static struct
enum target_waitkind kind;
struct
{
- int parent_pid;
- int child_pid;
+ ptid_t parent_pid;
+ ptid_t child_pid;
}
fork_event;
char *execd_pathname;
@@ -362,9 +362,9 @@ follow_inferior_reset_breakpoints (void)
/* EXECD_PATHNAME is assumed to be non-NULL. */
static void
-follow_exec (int pid, char *execd_pathname)
+follow_exec (ptid_t pid, char *execd_pathname)
{
- int saved_pid = pid;
+ ptid_t saved_pid = pid;
struct target_ops *tgt;
/* This is an exec event that we actually wish to pay attention to.
@@ -404,7 +404,7 @@ follow_exec (int pid, char *execd_pathna
gdb_flush (gdb_stdout);
generic_mourn_inferior ();
/* Because mourn_inferior resets inferior_ptid. */
- inferior_ptid = pid_to_ptid (saved_pid);
+ inferior_ptid = saved_pid;
if (gdb_sysroot && *gdb_sysroot)
{
@@ -1897,7 +1897,7 @@ handle_inferior_event (struct execution_
stop_signal = TARGET_SIGNAL_TRAP;
pending_follow.kind = ecs->ws.kind;
- pending_follow.fork_event.parent_pid = PIDGET (ecs->ptid);
+ pending_follow.fork_event.parent_pid = ecs->ptid;
pending_follow.fork_event.child_pid = ecs->ws.value.related_pid;
if (!ptid_equal (ecs->ptid, inferior_ptid))
@@ -1932,7 +1932,7 @@ handle_inferior_event (struct execution_
/* This causes the eventpoints and symbol table to be reset. Must
do this now, before trying to determine whether to stop. */
- follow_exec (PIDGET (inferior_ptid), pending_follow.execd_pathname);
+ follow_exec (inferior_ptid, pending_follow.execd_pathname);
xfree (pending_follow.execd_pathname);
stop_pc = regcache_read_pc (get_thread_regcache (ecs->ptid));
@@ -4323,7 +4323,7 @@ discard_inferior_status (struct inferior
}
int
-inferior_has_forked (int pid, int *child_pid)
+inferior_has_forked (ptid_t pid, ptid_t *child_pid)
{
struct target_waitstatus last;
ptid_t last_ptid;
@@ -4333,7 +4333,7 @@ inferior_has_forked (int pid, int *child
if (last.kind != TARGET_WAITKIND_FORKED)
return 0;
- if (ptid_get_pid (last_ptid) != pid)
+ if (!ptid_equal (last_ptid, pid))
return 0;
*child_pid = last.value.related_pid;
@@ -4341,7 +4341,7 @@ inferior_has_forked (int pid, int *child
}
int
-inferior_has_vforked (int pid, int *child_pid)
+inferior_has_vforked (ptid_t pid, ptid_t *child_pid)
{
struct target_waitstatus last;
ptid_t last_ptid;
@@ -4351,7 +4351,7 @@ inferior_has_vforked (int pid, int *chil
if (last.kind != TARGET_WAITKIND_VFORKED)
return 0;
- if (ptid_get_pid (last_ptid) != pid)
+ if (!ptid_equal (last_ptid, pid))
return 0;
*child_pid = last.value.related_pid;
@@ -4359,7 +4359,7 @@ inferior_has_vforked (int pid, int *chil
}
int
-inferior_has_execd (int pid, char **execd_pathname)
+inferior_has_execd (ptid_t pid, char **execd_pathname)
{
struct target_waitstatus last;
ptid_t last_ptid;
@@ -4369,7 +4369,7 @@ inferior_has_execd (int pid, char **exec
if (last.kind != TARGET_WAITKIND_EXECD)
return 0;
- if (ptid_get_pid (last_ptid) != pid)
+ if (!ptid_equal (last_ptid, pid))
return 0;
*execd_pathname = xstrdup (last.value.execd_pathname);
Index: src/gdb/linux-nat.c
===================================================================
--- src.orig/gdb/linux-nat.c 2008-06-10 11:52:00.000000000 +0100
+++ src/gdb/linux-nat.c 2008-06-10 11:52:11.000000000 +0100
@@ -568,7 +568,7 @@ linux_child_follow_fork (struct target_o
parent_pid = ptid_get_lwp (last_ptid);
if (parent_pid == 0)
parent_pid = ptid_get_pid (last_ptid);
- child_pid = last_status.value.related_pid;
+ child_pid = PIDGET (last_status.value.related_pid);
if (! follow_child)
{
@@ -1623,7 +1623,7 @@ linux_handle_extended_wait (struct lwp_i
_("wait returned unexpected status 0x%x"), status);
}
- ourstatus->value.related_pid = new_pid;
+ ourstatus->value.related_pid = ptid_build (new_pid, new_pid, 0);
if (event == PTRACE_EVENT_FORK)
ourstatus->kind = TARGET_WAITKIND_FORKED;
@@ -1655,7 +1655,8 @@ linux_handle_extended_wait (struct lwp_i
else
{
new_lp->resumed = 1;
- ptrace (PTRACE_CONT, lp->waitstatus.value.related_pid, 0,
+ ptrace (PTRACE_CONT,
+ PIDGET (lp->waitstatus.value.related_pid), 0,
status ? WSTOPSIG (status) : 0);
}
@@ -2879,7 +2880,7 @@ linux_nat_kill (void)
if (last.kind == TARGET_WAITKIND_FORKED
|| last.kind == TARGET_WAITKIND_VFORKED)
{
- ptrace (PT_KILL, last.value.related_pid, 0, 0);
+ ptrace (PT_KILL, PIDGET (last.value.related_pid), 0, 0);
wait (&status);
}
Index: src/gdb/inf-ptrace.c
===================================================================
--- src.orig/gdb/inf-ptrace.c 2008-06-10 11:49:22.000000000 +0100
+++ src/gdb/inf-ptrace.c 2008-06-10 11:52:11.000000000 +0100
@@ -399,7 +399,7 @@ inf_ptrace_wait (ptid_t ptid, struct tar
{
case PTRACE_FORK:
ourstatus->kind = TARGET_WAITKIND_FORKED;
- ourstatus->value.related_pid = pe.pe_other_pid;
+ ourstatus->value.related_pid = pid_to_ptid (pe.pe_other_pid);
/* Make sure the other end of the fork is stopped too. */
fpid = waitpid (pe.pe_other_pid, &status, 0);
@@ -414,7 +414,7 @@ inf_ptrace_wait (ptid_t ptid, struct tar
gdb_assert (pe.pe_other_pid == pid);
if (fpid == ptid_get_pid (inferior_ptid))
{
- ourstatus->value.related_pid = pe.pe_other_pid;
+ ourstatus->value.related_pid = pid_to_ptid (pe.pe_other_pid);
return pid_to_ptid (fpid);
}
Index: src/gdb/inf-ttrace.c
===================================================================
--- src.orig/gdb/inf-ttrace.c 2008-06-10 11:49:22.000000000 +0100
+++ src/gdb/inf-ttrace.c 2008-06-10 11:52:11.000000000 +0100
@@ -839,6 +839,7 @@ inf_ttrace_wait (ptid_t ptid, struct tar
lwpid_t lwpid = ptid_get_lwp (ptid);
ttstate_t tts;
struct thread_info *ti;
+ ptid_t related_ptid;
/* Until proven otherwise. */
ourstatus->kind = TARGET_WAITKIND_SPURIOUS;
@@ -912,8 +913,11 @@ inf_ttrace_wait (ptid_t ptid, struct tar
break;
case TTEVT_FORK:
+ related_ptid = ptid_build (tts.tts_u.tts_fork.tts_fpid,
+ tts.tts_u.tts_fork.tts_flwpid, 0);
+
ourstatus->kind = TARGET_WAITKIND_FORKED;
- ourstatus->value.related_pid = tts.tts_u.tts_fork.tts_fpid;
+ ourstatus->value.related_pid = related_ptid;
/* Make sure the other end of the fork is stopped too. */
if (ttrace_wait (tts.tts_u.tts_fork.tts_fpid,
@@ -924,16 +928,21 @@ inf_ttrace_wait (ptid_t ptid, struct tar
gdb_assert (tts.tts_event == TTEVT_FORK);
if (tts.tts_u.tts_fork.tts_isparent)
{
+ related_ptid = ptid_build (tts.tts_u.tts_fork.tts_fpid,
+ tts.tts_u.tts_fork.tts_flwpid, 0);
ptid = ptid_build (tts.tts_pid, tts.tts_lwpid, 0);
- ourstatus->value.related_pid = tts.tts_u.tts_fork.tts_fpid;
+ ourstatus->value.related_pid = related_ptid;
}
break;
case TTEVT_VFORK:
gdb_assert (!tts.tts_u.tts_fork.tts_isparent);
+ related_ptid = ptid_build (tts.tts_u.tts_fork.tts_fpid,
+ tts.tts_u.tts_fork.tts_flwpid, 0);
+
ourstatus->kind = TARGET_WAITKIND_VFORKED;
- ourstatus->value.related_pid = tts.tts_u.tts_fork.tts_fpid;
+ ourstatus->value.related_pid = related_ptid;
/* HACK: To avoid touching the parent during the vfork, switch
away from it. */
Index: src/gdb/win32-nat.c
===================================================================
--- src.orig/gdb/win32-nat.c 2008-06-10 11:49:22.000000000 +0100
+++ src/gdb/win32-nat.c 2008-06-10 11:52:11.000000000 +0100
@@ -1300,7 +1300,7 @@ get_win32_debug_event (int pid, struct t
/* Kludge around a Windows bug where first event is a create
thread event. Caused when attached process does not have
a main thread. */
- retval = ourstatus->value.related_pid = fake_create_process ();
+ retval = fake_create_process ();
if (retval)
saw_create++;
}
@@ -1340,7 +1340,7 @@ get_win32_debug_event (int pid, struct t
/* Add the main thread */
th = win32_add_thread (main_thread_id,
current_event.u.CreateProcessInfo.hThread);
- retval = ourstatus->value.related_pid = current_event.dwThreadId;
+ retval = current_event.dwThreadId;
break;
case EXIT_PROCESS_DEBUG_EVENT: