aboutsummaryrefslogtreecommitdiff
path: root/gdb/linux-fork.c
diff options
context:
space:
mode:
authorPedro Alves <palves@redhat.com>2009-07-02 21:57:28 +0000
committerPedro Alves <palves@redhat.com>2009-07-02 21:57:28 +0000
commit2277426b30143428d49daf1d3e422f5096c4c4cb (patch)
treee02a568122cbe0c10f2fdf3761746e39b35492f7 /gdb/linux-fork.c
parent59837fe086d095b2ce147ac6e3539f6843007f4f (diff)
downloadgdb-2277426b30143428d49daf1d3e422f5096c4c4cb.zip
gdb-2277426b30143428d49daf1d3e422f5096c4c4cb.tar.gz
gdb-2277426b30143428d49daf1d3e422f5096c4c4cb.tar.bz2
gdb/
2009-07-02 Pedro Alves <pedro@codesourcery.com> * linux-nat.c (linux_child_follow_fork): If we're staying attached to the child process, enable event reporting on it. Don't handle checkpoints here. Instead, add the child fork to the lwp thread and inferior lists without clobbering the previous inferior. Let the thread_db layer learn about a new child process, even if following the parent. (linux_nat_switch_fork): Delete lwps of the current inferior only, instead of clearing the whole list. Use thread_change_ptid to give the core the illusion the new checkpoint is still the same inferior. Clear the register cache. (linux_handle_extended_wait): Handle checkpoints here. (linux_multi_process): Turn on. * linux-fork.c (struct fork_info) <pc>: Remove field. (init_fork_list): Do not delete the checkpoint from the inferior list (it is not there). (fork_load_infrun_state): Don't switch inferior_ptid here. Pass the new checkpoint's ptid to linux_nat_switch_fork. (fork_save_infrun_state): Make static. Don't stop the pc field of fork_info, it's gone. (linux_fork_mourn_inferior): Don't delete the checkpoint from the inferior list, it's not there. (linux_fork_detach): Ditto. (delete_fork_command): Replace mention of fork/checkpoint by checkpoint only. (detach_fork_command): Likewise. Don't delete the checkpoint from the inferior list. (info_forks_command): Adjust. (restore_detach_fork): Delete. (checkpointing_pid): New. (linux_fork_checkpointing_p): New. (save_detach_fork): Delete. (checkpoint_command): Delete temp_detach_fork. Don't remove breakpoints, that's a nop. Store the pid of the process we're checkpointing, and use make_cleanup_restore_integer to restore it. Don't reinsert breakpoints here. (process_command, fork_command): Delete. (restart_command): Update comments to only mention checkpoints, not forks. (_initialize_linux_fork): Delete "fork", "process", "info forks" commands. * linux-fork.h (fork_save_infrun_state, fork_list): Delete declarations. (linux_fork_checkpointing_p): Declare. * cli/cli-cmds.c (killlist): New. * cli/cli-cmds.h (killlist): Declare. * gdbcmd.h (killlist): Declare. * inferior.c: Include "gdbthread.h". (detach_inferior_command, kill_inferior_command) (inferior_command): New. (info_inferiors_command): Allow specifying a specific inferior id. (_initialize_inferiors): Register "inferior", "kill inferior" and "detach inferior" commands. * infcmd.c (_initialize_infcmd): Make "kill" a prefix command. * gdbthread.h (any_thread_of_process): Declare. * thread.c (any_thread_of_process): New. * NEWS: Mention multi-inferior debugging. Mention 'info inferiors', 'inferior', 'detach inferior' and 'kill inferior' as new commands. (Removed commands): New section, mentioning that 'info forks', 'fork', 'process', 'delete fork' and 'detach fork' are now gone. gdb/testsuite/ 2009-07-02 Pedro Alves <pedro@codesourcery.com> * gdb.base/multi-forks.exp: Only run detach-on-fork tests on linux. Adjust to use "inferior", "info inferiors", "detach inferior" and "kill inferior" instead of "restart", "info fork", "detach fork" and "delete fork". * gdb.base/ending-run.exp: Spell out "info". * gdb.base/help.exp: Adjust to use test_prefix_command_help for the "kill" command. gdb/doc/ 2009-07-02 Pedro Alves <pedro@codesourcery.com> * gdb.texinfo (Debugging multiple inferiors): Document the "inferior", "detach inferior" and "kill inferior" commands. (Debugging Programs with Multiple Processes): Adjust to mention generic "inferior" commands. Delete mention of "detach fork" and "delete fork". Cross reference to "Debugging multiple inferiors" section.
Diffstat (limited to 'gdb/linux-fork.c')
-rw-r--r--gdb/linux-fork.c132
1 files changed, 28 insertions, 104 deletions
diff --git a/gdb/linux-fork.c b/gdb/linux-fork.c
index b89e8b5..c0004d1 100644
--- a/gdb/linux-fork.c
+++ b/gdb/linux-fork.c
@@ -53,7 +53,6 @@ struct fork_info
struct regcache *savedregs; /* Convenient for info fork, saves
having to actually switch contexts. */
int clobber_regs; /* True if we should restore saved regs. */
- ULONGEST pc; /* PC for info fork. */
off_t *filepos; /* Set of open file descriptors' offsets. */
int maxfd;
};
@@ -211,7 +210,6 @@ init_fork_list (void)
for (fp = fork_list; fp; fp = fpnext)
{
fpnext = fp->next;
- delete_inferior (ptid_get_pid (fp->ptid));
free_fork (fp);
}
@@ -241,9 +239,7 @@ fork_load_infrun_state (struct fork_info *fp)
extern void nullify_last_target_wait_ptid ();
int i;
- inferior_ptid = fp->ptid;
-
- linux_nat_switch_fork (inferior_ptid);
+ linux_nat_switch_fork (fp->ptid);
if (fp->savedregs && fp->clobber_regs)
regcache_cpy (get_current_regcache (), fp->savedregs);
@@ -269,7 +265,7 @@ fork_load_infrun_state (struct fork_info *fp)
/* Save infrun state for the fork PTID.
Exported for use by linux child_follow_fork. */
-extern void
+static void
fork_save_infrun_state (struct fork_info *fp, int clobber_regs)
{
char path[MAXPATHLEN];
@@ -281,7 +277,6 @@ fork_save_infrun_state (struct fork_info *fp, int clobber_regs)
fp->savedregs = regcache_dup (get_current_regcache ());
fp->clobber_regs = clobber_regs;
- fp->pc = regcache_read_pc (get_current_regcache ());
if (clobber_regs)
{
@@ -371,8 +366,6 @@ linux_fork_mourn_inferior (void)
We need to delete that one from the fork_list, and switch
to the next available fork. */
delete_fork (inferior_ptid);
- /* Delete process from GDB's inferior list. */
- delete_inferior (ptid_get_pid (inferior_ptid));
/* There should still be a fork - if there's only one left,
delete_fork won't remove it, because we haven't updated
@@ -403,8 +396,6 @@ linux_fork_detach (char *args, int from_tty)
error (_("Unable to detach %s"), target_pid_to_str (inferior_ptid));
delete_fork (inferior_ptid);
- /* Delete process from GDB's inferior list. */
- delete_inferior (ptid_get_pid (inferior_ptid));
/* There should still be a fork - if there's only one left,
delete_fork won't remove it, because we haven't updated
@@ -430,14 +421,14 @@ delete_fork_command (char *args, int from_tty)
ptid_t ptid;
if (!args || !*args)
- error (_("Requires argument (fork/checkpoint id to delete)"));
+ error (_("Requires argument (checkpoint id to delete)"));
ptid = fork_id_to_ptid (parse_and_eval_long (args));
if (ptid_equal (ptid, minus_one_ptid))
- error (_("No such fork/checkpoint id, %s"), args);
+ error (_("No such checkpoint id, %s"), args);
if (ptid_equal (ptid, inferior_ptid))
- error (_("Please switch to another fork/checkpoint before deleting the current one"));
+ error (_("Please switch to another checkpoint before deleting the current one"));
if (ptrace (PTRACE_KILL, PIDGET (ptid), 0, 0))
error (_("Unable to kill pid %s"), target_pid_to_str (ptid));
@@ -446,8 +437,6 @@ delete_fork_command (char *args, int from_tty)
printf_filtered (_("Killed %s\n"), target_pid_to_str (ptid));
delete_fork (ptid);
- /* Delete process from GDB's inferior list. */
- delete_inferior (ptid_get_pid (ptid));
}
static void
@@ -456,14 +445,15 @@ detach_fork_command (char *args, int from_tty)
ptid_t ptid;
if (!args || !*args)
- error (_("Requires argument (fork id to detach)"));
+ error (_("Requires argument (checkpoint id to detach)"));
ptid = fork_id_to_ptid (parse_and_eval_long (args));
if (ptid_equal (ptid, minus_one_ptid))
- error (_("No such fork id, %s"), args);
+ error (_("No such checkpoint id, %s"), args);
if (ptid_equal (ptid, inferior_ptid))
- error (_("Please switch to another fork before detaching the current one"));
+ error (_("\
+Please switch to another checkpoint before detaching the current one"));
if (ptrace (PTRACE_DETACH, PIDGET (ptid), 0, 0))
error (_("Unable to detach %s"), target_pid_to_str (ptid));
@@ -472,8 +462,6 @@ detach_fork_command (char *args, int from_tty)
printf_filtered (_("Detached %s\n"), target_pid_to_str (ptid));
delete_fork (ptid);
- /* Delete process from GDB's process table. */
- detach_inferior (ptid_get_pid (ptid));
}
/* Print information about currently known forks. */
@@ -508,7 +496,7 @@ info_forks_command (char *arg, int from_tty)
else
{
printf_filtered (" ");
- pc = fp->pc;
+ pc = regcache_read_pc (fp->savedregs);
}
printf_filtered ("%d %s", fp->num, target_pid_to_str (fp->ptid));
if (fp->num == 0)
@@ -542,31 +530,19 @@ info_forks_command (char *arg, int from_tty)
if (printed == NULL)
{
if (requested > 0)
- printf_filtered (_("No fork number %d.\n"), requested);
+ printf_filtered (_("No checkpoint number %d.\n"), requested);
else
- printf_filtered (_("No forks.\n"));
+ printf_filtered (_("No checkpoints.\n"));
}
}
-/* Save/restore mode variable 'detach_fork':
- We need to temporarily take over this mode variable, while
- preserving the user-specified state, and make sure that it
- gets restored in case of error.
-
- The int pointer that we use comes from the caller, so we can
- be called more than once (even though currently we don't need to). */
-
-static void
-restore_detach_fork (void *arg)
-{
- detach_fork = *(int *) arg;
-}
+/* The PID of the process we're checkpointing. */
+static int checkpointing_pid = 0;
-static struct cleanup *
-save_detach_fork (int *saved_val)
+int
+linux_fork_checkpointing_p (int pid)
{
- *saved_val = detach_fork;
- return make_cleanup (restore_detach_fork, (void *) saved_val);
+ return (checkpointing_pid == pid);
}
static void
@@ -581,12 +557,6 @@ checkpoint_command (char *args, int from_tty)
pid_t retpid;
struct cleanup *old_chain;
long i;
- /* Make this temp var static, 'cause it's used in the error context. */
- static int temp_detach_fork;
-
- /* Remove breakpoints, so that they are not inserted
- in the forked process. */
- remove_breakpoints ();
/* Make the inferior fork, record its (and gdb's) state. */
@@ -600,8 +570,11 @@ checkpoint_command (char *args, int from_tty)
gdbarch = get_objfile_arch (fork_objf);
ret = value_from_longest (builtin_type (gdbarch)->builtin_int, 0);
- old_chain = save_detach_fork (&temp_detach_fork);
- detach_fork = 0;
+
+ /* Tell linux-nat.c that we're checkpointing this inferior. */
+ old_chain = make_cleanup_restore_integer (&checkpointing_pid);
+ checkpointing_pid = PIDGET (inferior_ptid);
+
ret = call_function_by_hand (fork_fn, 0, &ret);
do_cleanups (old_chain);
if (!ret) /* Probably can't happen. */
@@ -629,7 +602,6 @@ checkpoint_command (char *args, int from_tty)
if (!fp)
error (_("Failed to find new fork"));
fork_save_infrun_state (fp, 1);
- insert_breakpoints ();
}
static void
@@ -656,37 +628,7 @@ linux_fork_context (struct fork_info *newfp, int from_tty)
print_stack_frame (get_selected_frame (NULL), 1, SRC_AND_LOC);
}
-/* Switch inferior process (fork) context, by process id. */
-static void
-process_command (char *args, int from_tty)
-{
- struct fork_info *fp;
-
- if (!args || !*args)
- error (_("Requires argument (process id to switch to)"));
-
- if ((fp = find_fork_pid (parse_and_eval_long (args))) == NULL)
- error (_("Not found: process id %s"), args);
-
- linux_fork_context (fp, from_tty);
-}
-
-/* Switch inferior process (fork) context, by fork id. */
-static void
-fork_command (char *args, int from_tty)
-{
- struct fork_info *fp;
-
- if (!args || !*args)
- error (_("Requires argument (fork id to switch to)"));
-
- if ((fp = find_fork_id (parse_and_eval_long (args))) == NULL)
- error (_("Not found: fork id %s"), args);
-
- linux_fork_context (fp, from_tty);
-}
-
-/* Switch inferior process (fork) context, by checkpoint id. */
+/* Switch inferior process (checkpoint) context, by checkpoint id. */
static void
restart_command (char *args, int from_tty)
{
@@ -727,9 +669,8 @@ Tells gdb whether to detach the child of a fork."),
add_com ("checkpoint", class_obscure, checkpoint_command, _("\
Fork a duplicate process (experimental)."));
- /* Restart command: restore the context of a specified fork
- process. May be used for "program forks" as well as for
- "debugger forks" (checkpoints). */
+ /* Restart command: restore the context of a specified checkpoint
+ process. */
add_com ("restart", class_obscure, restart_command, _("\
restart <n>: restore program context from a checkpoint.\n\
@@ -739,36 +680,19 @@ Argument 'n' is checkpoint ID, as displayed by 'info checkpoints'."));
fork list. */
add_cmd ("checkpoint", class_obscure, delete_fork_command, _("\
-Delete a fork/checkpoint (experimental)."),
+Delete a checkpoint (experimental)."),
&deletelist);
/* Detach checkpoint command: release the process to run independently,
and remove it from the fork list. */
add_cmd ("checkpoint", class_obscure, detach_fork_command, _("\
-Detach from a fork/checkpoint (experimental)."),
+Detach from a checkpoint (experimental)."),
&detachlist);
/* Info checkpoints command: list all forks/checkpoints
currently under gdb's control. */
add_info ("checkpoints", info_forks_command,
- _("IDs of currently known forks/checkpoints."));
-
- /* Command aliases (let "fork" and "checkpoint" be used
- interchangeably). */
-
- add_alias_cmd ("fork", "checkpoint", class_obscure, 1, &deletelist);
- add_alias_cmd ("fork", "checkpoint", class_obscure, 1, &detachlist);
- add_info_alias ("forks", "checkpoints", 0);
-
- /* "fork <n>" (by analogy to "thread <n>"). */
- add_com ("fork", class_obscure, fork_command, _("\
-fork <n>: Switch between forked processes.\n\
-Argument 'n' is fork ID, as displayed by 'info forks'."));
-
- /* "process <proc id>" as opposed to "fork <fork id>". */
- add_com ("process", class_obscure, process_command, _("\
-process <pid>: Switch between forked processes.\n\
-Argument 'pid' is process ID, as displayed by 'info forks' or 'shell ps'."));
+ _("IDs of currently known checkpoints."));
}