* [RFA] Checkpoint: wait the defunct process when delete it
@ 2010-05-09 6:23 Hui Zhu
2010-05-10 19:31 ` Michael Snyder
` (2 more replies)
0 siblings, 3 replies; 23+ messages in thread
From: Hui Zhu @ 2010-05-09 6:23 UTC (permalink / raw)
To: gdb-patches ml; +Cc: Michael Snyder
Hi,
I found that when we delete the checkpoint process, it keep defunct.
This is because the parent process is still running and didn't wait
it.
So I add a wait_ptid function after ptrace kill.
Please help me review it.
Thanks,
Hui
2010-05-09 Hui Zhu <teawater@gmail.com>
* linux-fork.c (wait_ptid): New function.
(delete_checkpoint_command): Call wait_ptid.
---
linux-fork.c | 32 ++++++++++++++++++++++++++++++++
1 file changed, 32 insertions(+)
--- a/linux-fork.c
+++ b/linux-fork.c
@@ -410,6 +410,35 @@ linux_fork_detach (char *args, int from_
delete_fork (inferior_ptid);
}
+static int
+wait_ptid (ptid_t ptid)
+{
+ struct objfile *waitpid_objf;
+ struct value *waitpid_fn = NULL;
+ struct value *argv[4];
+ struct gdbarch *gdbarch = get_current_arch ();
+
+ /* Get the waitpid_fn. */
+ if (lookup_minimal_symbol ("waitpid", NULL, NULL) != NULL)
+ waitpid_fn = find_function_in_inferior ("waitpid", &waitpid_objf);
+ if (!waitpid_fn)
+ if (lookup_minimal_symbol ("_waitpid", NULL, NULL) != NULL)
+ waitpid_fn = find_function_in_inferior ("waitpid", &waitpid_objf);
+ if (!waitpid_fn)
+ return -1;
+
+ /* Get the argv. */
+ argv[0] = value_from_longest (builtin_type (gdbarch)->builtin_int,
PIDGET (ptid));
+ argv[1] = value_from_longest (builtin_type (gdbarch)->builtin_int, 0);
+ argv[2] = value_from_longest (builtin_type (gdbarch)->builtin_int, 0);
+ argv[3] = 0;
+
+ if (call_function_by_hand (waitpid_fn, 3, argv) == 0)
+ return -1;
+
+ return 0;
+}
+
/* Fork list <-> user interface. */
static void
@@ -431,6 +460,9 @@ Please switch to another checkpoint befo
if (ptrace (PTRACE_KILL, PIDGET (ptid), 0, 0))
error (_("Unable to kill pid %s"), target_pid_to_str (ptid));
+ if (wait_ptid (ptid))
+ error (_("Unable to wait pid %s"), target_pid_to_str (ptid));
+
if (from_tty)
printf_filtered (_("Killed %s\n"), target_pid_to_str (ptid));
^ permalink raw reply [flat|nested] 23+ messages in thread* Re: [RFA] Checkpoint: wait the defunct process when delete it 2010-05-09 6:23 [RFA] Checkpoint: wait the defunct process when delete it Hui Zhu @ 2010-05-10 19:31 ` Michael Snyder 2010-05-10 23:30 ` Pedro Alves 2010-05-11 22:43 ` Michael Snyder 2 siblings, 0 replies; 23+ messages in thread From: Michael Snyder @ 2010-05-10 19:31 UTC (permalink / raw) To: Hui Zhu; +Cc: gdb-patches ml Hui Zhu wrote: > Hi, > > I found that when we delete the checkpoint process, it keep defunct. > This is because the parent process is still running and didn't wait > it. > So I add a wait_ptid function after ptrace kill. > > Please help me review it. I think it should be called something more informative than "wait_ptid". The name should reflect the fact that it is actually the inferior that is calling wait, not gdb. Something like "inferior_call_wait_ptid", perhaps. Other than that it seems like a good idea... > 2010-05-09 Hui Zhu <teawater@gmail.com> > > * linux-fork.c (wait_ptid): New function. > (delete_checkpoint_command): Call wait_ptid. > > > --- > linux-fork.c | 32 ++++++++++++++++++++++++++++++++ > 1 file changed, 32 insertions(+) > > --- a/linux-fork.c > +++ b/linux-fork.c > @@ -410,6 +410,35 @@ linux_fork_detach (char *args, int from_ > delete_fork (inferior_ptid); > } > > +static int > +wait_ptid (ptid_t ptid) > +{ > + struct objfile *waitpid_objf; > + struct value *waitpid_fn = NULL; > + struct value *argv[4]; > + struct gdbarch *gdbarch = get_current_arch (); > + > + /* Get the waitpid_fn. */ > + if (lookup_minimal_symbol ("waitpid", NULL, NULL) != NULL) > + waitpid_fn = find_function_in_inferior ("waitpid", &waitpid_objf); > + if (!waitpid_fn) > + if (lookup_minimal_symbol ("_waitpid", NULL, NULL) != NULL) > + waitpid_fn = find_function_in_inferior ("waitpid", &waitpid_objf); > + if (!waitpid_fn) > + return -1; > + > + /* Get the argv. */ > + argv[0] = value_from_longest (builtin_type (gdbarch)->builtin_int, > PIDGET (ptid)); > + argv[1] = value_from_longest (builtin_type (gdbarch)->builtin_int, 0); > + argv[2] = value_from_longest (builtin_type (gdbarch)->builtin_int, 0); > + argv[3] = 0; > + > + if (call_function_by_hand (waitpid_fn, 3, argv) == 0) > + return -1; > + > + return 0; > +} > + > /* Fork list <-> user interface. */ > > static void > @@ -431,6 +460,9 @@ Please switch to another checkpoint befo > if (ptrace (PTRACE_KILL, PIDGET (ptid), 0, 0)) > error (_("Unable to kill pid %s"), target_pid_to_str (ptid)); > > + if (wait_ptid (ptid)) > + error (_("Unable to wait pid %s"), target_pid_to_str (ptid)); > + > if (from_tty) > printf_filtered (_("Killed %s\n"), target_pid_to_str (ptid)); ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [RFA] Checkpoint: wait the defunct process when delete it 2010-05-09 6:23 [RFA] Checkpoint: wait the defunct process when delete it Hui Zhu 2010-05-10 19:31 ` Michael Snyder @ 2010-05-10 23:30 ` Pedro Alves 2010-05-11 21:50 ` Michael Snyder 2010-05-11 22:43 ` Michael Snyder 2 siblings, 1 reply; 23+ messages in thread From: Pedro Alves @ 2010-05-10 23:30 UTC (permalink / raw) To: gdb-patches; +Cc: Hui Zhu, Michael Snyder On Sunday 09 May 2010 07:23:15, Hui Zhu wrote: > I found that when we delete the checkpoint process, it keep defunct. > This is because the parent process is still running and didn't wait > it. > So I add a wait_ptid function after ptrace kill. You're assuming inferior_ptid is the parent process of the checkpoint fork, but I don't believe that is always true. E.g., if you do (gdb) checkpoint (gdb) checkpoint (gdb) checkpoint (gdb) info checkpoints 3 process 15353 at 0x457d43, file gdb.c, line 28 2 process 15352 at 0x457d43, file gdb.c, line 28 1 process 15351 at 0x457d43, file gdb.c, line 28 * 0 Thread 0x7ffff7fcc6f0 (LWP 15348) (main process) at 0x457d43, file gdb.c, line 28 (gdb) restart 1 ... (gdb) delete checkpoint 2 At this point, inferior_ptid will be process 15351, but that is not the parent of 15352, the process you're killing. 15348 is. > +static int > +wait_ptid (ptid_t ptid) > +{ I'd rename this to call_waitpid, similarly to the call_lseek function already present in the file. You may want to reimplement your function similarly to call_lseek is implemented too. Your call. > + struct objfile *waitpid_objf; > + struct value *waitpid_fn = NULL; > + struct value *argv[4]; > + struct gdbarch *gdbarch = get_current_arch (); > + > + /* Get the waitpid_fn. */ > + if (lookup_minimal_symbol ("waitpid", NULL, NULL) != NULL) > + waitpid_fn = find_function_in_inferior ("waitpid", &waitpid_objf); > + if (!waitpid_fn) > + if (lookup_minimal_symbol ("_waitpid", NULL, NULL) != NULL) "_waitpid" here, > + waitpid_fn = find_function_in_inferior ("waitpid", &waitpid_objf); but "waitpid" here? You could also put those two 'if's on a single line, like: if (lookup_minimal_symbol ("waitpid", NULL, NULL) != NULL) waitpid_fn = find_function_in_inferior ("waitpid", &waitpid_objf); if (!waitpid_fn && lookup_minimal_symbol ("_waitpid", NULL, NULL) != NULL) waitpid_fn = find_function_in_inferior ("_waitpid", &waitpid_objf); > + /* Get the argv. */ > + argv[0] = value_from_longest (builtin_type (gdbarch)->builtin_int, > PIDGET (ptid)); > + argv[1] = value_from_longest (builtin_type (gdbarch)->builtin_int, 0); > + argv[2] = value_from_longest (builtin_type (gdbarch)->builtin_int, 0); > + argv[3] = 0; The second argument of waitpid is a pointer, not an integer. From `man waitpid': pid_t waitpid(pid_t pid, int *status, int options); > + if (call_function_by_hand (waitpid_fn, 3, argv) == 0) > + return -1; This doesn't work in non-stop/async modes if the parent is presently running. Maybe just take the easy route for now, and add an is_stopped check, bailing out if not stopped? > + if (wait_ptid (ptid)) > + error (_("Unable to wait pid %s"), target_pid_to_str (ptid)); -- Pedro Alves ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [RFA] Checkpoint: wait the defunct process when delete it 2010-05-10 23:30 ` Pedro Alves @ 2010-05-11 21:50 ` Michael Snyder 2010-05-11 22:28 ` Michael Snyder 2010-05-12 0:02 ` Pedro Alves 0 siblings, 2 replies; 23+ messages in thread From: Michael Snyder @ 2010-05-11 21:50 UTC (permalink / raw) To: Pedro Alves; +Cc: gdb-patches, Hui Zhu Pedro Alves wrote: > On Sunday 09 May 2010 07:23:15, Hui Zhu wrote: > >> I found that when we delete the checkpoint process, it keep defunct. >> This is because the parent process is still running and didn't wait >> it. >> So I add a wait_ptid function after ptrace kill. > > You're assuming inferior_ptid is the parent process > of the checkpoint fork, but I don't believe that is always > true. Correct. Maybe we should add a "parent ID" field to the internal checkpoint table? ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [RFA] Checkpoint: wait the defunct process when delete it 2010-05-11 21:50 ` Michael Snyder @ 2010-05-11 22:28 ` Michael Snyder 2010-05-12 0:02 ` Pedro Alves 1 sibling, 0 replies; 23+ messages in thread From: Michael Snyder @ 2010-05-11 22:28 UTC (permalink / raw) To: Pedro Alves; +Cc: gdb-patches, Hui Zhu [-- Attachment #1: Type: text/plain, Size: 702 bytes --] Michael Snyder wrote: > Pedro Alves wrote: >> On Sunday 09 May 2010 07:23:15, Hui Zhu wrote: >> >>> I found that when we delete the checkpoint process, it keep defunct. >>> This is because the parent process is still running and didn't wait >>> it. >>> So I add a wait_ptid function after ptrace kill. >> You're assuming inferior_ptid is the parent process >> of the checkpoint fork, but I don't believe that is always >> true. > > Correct. Maybe we should add a "parent ID" field to the > internal checkpoint table? Hui, Here's a small change that saves the parent PTID. Can you combine this with your change, to make sure that waitpid is called by the correct process? Good luck, Michael [-- Attachment #2: fork.txt --] [-- Type: text/plain, Size: 756 bytes --] Index: linux-fork.c =================================================================== RCS file: /cvs/src/src/gdb/linux-fork.c,v retrieving revision 1.32 diff -u -p -r1.32 linux-fork.c --- linux-fork.c 5 May 2010 20:37:23 -0000 1.32 +++ linux-fork.c 11 May 2010 22:26:08 -0000 @@ -47,6 +47,7 @@ struct fork_info { struct fork_info *next; ptid_t ptid; + ptid_t parent_ptid; int num; /* Convenient handle (GDB fork id) */ struct regcache *savedregs; /* Convenient for info fork, saves having to actually switch contexts. */ @@ -596,6 +597,7 @@ checkpoint_command (char *args, int from if (!fp) error (_("Failed to find new fork")); fork_save_infrun_state (fp, 1); + fp->parent_ptid = last_target_ptid; } static void ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [RFA] Checkpoint: wait the defunct process when delete it 2010-05-11 21:50 ` Michael Snyder 2010-05-11 22:28 ` Michael Snyder @ 2010-05-12 0:02 ` Pedro Alves 1 sibling, 0 replies; 23+ messages in thread From: Pedro Alves @ 2010-05-12 0:02 UTC (permalink / raw) To: gdb-patches; +Cc: Michael Snyder, Hui Zhu On Tuesday 11 May 2010 22:50:26, Michael Snyder wrote: > Pedro Alves wrote: > > On Sunday 09 May 2010 07:23:15, Hui Zhu wrote: > > > >> I found that when we delete the checkpoint process, it keep defunct. > >> This is because the parent process is still running and didn't wait > >> it. > >> So I add a wait_ptid function after ptrace kill. > > > > You're assuming inferior_ptid is the parent process > > of the checkpoint fork, but I don't believe that is always > > true. > > Correct. Maybe we should add a "parent ID" field to the > internal checkpoint table? Sure. -- Pedro Alves ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [RFA] Checkpoint: wait the defunct process when delete it 2010-05-09 6:23 [RFA] Checkpoint: wait the defunct process when delete it Hui Zhu 2010-05-10 19:31 ` Michael Snyder 2010-05-10 23:30 ` Pedro Alves @ 2010-05-11 22:43 ` Michael Snyder 2010-05-12 0:05 ` Pedro Alves 2 siblings, 1 reply; 23+ messages in thread From: Michael Snyder @ 2010-05-11 22:43 UTC (permalink / raw) To: Hui Zhu; +Cc: gdb-patches ml Follow-up to my last reply... Hui Zhu wrote: > Hi, > > I found that when we delete the checkpoint process, it keep defunct. > This is because the parent process is still running and didn't wait > it. > So I add a wait_ptid function after ptrace kill. > > Please help me review it. > > Thanks, > Hui > > 2010-05-09 Hui Zhu <teawater@gmail.com> > > * linux-fork.c (wait_ptid): New function. > (delete_checkpoint_command): Call wait_ptid. > > > --- > linux-fork.c | 32 ++++++++++++++++++++++++++++++++ > 1 file changed, 32 insertions(+) > > --- a/linux-fork.c > +++ b/linux-fork.c > @@ -410,6 +410,35 @@ linux_fork_detach (char *args, int from_ > delete_fork (inferior_ptid); > } > > +static int > +wait_ptid (ptid_t ptid) > +{ > + struct objfile *waitpid_objf; > + struct value *waitpid_fn = NULL; > + struct value *argv[4]; > + struct gdbarch *gdbarch = get_current_arch (); > + > + /* Get the waitpid_fn. */ > + if (lookup_minimal_symbol ("waitpid", NULL, NULL) != NULL) > + waitpid_fn = find_function_in_inferior ("waitpid", &waitpid_objf); > + if (!waitpid_fn) > + if (lookup_minimal_symbol ("_waitpid", NULL, NULL) != NULL) > + waitpid_fn = find_function_in_inferior ("waitpid", &waitpid_objf); > + if (!waitpid_fn) > + return -1; > + > + /* Get the argv. */ > + argv[0] = value_from_longest (builtin_type (gdbarch)->builtin_int, > PIDGET (ptid)); > + argv[1] = value_from_longest (builtin_type (gdbarch)->builtin_int, 0); > + argv[2] = value_from_longest (builtin_type (gdbarch)->builtin_int, 0); > + argv[3] = 0; old_cleanup = save_inferior_ptid (); inferior_ptid = fd->parent_ptid; Something like this? Then the original inferior_ptid will be restored when you do > + if (call_function_by_hand (waitpid_fn, 3, argv) == 0) > + return -1; do_cleanups(); > + return 0; > +} > + > /* Fork list <-> user interface. */ > > static void > @@ -431,6 +460,9 @@ Please switch to another checkpoint befo > if (ptrace (PTRACE_KILL, PIDGET (ptid), 0, 0)) > error (_("Unable to kill pid %s"), target_pid_to_str (ptid)); > > + if (wait_ptid (ptid)) > + error (_("Unable to wait pid %s"), target_pid_to_str (ptid)); > + > if (from_tty) > printf_filtered (_("Killed %s\n"), target_pid_to_str (ptid)); ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [RFA] Checkpoint: wait the defunct process when delete it 2010-05-11 22:43 ` Michael Snyder @ 2010-05-12 0:05 ` Pedro Alves 2010-05-12 0:27 ` Michael Snyder 0 siblings, 1 reply; 23+ messages in thread From: Pedro Alves @ 2010-05-12 0:05 UTC (permalink / raw) To: gdb-patches; +Cc: Michael Snyder, Hui Zhu On Tuesday 11 May 2010 23:43:04, Michael Snyder wrote: > old_cleanup = save_inferior_ptid (); > inferior_ptid = fd->parent_ptid; > > Something like this? Then the original inferior_ptid will be > restored when you do > > > + if (call_function_by_hand (waitpid_fn, 3, argv) == 0) > > + return -1; > > do_cleanups(); > > > + return 0; > > +} That won't work. You will hit an assertion somewhere: either because inferior_ptid is not found in the linux-nat.c lwp list, or because inferior_ptid is not found in gdb's thread list. I believe you'll need to do a full linux_nat_switch_fork and back. -- Pedro Alves ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [RFA] Checkpoint: wait the defunct process when delete it 2010-05-12 0:05 ` Pedro Alves @ 2010-05-12 0:27 ` Michael Snyder 2010-05-12 4:19 ` Hui Zhu 0 siblings, 1 reply; 23+ messages in thread From: Michael Snyder @ 2010-05-12 0:27 UTC (permalink / raw) To: Pedro Alves; +Cc: gdb-patches, Hui Zhu Pedro Alves wrote: > On Tuesday 11 May 2010 23:43:04, Michael Snyder wrote: > > >> old_cleanup = save_inferior_ptid (); >> inferior_ptid = fd->parent_ptid; >> >> Something like this? Then the original inferior_ptid will be >> restored when you do >> >>> + if (call_function_by_hand (waitpid_fn, 3, argv) == 0) >>> + return -1; >> do_cleanups(); >> >>> + return 0; >>> +} > > That won't work. You will hit an assertion somewhere: either because > inferior_ptid is not found in the linux-nat.c lwp list, or because > inferior_ptid is not found in gdb's thread list. I believe you'll > need to do a full linux_nat_switch_fork and back. > There you go. ;-) ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [RFA] Checkpoint: wait the defunct process when delete it 2010-05-12 0:27 ` Michael Snyder @ 2010-05-12 4:19 ` Hui Zhu 2010-05-12 18:39 ` Pedro Alves 0 siblings, 1 reply; 23+ messages in thread From: Hui Zhu @ 2010-05-12 4:19 UTC (permalink / raw) To: Michael Snyder, Pedro Alves; +Cc: gdb-patches On Wed, May 12, 2010 at 08:27, Michael Snyder <msnyder@vmware.com> wrote: > > Pedro Alves wrote: >> >> On Tuesday 11 May 2010 23:43:04, Michael Snyder wrote: >> >> >>> old_cleanup = save_inferior_ptid (); >>> inferior_ptid = fd->parent_ptid; >>> >>> Something like this? Then the original inferior_ptid will be >>> restored when you do >>> >>>> + if (call_function_by_hand (waitpid_fn, 3, argv) == 0) >>>> + return -1; >>> >>> do_cleanups(); >>> >>>> + return 0; >>>> +} >> >> That won't work. You will hit an assertion somewhere: either because >> inferior_ptid is not found in the linux-nat.c lwp list, or because >> inferior_ptid is not found in gdb's thread list. I believe you'll >> need to do a full linux_nat_switch_fork and back. >> > > There you go. ;-) > Hello guys, I am sorry that I didn't complete the new patch yesterday. Thanks for your help. According to your comments. I did following change: 1. Before kill the ptid, GDB switch to ptid and call "inferior_call_getppid" to get the ppid of this inferior. And save it to ppid. 2. before call "inferior_call_waitpid" to waitpid the ptid. Check if ppid is a simple thread. ppid > 1 Check if ppid is the GDB. If ppid is GDB, it will auto wait the ptid. ppid != getpid () Check if ppid is stop. is_stopped (pptid) 3. In function inferior_call_waitpid, before call waitpid, swith to ppid. 4. If inferior_call_waitpid, just give a warning to user. Please help me review it. Best regards, Hui 2010-05-12 Hui Zhu <teawater@gmail.com> * linux-fork.c (gdbthread.h): New include. (inferior_call_getppid, inferior_call_waitpid): New function. (delete_checkpoint_command): Call inferior_call_getppid and inferior_call_waitpid. --- linux-fork.c | 105 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 104 insertions(+), 1 deletion(-) --- a/linux-fork.c +++ b/linux-fork.c @@ -29,6 +29,7 @@ #include "gdb_string.h" #include "linux-fork.h" #include "linux-nat.h" +#include "gdbthread.h" #include <sys/ptrace.h> #include "gdb_wait.h" @@ -410,12 +411,105 @@ linux_fork_detach (char *args, int from_ delete_fork (inferior_ptid); } +static int +inferior_call_getppid (ptid_t ptid) +{ + struct objfile *getppid_objf; + struct value *getppid_fn = NULL, *ret; + struct value *argv[4]; + struct gdbarch *gdbarch = get_current_arch (); + struct fork_info *oldfp, *newfp; + int ppid = 1; + + /* Switch to ptid. */ + oldfp = find_fork_ptid (inferior_ptid); + gdb_assert (oldfp != NULL); + newfp = find_fork_ptid (ptid); + gdb_assert (oldfp != NULL); + fork_save_infrun_state (oldfp, 1); + remove_breakpoints (); + fork_load_infrun_state (newfp); + insert_breakpoints (); + + /* Get the getppid_fn. */ + if (lookup_minimal_symbol ("getppid", NULL, NULL) != NULL) + getppid_fn = find_function_in_inferior ("getppid", &getppid_objf); + if (!getppid_fn && lookup_minimal_symbol ("_getppid", NULL, NULL) != NULL) + getppid_fn = find_function_in_inferior ("_getppid", &getppid_objf); + if (!getppid_fn) + return 1; + + ret = call_function_by_hand (getppid_fn, 0, NULL); + if (ret == 0) + return ppid; + ppid = value_as_long (ret); + + /* Switch back to inferior_ptid. */ + remove_breakpoints (); + fork_load_infrun_state (oldfp); + insert_breakpoints (); + + return ppid; +} + +static int +inferior_call_waitpid (ptid_t pptid, int pid) +{ + struct objfile *waitpid_objf; + struct value *waitpid_fn = NULL; + struct value *argv[4]; + struct gdbarch *gdbarch = get_current_arch (); + struct fork_info *oldfp = NULL, *newfp = NULL; + int ret = 0; + + if (!ptid_equal (pptid, inferior_ptid)) + { + /* Switch to pptid. */ + oldfp = find_fork_ptid (inferior_ptid); + gdb_assert (oldfp != NULL); + newfp = find_fork_ptid (pptid); + gdb_assert (oldfp != NULL); + fork_save_infrun_state (oldfp, 1); + remove_breakpoints (); + fork_load_infrun_state (newfp); + insert_breakpoints (); + } + + /* Get the waitpid_fn. */ + if (lookup_minimal_symbol ("waitpid", NULL, NULL) != NULL) + waitpid_fn = find_function_in_inferior ("waitpid", &waitpid_objf); + if (!waitpid_fn && lookup_minimal_symbol ("_waitpid", NULL, NULL) != NULL) + waitpid_fn = find_function_in_inferior ("_waitpid", &waitpid_objf); + if (!waitpid_fn) + return -1; + + /* Get the argv. */ + argv[0] = value_from_longest (builtin_type (gdbarch)->builtin_int, pid); + argv[1] = value_from_longest (builtin_type (gdbarch)->builtin_data_ptr, 0); + argv[2] = value_from_longest (builtin_type (gdbarch)->builtin_int, 0); + argv[3] = 0; + + if (call_function_by_hand (waitpid_fn, 3, argv) == 0) + ret = -1; + + if (oldfp) + { + /* Switch back to inferior_ptid. */ + remove_breakpoints (); + fork_load_infrun_state (oldfp); + insert_breakpoints (); + } + + return ret; +} + /* Fork list <-> user interface. */ static void delete_checkpoint_command (char *args, int from_tty) { - ptid_t ptid; + ptid_t ptid, pptid; + int ppid; if (!args || !*args) error (_("Requires argument (checkpoint id to delete)")); @@ -428,9 +522,18 @@ delete_checkpoint_command (char *args, i error (_("\ Please switch to another checkpoint before deleting the current one")); + ppid = inferior_call_getppid (ptid); + pptid = ptid_build (ppid, ppid, 0); + if (ptrace (PTRACE_KILL, PIDGET (ptid), 0, 0)) error (_("Unable to kill pid %s"), target_pid_to_str (ptid)); + if (ppid > 1 && ppid != getpid () && is_stopped (pptid)) + { + if (inferior_call_waitpid (pptid, PIDGET (ptid))) + warning (_("Unable to wait pid %s"), target_pid_to_str (ptid)); + } + if (from_tty) printf_filtered (_("Killed %s\n"), target_pid_to_str (ptid)); ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [RFA] Checkpoint: wait the defunct process when delete it 2010-05-12 4:19 ` Hui Zhu @ 2010-05-12 18:39 ` Pedro Alves 2010-05-12 18:57 ` Pedro Alves 2010-05-13 9:11 ` Hui Zhu 0 siblings, 2 replies; 23+ messages in thread From: Pedro Alves @ 2010-05-12 18:39 UTC (permalink / raw) To: Hui Zhu; +Cc: Michael Snyder, gdb-patches On Wednesday 12 May 2010 05:19:25, Hui Zhu wrote: > On Wed, May 12, 2010 at 08:27, Michael Snyder <msnyder@vmware.com> wrote: > > > > Pedro Alves wrote: > >> > >> On Tuesday 11 May 2010 23:43:04, Michael Snyder wrote: > >> > >> > >>> old_cleanup = save_inferior_ptid (); > >>> inferior_ptid = fd->parent_ptid; > >>> > >>> Something like this? Then the original inferior_ptid will be > >>> restored when you do > >>> > >>>> + if (call_function_by_hand (waitpid_fn, 3, argv) == 0) > >>>> + return -1; > >>> > >>> do_cleanups(); > >>> > >>>> + return 0; > >>>> +} > >> > >> That won't work. You will hit an assertion somewhere: either because > >> inferior_ptid is not found in the linux-nat.c lwp list, or because > >> inferior_ptid is not found in gdb's thread list. I believe you'll > >> need to do a full linux_nat_switch_fork and back. > >> > > > > There you go. ;-) > > > > Hello guys, > > I am sorry that I didn't complete the new patch yesterday. Thanks for > your help. > > According to your comments. I did following change: > > 1. Before kill the ptid, GDB switch to ptid and call > "inferior_call_getppid" to get the ppid of this inferior. And save it > to ppid. > > 2. before call "inferior_call_waitpid" to waitpid the ptid. > Check if ppid is a simple thread. ppid > 1 > Check if ppid is the GDB. If ppid is GDB, it will auto wait the ptid. What do you mean, it will auto wait the ptid? AFAICS, (gdb) checkpoint (gdb) checkpoint (gdb) checkpoint (gdb) checkpoint (gdb) checkpoint (gdb) restart 5 (gdb) delete checkpoint 0 will still leave checkpoint 0 zombie? > ppid != getpid () > Check if ppid is stop. is_stopped (pptid) > > 3. In function inferior_call_waitpid, before call waitpid, swith to ppid. > > 4. If inferior_call_waitpid, just give a warning to user. > > Please help me review it. > > Best regards, > Hui > > 2010-05-12 Hui Zhu <teawater@gmail.com> > > * linux-fork.c (gdbthread.h): New include. > (inferior_call_getppid, inferior_call_waitpid): New function. > (delete_checkpoint_command): Call inferior_call_getppid > and inferior_call_waitpid. > > > --- > linux-fork.c | 105 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- > 1 file changed, 104 insertions(+), 1 deletion(-) > > --- a/linux-fork.c > +++ b/linux-fork.c > @@ -29,6 +29,7 @@ > #include "gdb_string.h" > #include "linux-fork.h" > #include "linux-nat.h" > +#include "gdbthread.h" > > #include <sys/ptrace.h> > #include "gdb_wait.h" > @@ -410,12 +411,105 @@ linux_fork_detach (char *args, int from_ > delete_fork (inferior_ptid); > } > > +static int > +inferior_call_getppid (ptid_t ptid) > +{ > + struct objfile *getppid_objf; > + struct value *getppid_fn = NULL, *ret; > + struct value *argv[4]; > + struct gdbarch *gdbarch = get_current_arch (); > + struct fork_info *oldfp, *newfp; > + int ppid = 1; > + > + /* Switch to ptid. */ > + oldfp = find_fork_ptid (inferior_ptid); > + gdb_assert (oldfp != NULL); > + newfp = find_fork_ptid (ptid); > + gdb_assert (oldfp != NULL); > + fork_save_infrun_state (oldfp, 1); > + remove_breakpoints (); > + fork_load_infrun_state (newfp); > + insert_breakpoints (); > + > + /* Get the getppid_fn. */ > + if (lookup_minimal_symbol ("getppid", NULL, NULL) != NULL) > + getppid_fn = find_function_in_inferior ("getppid", &getppid_objf); > + if (!getppid_fn && lookup_minimal_symbol ("_getppid", NULL, NULL) != NULL) > + getppid_fn = find_function_in_inferior ("_getppid", &getppid_objf); > + if (!getppid_fn) > + return 1; > + > + ret = call_function_by_hand (getppid_fn, 0, NULL); > + if (ret == 0) > + return ppid; ??? can getppid really return 0 ? > + ppid = value_as_long (ret); > + > + /* Switch back to inferior_ptid. */ > + remove_breakpoints (); > + fork_load_infrun_state (oldfp); > + insert_breakpoints (); > + > + return ppid; > +} I don't think calling getppid is a great idea. You may not even be debugging the parent process of the process you are about to kill! E.g., say you attach to a process, create a checkpoint, restart the checkpoint, and delete checkpoint 0. getppid will return a pid of a process you are _not_ debugging. You should at least check for that. But, why didn't storing the parent pid at fork time (like was suggested before), work? > + > +static int > +inferior_call_waitpid (ptid_t pptid, int pid) > +{ > + struct objfile *waitpid_objf; > + struct value *waitpid_fn = NULL; > + struct value *argv[4]; > + struct gdbarch *gdbarch = get_current_arch (); > + struct fork_info *oldfp = NULL, *newfp = NULL; > + int ret = 0; > + > + if (!ptid_equal (pptid, inferior_ptid)) > + { > + /* Switch to pptid. */ > + oldfp = find_fork_ptid (inferior_ptid); > + gdb_assert (oldfp != NULL); > + newfp = find_fork_ptid (pptid); > + gdb_assert (oldfp != NULL); > + fork_save_infrun_state (oldfp, 1); > + remove_breakpoints (); > + fork_load_infrun_state (newfp); > + insert_breakpoints (); > + } > + > + /* Get the waitpid_fn. */ > + if (lookup_minimal_symbol ("waitpid", NULL, NULL) != NULL) > + waitpid_fn = find_function_in_inferior ("waitpid", &waitpid_objf); > + if (!waitpid_fn && lookup_minimal_symbol ("_waitpid", NULL, NULL) != NULL) > + waitpid_fn = find_function_in_inferior ("_waitpid", &waitpid_objf); > + if (!waitpid_fn) > + return -1; This early return doesn't switch back to oldfp... I'd prefer to have this switching in and out done by the caller of this function. Can you do that change please? > + > + /* Get the argv. */ > + argv[0] = value_from_longest (builtin_type (gdbarch)->builtin_int, pid); > + argv[1] = value_from_longest (builtin_type (gdbarch)->builtin_data_ptr, 0); value_from_pointer > + argv[2] = value_from_longest (builtin_type (gdbarch)->builtin_int, 0); > + argv[3] = 0; > + > + if (call_function_by_hand (waitpid_fn, 3, argv) == 0) > + ret = -1; > + > + if (oldfp) > + { > + /* Switch back to inferior_ptid. */ > + remove_breakpoints (); > + fork_load_infrun_state (oldfp); > + insert_breakpoints (); > + } > + > + return ret; > +} > + > /* Fork list <-> user interface. */ > > static void > delete_checkpoint_command (char *args, int from_tty) > { > - ptid_t ptid; > + ptid_t ptid, pptid; > + int ppid; > > if (!args || !*args) > error (_("Requires argument (checkpoint id to delete)")); > @@ -428,9 +522,18 @@ delete_checkpoint_command (char *args, i > error (_("\ > Please switch to another checkpoint before deleting the current one")); > > + ppid = inferior_call_getppid (ptid); > + pptid = ptid_build (ppid, ppid, 0); > + > if (ptrace (PTRACE_KILL, PIDGET (ptid), 0, 0)) > error (_("Unable to kill pid %s"), target_pid_to_str (ptid)); > > + if (ppid > 1 && ppid != getpid () && is_stopped (pptid)) > + { > + if (inferior_call_waitpid (pptid, PIDGET (ptid))) > + warning (_("Unable to wait pid %s"), target_pid_to_str (ptid)); > + } > + > if (from_tty) > printf_filtered (_("Killed %s\n"), target_pid_to_str (ptid)); > -- Pedro Alves ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [RFA] Checkpoint: wait the defunct process when delete it 2010-05-12 18:39 ` Pedro Alves @ 2010-05-12 18:57 ` Pedro Alves 2010-05-13 9:11 ` Hui Zhu 1 sibling, 0 replies; 23+ messages in thread From: Pedro Alves @ 2010-05-12 18:57 UTC (permalink / raw) To: Hui Zhu; +Cc: Michael Snyder, gdb-patches On Wednesday 12 May 2010 05:19:25, Hui Zhu wrote: > On Wed, May 12, 2010 at 08:27, Michael Snyder <msnyder@vmware.com> wrote: > > > > Pedro Alves wrote: > >> > >> On Tuesday 11 May 2010 23:43:04, Michael Snyder wrote: > >> > >> > >>> old_cleanup = save_inferior_ptid (); > >>> inferior_ptid = fd->parent_ptid; > >>> > >>> Something like this? Then the original inferior_ptid will be > >>> restored when you do > >>> > >>>> + if (call_function_by_hand (waitpid_fn, 3, argv) == 0) > >>>> + return -1; > >>> > >>> do_cleanups(); > >>> > >>>> + return 0; > >>>> +} > >> > >> That won't work. You will hit an assertion somewhere: either because > >> inferior_ptid is not found in the linux-nat.c lwp list, or because > >> inferior_ptid is not found in gdb's thread list. I believe you'll > >> need to do a full linux_nat_switch_fork and back. > >> > > > > There you go. ;-) > > > > Hello guys, > > I am sorry that I didn't complete the new patch yesterday. Thanks for > your help. > > According to your comments. I did following change: > > 1. Before kill the ptid, GDB switch to ptid and call > "inferior_call_getppid" to get the ppid of this inferior. And save it > to ppid. > > 2. before call "inferior_call_waitpid" to waitpid the ptid. > Check if ppid is a simple thread. ppid > 1 > Check if ppid is the GDB. If ppid is GDB, it will auto wait the ptid. What do you mean, it will auto wait the ptid? AFAICS, (gdb) checkpoint (gdb) checkpoint (gdb) checkpoint (gdb) checkpoint (gdb) checkpoint (gdb) restart 5 (gdb) delete checkpoint 0 will still leave checkpoint 0 zombie? > ppid != getpid () > Check if ppid is stop. is_stopped (pptid) > > 3. In function inferior_call_waitpid, before call waitpid, swith to ppid. > > 4. If inferior_call_waitpid, just give a warning to user. > > Please help me review it. > > Best regards, > Hui > > 2010-05-12 Hui Zhu <teawater@gmail.com> > > * linux-fork.c (gdbthread.h): New include. > (inferior_call_getppid, inferior_call_waitpid): New function. > (delete_checkpoint_command): Call inferior_call_getppid > and inferior_call_waitpid. > > > --- > linux-fork.c | 105 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- > 1 file changed, 104 insertions(+), 1 deletion(-) > > --- a/linux-fork.c > +++ b/linux-fork.c > @@ -29,6 +29,7 @@ > #include "gdb_string.h" > #include "linux-fork.h" > #include "linux-nat.h" > +#include "gdbthread.h" > > #include <sys/ptrace.h> > #include "gdb_wait.h" > @@ -410,12 +411,105 @@ linux_fork_detach (char *args, int from_ > delete_fork (inferior_ptid); > } > > +static int > +inferior_call_getppid (ptid_t ptid) > +{ > + struct objfile *getppid_objf; > + struct value *getppid_fn = NULL, *ret; > + struct value *argv[4]; > + struct gdbarch *gdbarch = get_current_arch (); > + struct fork_info *oldfp, *newfp; > + int ppid = 1; > + > + /* Switch to ptid. */ > + oldfp = find_fork_ptid (inferior_ptid); > + gdb_assert (oldfp != NULL); > + newfp = find_fork_ptid (ptid); > + gdb_assert (oldfp != NULL); > + fork_save_infrun_state (oldfp, 1); > + remove_breakpoints (); > + fork_load_infrun_state (newfp); > + insert_breakpoints (); > + > + /* Get the getppid_fn. */ > + if (lookup_minimal_symbol ("getppid", NULL, NULL) != NULL) > + getppid_fn = find_function_in_inferior ("getppid", &getppid_objf); > + if (!getppid_fn && lookup_minimal_symbol ("_getppid", NULL, NULL) != NULL) > + getppid_fn = find_function_in_inferior ("_getppid", &getppid_objf); > + if (!getppid_fn) > + return 1; > + > + ret = call_function_by_hand (getppid_fn, 0, NULL); > + if (ret == 0) > + return ppid; ??? can getppid really return 0 ? > + ppid = value_as_long (ret); > + > + /* Switch back to inferior_ptid. */ > + remove_breakpoints (); > + fork_load_infrun_state (oldfp); > + insert_breakpoints (); > + > + return ppid; > +} I don't think calling getppid is a great idea. You may not even be debugging the parent process of the process you are about to kill! E.g., say you attach to a process, create a checkpoint, restart the checkpoint, and delete checkpoint 0. getppid will return a pid of a process you are _not_ debugging. You should at least check for that. But, why didn't storing the parent pid at fork time (like was suggested before), work? > + > +static int > +inferior_call_waitpid (ptid_t pptid, int pid) > +{ > + struct objfile *waitpid_objf; > + struct value *waitpid_fn = NULL; > + struct value *argv[4]; > + struct gdbarch *gdbarch = get_current_arch (); > + struct fork_info *oldfp = NULL, *newfp = NULL; > + int ret = 0; > + > + if (!ptid_equal (pptid, inferior_ptid)) > + { > + /* Switch to pptid. */ > + oldfp = find_fork_ptid (inferior_ptid); > + gdb_assert (oldfp != NULL); > + newfp = find_fork_ptid (pptid); > + gdb_assert (oldfp != NULL); > + fork_save_infrun_state (oldfp, 1); > + remove_breakpoints (); > + fork_load_infrun_state (newfp); > + insert_breakpoints (); > + } > + > + /* Get the waitpid_fn. */ > + if (lookup_minimal_symbol ("waitpid", NULL, NULL) != NULL) > + waitpid_fn = find_function_in_inferior ("waitpid", &waitpid_objf); > + if (!waitpid_fn && lookup_minimal_symbol ("_waitpid", NULL, NULL) != NULL) > + waitpid_fn = find_function_in_inferior ("_waitpid", &waitpid_objf); > + if (!waitpid_fn) > + return -1; This early return doesn't switch back to oldfp... I'd prefer to have this switching in and out done by the caller of this function. Can you do that change please? > + > + /* Get the argv. */ > + argv[0] = value_from_longest (builtin_type (gdbarch)->builtin_int, pid); > + argv[1] = value_from_longest (builtin_type (gdbarch)->builtin_data_ptr, 0); value_from_pointer > + argv[2] = value_from_longest (builtin_type (gdbarch)->builtin_int, 0); > + argv[3] = 0; > + > + if (call_function_by_hand (waitpid_fn, 3, argv) == 0) > + ret = -1; > + > + if (oldfp) > + { > + /* Switch back to inferior_ptid. */ > + remove_breakpoints (); > + fork_load_infrun_state (oldfp); > + insert_breakpoints (); > + } > + > + return ret; > +} > + > /* Fork list <-> user interface. */ > > static void > delete_checkpoint_command (char *args, int from_tty) > { > - ptid_t ptid; > + ptid_t ptid, pptid; > + int ppid; > > if (!args || !*args) > error (_("Requires argument (checkpoint id to delete)")); > @@ -428,9 +522,18 @@ delete_checkpoint_command (char *args, i > error (_("\ > Please switch to another checkpoint before deleting the current one")); > > + ppid = inferior_call_getppid (ptid); > + pptid = ptid_build (ppid, ppid, 0); > + > if (ptrace (PTRACE_KILL, PIDGET (ptid), 0, 0)) > error (_("Unable to kill pid %s"), target_pid_to_str (ptid)); > > + if (ppid > 1 && ppid != getpid () && is_stopped (pptid)) > + { > + if (inferior_call_waitpid (pptid, PIDGET (ptid))) > + warning (_("Unable to wait pid %s"), target_pid_to_str (ptid)); > + } > + > if (from_tty) > printf_filtered (_("Killed %s\n"), target_pid_to_str (ptid)); > -- Pedro Alves ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [RFA] Checkpoint: wait the defunct process when delete it 2010-05-12 18:39 ` Pedro Alves 2010-05-12 18:57 ` Pedro Alves @ 2010-05-13 9:11 ` Hui Zhu 2010-05-13 11:50 ` Pedro Alves 1 sibling, 1 reply; 23+ messages in thread From: Hui Zhu @ 2010-05-13 9:11 UTC (permalink / raw) To: Pedro Alves; +Cc: Michael Snyder, gdb-patches On Thu, May 13, 2010 at 02:37, Pedro Alves <pedro@codesourcery.com> wrote: > On Wednesday 12 May 2010 05:19:25, Hui Zhu wrote: >> On Wed, May 12, 2010 at 08:27, Michael Snyder <msnyder@vmware.com> wrote: >> > >> > Pedro Alves wrote: >> >> >> >> On Tuesday 11 May 2010 23:43:04, Michael Snyder wrote: >> >> >> >> >> >>> old_cleanup = save_inferior_ptid (); >> >>> inferior_ptid = fd->parent_ptid; >> >>> >> >>> Something like this? Then the original inferior_ptid will be >> >>> restored when you do >> >>> >> >>>> + if (call_function_by_hand (waitpid_fn, 3, argv) == 0) >> >>>> + return -1; >> >>> >> >>> do_cleanups(); >> >>> >> >>>> + return 0; >> >>>> +} >> >> >> >> That won't work. You will hit an assertion somewhere: either because >> >> inferior_ptid is not found in the linux-nat.c lwp list, or because >> >> inferior_ptid is not found in gdb's thread list. I believe you'll >> >> need to do a full linux_nat_switch_fork and back. >> >> >> > >> > There you go. ;-) >> > >> >> Hello guys, >> >> I am sorry that I didn't complete the new patch yesterday. Thanks for >> your help. >> >> According to your comments. I did following change: >> >> 1. Before kill the ptid, GDB switch to ptid and call >> "inferior_call_getppid" to get the ppid of this inferior. And save it >> to ppid. >> >> 2. before call "inferior_call_waitpid" to waitpid the ptid. >> Check if ppid is a simple thread. ppid > 1 >> Check if ppid is the GDB. If ppid is GDB, it will auto wait the ptid. > > What do you mean, it will auto wait the ptid? AFAICS, > > (gdb) checkpoint > (gdb) checkpoint > (gdb) checkpoint > (gdb) checkpoint > (gdb) checkpoint > (gdb) restart 5 > (gdb) delete checkpoint 0 > > will still leave checkpoint 0 zombie? This is because the parent of checkpoint is GDB. GDB will auto wait the zombie, so I just leave them there let GDB hanle it. > >> ppid != getpid () >> Check if ppid is stop. is_stopped (pptid) >> >> 3. In function inferior_call_waitpid, before call waitpid, swith to ppid. >> >> 4. If inferior_call_waitpid, just give a warning to user. >> >> Please help me review it. >> >> Best regards, >> Hui >> >> 2010-05-12 Hui Zhu <teawater@gmail.com> >> >> * linux-fork.c (gdbthread.h): New include. >> (inferior_call_getppid, inferior_call_waitpid): New function. >> (delete_checkpoint_command): Call inferior_call_getppid >> and inferior_call_waitpid. >> >> >> --- >> linux-fork.c | 105 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- >> 1 file changed, 104 insertions(+), 1 deletion(-) >> >> --- a/linux-fork.c >> +++ b/linux-fork.c >> @@ -29,6 +29,7 @@ >> #include "gdb_string.h" >> #include "linux-fork.h" >> #include "linux-nat.h" >> +#include "gdbthread.h" >> >> #include <sys/ptrace.h> >> #include "gdb_wait.h" >> @@ -410,12 +411,105 @@ linux_fork_detach (char *args, int from_ >> delete_fork (inferior_ptid); >> } >> >> +static int >> +inferior_call_getppid (ptid_t ptid) >> +{ >> + struct objfile *getppid_objf; >> + struct value *getppid_fn = NULL, *ret; >> + struct value *argv[4]; >> + struct gdbarch *gdbarch = get_current_arch (); >> + struct fork_info *oldfp, *newfp; >> + int ppid = 1; >> + >> + /* Switch to ptid. */ >> + oldfp = find_fork_ptid (inferior_ptid); >> + gdb_assert (oldfp != NULL); >> + newfp = find_fork_ptid (ptid); >> + gdb_assert (oldfp != NULL); >> + fork_save_infrun_state (oldfp, 1); >> + remove_breakpoints (); >> + fork_load_infrun_state (newfp); >> + insert_breakpoints (); >> + >> + /* Get the getppid_fn. */ >> + if (lookup_minimal_symbol ("getppid", NULL, NULL) != NULL) >> + getppid_fn = find_function_in_inferior ("getppid", &getppid_objf); >> + if (!getppid_fn && lookup_minimal_symbol ("_getppid", NULL, NULL) != NULL) >> + getppid_fn = find_function_in_inferior ("_getppid", &getppid_objf); >> + if (!getppid_fn) >> + return 1; >> + >> + ret = call_function_by_hand (getppid_fn, 0, NULL); >> + if (ret == 0) >> + return ppid; > > ??? can getppid really return 0 ? This 0 is not the return value of getppid. This is how function "checkpoint_command" use this function. Check it just for code safe. :) ret = call_function_by_hand (fork_fn, 0, &ret); do_cleanups (old_chain); if (!ret) /* Probably can't happen. */ error (_("checkpoint: call_function_by_hand returned null.")); > >> + ppid = value_as_long (ret); >> + >> + /* Switch back to inferior_ptid. */ >> + remove_breakpoints (); >> + fork_load_infrun_state (oldfp); >> + insert_breakpoints (); >> + >> + return ppid; >> +} > > I don't think calling getppid is a great idea. You may not > even be debugging the parent process of the process you are > about to kill! E.g., say you attach to a process, create a checkpoint, > restart the checkpoint, and delete checkpoint 0. getppid will return > a pid of a process you are _not_ debugging. You should at least > check for that. But, why didn't storing the parent pid > at fork time (like was suggested before), work? > I agree with you. getppid is too cumbersome. I will update the patch. >> + >> +static int >> +inferior_call_waitpid (ptid_t pptid, int pid) >> +{ >> + struct objfile *waitpid_objf; >> + struct value *waitpid_fn = NULL; >> + struct value *argv[4]; >> + struct gdbarch *gdbarch = get_current_arch (); >> + struct fork_info *oldfp = NULL, *newfp = NULL; >> + int ret = 0; >> + >> + if (!ptid_equal (pptid, inferior_ptid)) >> + { >> + /* Switch to pptid. */ >> + oldfp = find_fork_ptid (inferior_ptid); >> + gdb_assert (oldfp != NULL); >> + newfp = find_fork_ptid (pptid); >> + gdb_assert (oldfp != NULL); >> + fork_save_infrun_state (oldfp, 1); >> + remove_breakpoints (); >> + fork_load_infrun_state (newfp); >> + insert_breakpoints (); >> + } >> + >> + /* Get the waitpid_fn. */ >> + if (lookup_minimal_symbol ("waitpid", NULL, NULL) != NULL) >> + waitpid_fn = find_function_in_inferior ("waitpid", &waitpid_objf); >> + if (!waitpid_fn && lookup_minimal_symbol ("_waitpid", NULL, NULL) != NULL) >> + waitpid_fn = find_function_in_inferior ("_waitpid", &waitpid_objf); >> + if (!waitpid_fn) >> + return -1; > > This early return doesn't switch back to oldfp... I'd prefer to > have this switching in and out done by the caller of this function. > Can you do that change please? OK. I will fix it. > >> + >> + /* Get the argv. */ >> + argv[0] = value_from_longest (builtin_type (gdbarch)->builtin_int, pid); >> + argv[1] = value_from_longest (builtin_type (gdbarch)->builtin_data_ptr, 0); > > value_from_pointer > >> + argv[2] = value_from_longest (builtin_type (gdbarch)->builtin_int, 0); >> + argv[3] = 0; >> + >> + if (call_function_by_hand (waitpid_fn, 3, argv) == 0) >> + ret = -1; >> + >> + if (oldfp) >> + { >> + /* Switch back to inferior_ptid. */ >> + remove_breakpoints (); >> + fork_load_infrun_state (oldfp); >> + insert_breakpoints (); >> + } >> + >> + return ret; >> +} >> + >> /* Fork list <-> user interface. */ >> >> static void >> delete_checkpoint_command (char *args, int from_tty) >> { >> - ptid_t ptid; >> + ptid_t ptid, pptid; >> + int ppid; >> >> if (!args || !*args) >> error (_("Requires argument (checkpoint id to delete)")); >> @@ -428,9 +522,18 @@ delete_checkpoint_command (char *args, i >> error (_("\ >> Please switch to another checkpoint before deleting the current one")); >> >> + ppid = inferior_call_getppid (ptid); >> + pptid = ptid_build (ppid, ppid, 0); >> + >> if (ptrace (PTRACE_KILL, PIDGET (ptid), 0, 0)) >> error (_("Unable to kill pid %s"), target_pid_to_str (ptid)); >> >> + if (ppid > 1 && ppid != getpid () && is_stopped (pptid)) >> + { >> + if (inferior_call_waitpid (pptid, PIDGET (ptid))) >> + warning (_("Unable to wait pid %s"), target_pid_to_str (ptid)); >> + } >> + >> if (from_tty) >> printf_filtered (_("Killed %s\n"), target_pid_to_str (ptid)); >> > I make a new patch according to your mail. Please help me review it. Thanks, Hui 2010-05-13 Hui Zhu <teawater@gmail.com> Michael Snyder <msnyder@vmware.com> * linux-fork.c (gdbthread.h): New include. (fork_info): Add parent_ptid. (inferior_call_waitpid): New function. (delete_checkpoint_command): Call inferior_call_getppid and inferior_call_waitpid. (checkpoint_command): Set parent_ptid. --- linux-fork.c | 67 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) --- a/linux-fork.c +++ b/linux-fork.c @@ -29,6 +29,7 @@ #include "gdb_string.h" #include "linux-fork.h" #include "linux-nat.h" +#include "gdbthread.h" #include <sys/ptrace.h> #include "gdb_wait.h" @@ -47,6 +48,7 @@ struct fork_info { struct fork_info *next; ptid_t ptid; + ptid_t parent_ptid; int num; /* Convenient handle (GDB fork id) */ struct regcache *savedregs; /* Convenient for info fork, saves having to actually switch contexts. */ @@ -410,12 +412,66 @@ linux_fork_detach (char *args, int from_ delete_fork (inferior_ptid); } +static int +inferior_call_waitpid (ptid_t pptid, int pid) +{ + struct objfile *waitpid_objf; + struct value *waitpid_fn = NULL; + struct value *argv[4]; + struct gdbarch *gdbarch = get_current_arch (); + struct fork_info *oldfp = NULL, *newfp = NULL; + int ret = -1; + + if (!ptid_equal (pptid, inferior_ptid)) + { + /* Switch to pptid. */ + oldfp = find_fork_ptid (inferior_ptid); + gdb_assert (oldfp != NULL); + newfp = find_fork_ptid (pptid); + gdb_assert (oldfp != NULL); + fork_save_infrun_state (oldfp, 1); + remove_breakpoints (); + fork_load_infrun_state (newfp); + insert_breakpoints (); + } + + /* Get the waitpid_fn. */ + if (lookup_minimal_symbol ("waitpid", NULL, NULL) != NULL) + waitpid_fn = find_function_in_inferior ("waitpid", &waitpid_objf); + if (!waitpid_fn && lookup_minimal_symbol ("_waitpid", NULL, NULL) != NULL) + waitpid_fn = find_function_in_inferior ("_waitpid", &waitpid_objf); + if (!waitpid_fn) + goto out; + + /* Get the argv. */ + argv[0] = value_from_longest (builtin_type (gdbarch)->builtin_int, pid); + argv[1] = value_from_pointer (builtin_type (gdbarch)->builtin_data_ptr, 0); + argv[2] = value_from_longest (builtin_type (gdbarch)->builtin_int, 0); + argv[3] = 0; + + if (call_function_by_hand (waitpid_fn, 3, argv) == 0) + goto out; + + ret = 0; + +out: + if (oldfp) + { + /* Switch back to inferior_ptid. */ + remove_breakpoints (); + fork_load_infrun_state (oldfp); + insert_breakpoints (); + } + return ret; +} + /* Fork list <-> user interface. */ static void delete_checkpoint_command (char *args, int from_tty) { ptid_t ptid; + struct fork_info *fi; if (!args || !*args) error (_("Requires argument (checkpoint id to delete)")); @@ -431,6 +487,16 @@ Please switch to another checkpoint befo if (ptrace (PTRACE_KILL, PIDGET (ptid), 0, 0)) error (_("Unable to kill pid %s"), target_pid_to_str (ptid)); + fi = find_fork_ptid (ptid); + gdb_assert (fi); + + if ((!find_thread_ptid (fi->parent_ptid) && find_fork_ptid (fi->parent_ptid)) + || (find_thread_ptid (fi->parent_ptid) && is_stopped (fi->parent_ptid))) + { + if (inferior_call_waitpid (fi->parent_ptid, PIDGET (ptid))) + warning (_("Unable to wait pid %s"), target_pid_to_str (ptid)); + } + if (from_tty) printf_filtered (_("Killed %s\n"), target_pid_to_str (ptid)); @@ -596,6 +662,7 @@ checkpoint_command (char *args, int from if (!fp) error (_("Failed to find new fork")); fork_save_infrun_state (fp, 1); + fp->parent_ptid = last_target_ptid; } static void ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [RFA] Checkpoint: wait the defunct process when delete it 2010-05-13 9:11 ` Hui Zhu @ 2010-05-13 11:50 ` Pedro Alves 2010-05-14 11:05 ` Hui Zhu 0 siblings, 1 reply; 23+ messages in thread From: Pedro Alves @ 2010-05-13 11:50 UTC (permalink / raw) To: Hui Zhu; +Cc: Michael Snyder, gdb-patches On Thursday 13 May 2010 08:58:49, Hui Zhu wrote: > >> 2. before call "inferior_call_waitpid" to waitpid the ptid. > >> Check if ppid is a simple thread. ppid > 1 > >> Check if ppid is the GDB. If ppid is GDB, it will auto wait the ptid. > > > > What do you mean, it will auto wait the ptid? AFAICS, > > > > (gdb) checkpoint > > (gdb) checkpoint > > (gdb) checkpoint > > (gdb) checkpoint > > (gdb) checkpoint > > (gdb) restart 5 > > (gdb) delete checkpoint 0 > > > > will still leave checkpoint 0 zombie? > > This is because the parent of checkpoint is GDB. GDB will auto wait > the zombie, so I just leave them there let GDB hanle it. You didn't answer the question. Please point me at where is this "gdb auto waiting". I actually don't understand that rationale. The `init' process will "auto wait" the checkpoint forks as well, so why bother in the first place then? > + if ((!find_thread_ptid (fi->parent_ptid) && find_fork_ptid (fi->parent_ptid)) > + || (find_thread_ptid (fi->parent_ptid) && is_stopped (fi->parent_ptid))) This requires an explaning comment in the code. > >> + > >> + ret = call_function_by_hand (getppid_fn, 0, NULL); > >> + if (ret == 0) > >> + return ppid; > > > > ??? can getppid really return 0 ? > > This 0 is not the return value of getppid. Oh, right. :-) > This is how function "checkpoint_command" use this function. Check it > just for code safe. :) > ret = call_function_by_hand (fork_fn, 0, &ret); > do_cleanups (old_chain); > if (!ret) /* Probably can't happen. */ > error (_("checkpoint: call_function_by_hand returned null.")); Well, the only return from call_function_by_hand does: gdb_assert (retval); return retval; All other cases are handled by throwing an error. So "definitely can't happen"; please remove the new dead code you're adding. BTW, you patch is not error/exception safe. You didn't consider the case of an `error' being thrown between switching the fork and back. Otherwise, the patch looks good. -- Pedro Alves ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [RFA] Checkpoint: wait the defunct process when delete it 2010-05-13 11:50 ` Pedro Alves @ 2010-05-14 11:05 ` Hui Zhu 2010-05-14 14:43 ` Pedro Alves 0 siblings, 1 reply; 23+ messages in thread From: Hui Zhu @ 2010-05-14 11:05 UTC (permalink / raw) To: Pedro Alves; +Cc: Michael Snyder, gdb-patches On Thu, May 13, 2010 at 18:30, Pedro Alves <pedro@codesourcery.com> wrote: > > On Thursday 13 May 2010 08:58:49, Hui Zhu wrote: > > >> 2. before call "inferior_call_waitpid" to waitpid the ptid. > > >> Check if ppid is a simple thread. ppid > 1 > > >> Check if ppid is the GDB. If ppid is GDB, it will auto wait the ptid. > > > > > > What do you mean, it will auto wait the ptid? AFAICS, > > > > > > (gdb) checkpoint > > > (gdb) checkpoint > > > (gdb) checkpoint > > > (gdb) checkpoint > > > (gdb) checkpoint > > > (gdb) restart 5 > > > (gdb) delete checkpoint 0 > > > > > > will still leave checkpoint 0 zombie? > > > > This is because the parent of checkpoint is GDB. GDB will auto wait > > the zombie, so I just leave them there let GDB hanle it. > > You didn't answer the question. Please point me at where is > this "gdb auto waiting". > > I actually don't understand that rationale. The `init' process > will "auto wait" the checkpoint forks as well, so why bother in > the first place then? > my_waitpid with -1 will handle them. And looks if we don't call getppid, we will not have a good way to make sure if > > + if ((!find_thread_ptid (fi->parent_ptid) && find_fork_ptid (fi->parent_ptid)) > > + || (find_thread_ptid (fi->parent_ptid) && is_stopped (fi->parent_ptid))) > > This requires an explaning comment in the code. OK. I will add them. > > > >> + > > >> + ret = call_function_by_hand (getppid_fn, 0, NULL); > > >> + if (ret == 0) > > >> + return ppid; > > > > > > ??? can getppid really return 0 ? > > > > This 0 is not the return value of getppid. > > Oh, right. :-) > > > This is how function "checkpoint_command" use this function. Check it > > just for code safe. :) > > ret = call_function_by_hand (fork_fn, 0, &ret); > > do_cleanups (old_chain); > > if (!ret) /* Probably can't happen. */ > > error (_("checkpoint: call_function_by_hand returned null.")); > > Well, the only return from call_function_by_hand does: > > gdb_assert (retval); > return retval; > > All other cases are handled by throwing an error. So > "definitely can't happen"; please remove the new dead code > you're adding. Thanks. I will fix it. > > BTW, you patch is not error/exception safe. You didn't consider > the case of an `error' being thrown between switching the > fork and back. Thanks for alarm me about it. I have add a inferior_call_waitpid_cleanup to clean up And move inferior_call_waitpid to the end of function delete_checkpoint_command. Then it will not affect inferior_ptid and delete_fork (ptid); > > Otherwise, the patch looks good. Thanks. I fixed them all and checked in. Best regards, Hui 2010-05-14 Hui Zhu <teawater@gmail.com> Michael Snyder <msnyder@vmware.com> * linux-fork.c (gdbthread.h): New include. (fork_info): Add parent_ptid. (inferior_call_waitpid_cleanup, inferior_call_waitpid): New functions. (delete_checkpoint_command): Call inferior_call_waitpid. (checkpoint_command): Set parent_ptid. --- linux-fork.c | 79 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 79 insertions(+) --- a/linux-fork.c +++ b/linux-fork.c @@ -29,6 +29,7 @@ #include "gdb_string.h" #include "linux-fork.h" #include "linux-nat.h" +#include "gdbthread.h" #include <sys/ptrace.h> #include "gdb_wait.h" @@ -47,6 +48,7 @@ struct fork_info { struct fork_info *next; ptid_t ptid; + ptid_t parent_ptid; int num; /* Convenient handle (GDB fork id) */ struct regcache *savedregs; /* Convenient for info fork, saves having to actually switch contexts. */ @@ -410,12 +412,74 @@ linux_fork_detach (char *args, int from_ delete_fork (inferior_ptid); } +static void +inferior_call_waitpid_cleanup (void *fp) +{ + struct fork_info *oldfp = fp; + + /* Switch back to inferior_ptid. */ + remove_breakpoints (); + fork_load_infrun_state (oldfp); + insert_breakpoints (); +} + +static int +inferior_call_waitpid (ptid_t pptid, int pid) +{ + struct objfile *waitpid_objf; + struct value *waitpid_fn = NULL; + struct value *argv[4]; + struct gdbarch *gdbarch = get_current_arch (); + struct fork_info *oldfp = NULL, *newfp = NULL; + struct cleanup *old_cleanup = NULL; + int ret = -1; + + if (!ptid_equal (pptid, inferior_ptid)) + { + /* Switch to pptid. */ + oldfp = find_fork_ptid (inferior_ptid); + gdb_assert (oldfp != NULL); + newfp = find_fork_ptid (pptid); + gdb_assert (oldfp != NULL); + fork_save_infrun_state (oldfp, 1); + remove_breakpoints (); + fork_load_infrun_state (newfp); + insert_breakpoints (); + + old_cleanup = make_cleanup (inferior_call_waitpid_cleanup, oldfp); + } + + /* Get the waitpid_fn. */ + if (lookup_minimal_symbol ("waitpid", NULL, NULL) != NULL) + waitpid_fn = find_function_in_inferior ("waitpid", &waitpid_objf); + if (!waitpid_fn && lookup_minimal_symbol ("_waitpid", NULL, NULL) != NULL) + waitpid_fn = find_function_in_inferior ("_waitpid", &waitpid_objf); + if (!waitpid_fn) + goto out; + + /* Get the argv. */ + argv[0] = value_from_longest (builtin_type (gdbarch)->builtin_int, pid); + argv[1] = value_from_pointer (builtin_type (gdbarch)->builtin_data_ptr, 0); + argv[2] = value_from_longest (builtin_type (gdbarch)->builtin_int, 0); + argv[3] = 0; + + call_function_by_hand (waitpid_fn, 3, argv); + + ret = 0; + +out: + if (old_cleanup) + do_cleanups (old_cleanup); + return ret; +} + /* Fork list <-> user interface. */ static void delete_checkpoint_command (char *args, int from_tty) { ptid_t ptid; + struct fork_info *fi; if (!args || !*args) error (_("Requires argument (checkpoint id to delete)")); @@ -431,10 +495,24 @@ Please switch to another checkpoint befo if (ptrace (PTRACE_KILL, PIDGET (ptid), 0, 0)) error (_("Unable to kill pid %s"), target_pid_to_str (ptid)); + fi = find_fork_ptid (ptid); + gdb_assert (fi); + if (from_tty) printf_filtered (_("Killed %s\n"), target_pid_to_str (ptid)); delete_fork (ptid); + + /* If fi->parent_ptid is not a part of lwp but it's a part of checkpoint + list, waitpid the ptid. + If fi->parent_ptid is a part of lwp and it is stoped, waitpid the + ptid. */ + if ((!find_thread_ptid (fi->parent_ptid) && find_fork_ptid (fi->parent_ptid)) + || (find_thread_ptid (fi->parent_ptid) && is_stopped (fi->parent_ptid))) + { + if (inferior_call_waitpid (fi->parent_ptid, PIDGET (ptid))) + warning (_("Unable to wait pid %s"), target_pid_to_str (ptid)); + } } static void @@ -596,6 +674,7 @@ checkpoint_command (char *args, int from if (!fp) error (_("Failed to find new fork")); fork_save_infrun_state (fp, 1); + fp->parent_ptid = last_target_ptid; } static void ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [RFA] Checkpoint: wait the defunct process when delete it 2010-05-14 11:05 ` Hui Zhu @ 2010-05-14 14:43 ` Pedro Alves 2010-05-14 15:08 ` Hui Zhu 0 siblings, 1 reply; 23+ messages in thread From: Pedro Alves @ 2010-05-14 14:43 UTC (permalink / raw) To: Hui Zhu; +Cc: Michael Snyder, gdb-patches On Friday 14 May 2010 07:39:17, Hui Zhu wrote: > > BTW, you patch is not error/exception safe. You didn't consider > > the case of an `error' being thrown between switching the > > fork and back. > > Thanks for alarm me about it. I have add a > inferior_call_waitpid_cleanup to clean up And move > inferior_call_waitpid to the end of function > delete_checkpoint_command. Then it will not affect inferior_ptid and > delete_fork (ptid); You're now accessing the FI pointer after having just deleted it. The delete_fork(ptid) line deletes FI. > + fi = find_fork_ptid (ptid); > + gdb_assert (fi); > + > if (from_tty) > printf_filtered (_("Killed %s\n"), target_pid_to_str (ptid)); > > delete_fork (ptid); > + > + /* If fi->parent_ptid is not a part of lwp but it's a part of checkpoint > + list, waitpid the ptid. > + If fi->parent_ptid is a part of lwp and it is stoped, waitpid the > + ptid. */ > + if ((!find_thread_ptid (fi->parent_ptid) && find_fork_ptid (fi->parent_ptid)) > + || (find_thread_ptid (fi->parent_ptid) && is_stopped (fi->parent_ptid))) > + { > + if (inferior_call_waitpid (fi->parent_ptid, PIDGET (ptid))) > + warning (_("Unable to wait pid %s"), target_pid_to_str (ptid)); > + } > } > +static int > +inferior_call_waitpid (ptid_t pptid, int pid) > +{ > + struct objfile *waitpid_objf; > + struct value *waitpid_fn = NULL; > + struct value *argv[4]; > + struct gdbarch *gdbarch = get_current_arch (); > + struct fork_info *oldfp = NULL, *newfp = NULL; > + struct cleanup *old_cleanup = NULL; if (...) { > + old_cleanup = make_cleanup (inferior_call_waitpid_cleanup, oldfp); > + } > + > + if (old_cleanup) > + do_cleanups (old_cleanup); Please do not use this check-for-NULL-cleanup pattern anywhere. You should install a null_cleanup instead, and unconditionally run the cleanups. You should _never_ rely on old_cleanup being NULL to mean you haven't installed a cleanup above. The reason is that the old_cleanup = make_cleanup (inferior_call_waitpid_cleanup, oldfp); line may well return NULL, because NULL was the head of the cleanup chain when the first cleanup is registered, and that's what make_cleanup returns, the previous head of the chain. To convince yourself, put a breakpoint on make_my_cleanup and run gdb. Step out and check what is the old_chain value that ends up stored in the caller. > + return ret; > +} I see you dropped extracting the return value of the waitpid call, in addition to the dead code. Was that on purpose? It's fine either way, just pointing it out in case it slipped. -- Pedro Alves ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [RFA] Checkpoint: wait the defunct process when delete it 2010-05-14 14:43 ` Pedro Alves @ 2010-05-14 15:08 ` Hui Zhu 2010-05-14 16:19 ` Pedro Alves 2010-05-14 19:29 ` Michael Snyder 0 siblings, 2 replies; 23+ messages in thread From: Hui Zhu @ 2010-05-14 15:08 UTC (permalink / raw) To: Pedro Alves; +Cc: Michael Snyder, gdb-patches Thanks Pedro. On Fri, May 14, 2010 at 20:20, Pedro Alves <pedro@codesourcery.com> wrote: > On Friday 14 May 2010 07:39:17, Hui Zhu wrote: > >> > BTW, you patch is not error/exception safe. You didn't consider >> > the case of an `error' being thrown between switching the >> > fork and back. >> >> Thanks for alarm me about it. I have add a >> inferior_call_waitpid_cleanup to clean up And move >> inferior_call_waitpid to the end of function >> delete_checkpoint_command. Then it will not affect inferior_ptid and >> delete_fork (ptid); > > You're now accessing the FI pointer after having just deleted it. The > delete_fork(ptid) line deletes FI. Faint. I will fix it. > >> + fi = find_fork_ptid (ptid); >> + gdb_assert (fi); >> + >> if (from_tty) >> printf_filtered (_("Killed %s\n"), target_pid_to_str (ptid)); >> >> delete_fork (ptid); >> + >> + /* If fi->parent_ptid is not a part of lwp but it's a part of checkpoint >> + list, waitpid the ptid. >> + If fi->parent_ptid is a part of lwp and it is stoped, waitpid the >> + ptid. */ >> + if ((!find_thread_ptid (fi->parent_ptid) && find_fork_ptid (fi->parent_ptid)) >> + || (find_thread_ptid (fi->parent_ptid) && is_stopped (fi->parent_ptid))) >> + { >> + if (inferior_call_waitpid (fi->parent_ptid, PIDGET (ptid))) >> + warning (_("Unable to wait pid %s"), target_pid_to_str (ptid)); >> + } >> } > > >> +static int >> +inferior_call_waitpid (ptid_t pptid, int pid) >> +{ >> + struct objfile *waitpid_objf; >> + struct value *waitpid_fn = NULL; >> + struct value *argv[4]; >> + struct gdbarch *gdbarch = get_current_arch (); >> + struct fork_info *oldfp = NULL, *newfp = NULL; >> + struct cleanup *old_cleanup = NULL; > > if (...) > { >> + old_cleanup = make_cleanup (inferior_call_waitpid_cleanup, oldfp); >> + } >> + >> + if (old_cleanup) >> + do_cleanups (old_cleanup); > > Please do not use this check-for-NULL-cleanup pattern anywhere. > You should install a null_cleanup instead, and unconditionally run > the cleanups. You should _never_ rely on old_cleanup being > NULL to mean you haven't installed a cleanup above. The reason > is that the > > old_cleanup = make_cleanup (inferior_call_waitpid_cleanup, oldfp); > > line may well return NULL, because NULL was the head of > the cleanup chain when the first cleanup is registered, and that's > what make_cleanup returns, the previous head of the chain. > > To convince yourself, put a breakpoint on make_my_cleanup > and run gdb. Step out and check what is the old_chain value > that ends up stored in the caller. Thanks for told it so clear. I will fix it. > >> + return ret; >> +} > > I see you dropped extracting the return value of the waitpid > call, in addition to the dead code. Was that on purpose? It's > fine either way, just pointing it out in case it slipped. In before I just want check the return value of call_function_by_hand but didn't check the waitpid return value. So I just removed the check code. But add check for waitpid is not a big work, so I will add code for it. > > -- > Pedro Alves > I make a patch for cvs-head. Please help me review it. Best regards, Hui 2010-05-14 Hui Zhu <teawater@gmail.com> * linux-fork.c (inferior_call_waitpid_cleanup): Add check for oldfp. (inferior_call_waitpid): Move make_cleanup out of check. Check the return of waitpid. (delete_checkpoint_command): Add pptid to save fi->parent_ptid. --- linux-fork.c | 35 ++++++++++++++++++++--------------- 1 file changed, 20 insertions(+), 15 deletions(-) --- a/linux-fork.c +++ b/linux-fork.c @@ -417,10 +417,13 @@ inferior_call_waitpid_cleanup (void *fp) { struct fork_info *oldfp = fp; - /* Switch back to inferior_ptid. */ - remove_breakpoints (); - fork_load_infrun_state (oldfp); - insert_breakpoints (); + if (oldfp) + { + /* Switch back to inferior_ptid. */ + remove_breakpoints (); + fork_load_infrun_state (oldfp); + insert_breakpoints (); + } } static int @@ -428,10 +431,10 @@ inferior_call_waitpid (ptid_t pptid, int { struct objfile *waitpid_objf; struct value *waitpid_fn = NULL; - struct value *argv[4]; + struct value *argv[4], *retv; struct gdbarch *gdbarch = get_current_arch (); struct fork_info *oldfp = NULL, *newfp = NULL; - struct cleanup *old_cleanup = NULL; + struct cleanup *old_cleanup; int ret = -1; if (!ptid_equal (pptid, inferior_ptid)) @@ -445,10 +448,10 @@ inferior_call_waitpid (ptid_t pptid, int remove_breakpoints (); fork_load_infrun_state (newfp); insert_breakpoints (); - - old_cleanup = make_cleanup (inferior_call_waitpid_cleanup, oldfp); } + old_cleanup = make_cleanup (inferior_call_waitpid_cleanup, oldfp); + /* Get the waitpid_fn. */ if (lookup_minimal_symbol ("waitpid", NULL, NULL) != NULL) waitpid_fn = find_function_in_inferior ("waitpid", &waitpid_objf); @@ -463,13 +466,14 @@ inferior_call_waitpid (ptid_t pptid, int argv[2] = value_from_longest (builtin_type (gdbarch)->builtin_int, 0); argv[3] = 0; - call_function_by_hand (waitpid_fn, 3, argv); + retv = call_function_by_hand (waitpid_fn, 3, argv); + if (value_as_long (retv) < 0) + goto out; ret = 0; out: - if (old_cleanup) - do_cleanups (old_cleanup); + do_cleanups (old_cleanup); return ret; } @@ -478,7 +482,7 @@ out: static void delete_checkpoint_command (char *args, int from_tty) { - ptid_t ptid; + ptid_t ptid, pptid; struct fork_info *fi; if (!args || !*args) @@ -497,6 +501,7 @@ Please switch to another checkpoint befo fi = find_fork_ptid (ptid); gdb_assert (fi); + pptid = fi->parent_ptid; if (from_tty) printf_filtered (_("Killed %s\n"), target_pid_to_str (ptid)); @@ -507,10 +512,10 @@ Please switch to another checkpoint befo list, waitpid the ptid. If fi->parent_ptid is a part of lwp and it is stoped, waitpid the ptid. */ - if ((!find_thread_ptid (fi->parent_ptid) && find_fork_ptid (fi->parent_ptid)) - || (find_thread_ptid (fi->parent_ptid) && is_stopped (fi->parent_ptid))) + if ((!find_thread_ptid (pptid) && find_fork_ptid (pptid)) + || (find_thread_ptid (pptid) && is_stopped (pptid))) { - if (inferior_call_waitpid (fi->parent_ptid, PIDGET (ptid))) + if (inferior_call_waitpid (pptid, PIDGET (ptid))) warning (_("Unable to wait pid %s"), target_pid_to_str (ptid)); } } ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [RFA] Checkpoint: wait the defunct process when delete it 2010-05-14 15:08 ` Hui Zhu @ 2010-05-14 16:19 ` Pedro Alves 2010-05-17 6:41 ` Hui Zhu 2010-05-14 19:29 ` Michael Snyder 1 sibling, 1 reply; 23+ messages in thread From: Pedro Alves @ 2010-05-14 16:19 UTC (permalink / raw) To: Hui Zhu; +Cc: Michael Snyder, gdb-patches Thanks Hui, On Friday 14 May 2010 15:43:23, Hui Zhu wrote: > + pptid = fi->parent_ptid; > > if (from_tty) > printf_filtered (_("Killed %s\n"), target_pid_to_str (ptid)); > @@ -507,10 +512,10 @@ Please switch to another checkpoint befo > list, waitpid the ptid. > If fi->parent_ptid is a part of lwp and it is stoped, waitpid the > ptid. */ > - if ((!find_thread_ptid (fi->parent_ptid) && find_fork_ptid (fi->parent_ptid)) > - || (find_thread_ptid (fi->parent_ptid) && is_stopped (fi->parent_ptid))) > + if ((!find_thread_ptid (pptid) && find_fork_ptid (pptid)) Sorry, but is still not correct. When you end up with only one fork in the checkpoint list, delete_fork will delete it as well. For example: (gdb) checkpoint at this point, you have two checkpoints, checkpoint 1 (the forked child), and checkpoint 0, the inferior you were already debugging. When you delete the new checkpoint 1, with: (gdb) delete checkpoint 1 delete_fork will also delete checkpoint 0, the parent of checkpoint 1. (see the "Special case:" comment in delete_fork), so your find_fork_ptid(pptid) here will be too late. -- Pedro Alves ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [RFA] Checkpoint: wait the defunct process when delete it 2010-05-14 16:19 ` Pedro Alves @ 2010-05-17 6:41 ` Hui Zhu 2010-05-17 10:45 ` Pedro Alves 0 siblings, 1 reply; 23+ messages in thread From: Hui Zhu @ 2010-05-17 6:41 UTC (permalink / raw) To: Pedro Alves; +Cc: Michael Snyder, gdb-patches On Fri, May 14, 2010 at 23:08, Pedro Alves <pedro@codesourcery.com> wrote: > Thanks Hui, > > On Friday 14 May 2010 15:43:23, Hui Zhu wrote: >> + pptid = fi->parent_ptid; >> >> if (from_tty) >> printf_filtered (_("Killed %s\n"), target_pid_to_str (ptid)); >> @@ -507,10 +512,10 @@ Please switch to another checkpoint befo >> list, waitpid the ptid. >> If fi->parent_ptid is a part of lwp and it is stoped, waitpid the >> ptid. */ >> - if ((!find_thread_ptid (fi->parent_ptid) && find_fork_ptid (fi->parent_ptid)) >> - || (find_thread_ptid (fi->parent_ptid) && is_stopped (fi->parent_ptid))) >> + if ((!find_thread_ptid (pptid) && find_fork_ptid (pptid)) > > Sorry, but is still not correct. When you end up with only one fork > in the checkpoint list, delete_fork will delete it as well. For > example: > > (gdb) checkpoint > > at this point, you have two checkpoints, checkpoint 1 (the forked child), > and checkpoint 0, the inferior you were already debugging. When you > delete the new checkpoint 1, with: > > (gdb) delete checkpoint 1 > > delete_fork will also delete checkpoint 0, the parent of checkpoint 1. > (see the "Special case:" comment in delete_fork), so your > find_fork_ptid(pptid) here will be too late. > At this time, "find_thread_ptid (pptid) && is_stopped (pptid)" this line will handle it. Thanks, Hui ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [RFA] Checkpoint: wait the defunct process when delete it 2010-05-17 6:41 ` Hui Zhu @ 2010-05-17 10:45 ` Pedro Alves 2010-05-18 17:18 ` Hui Zhu 0 siblings, 1 reply; 23+ messages in thread From: Pedro Alves @ 2010-05-17 10:45 UTC (permalink / raw) To: Hui Zhu; +Cc: Michael Snyder, gdb-patches On Monday 17 May 2010 07:37:01, Hui Zhu wrote: > At this time, "find_thread_ptid (pptid) && is_stopped (pptid)" this > line will handle it. I see. I'd prefer to not have these subtle assumptions, but the patch is okay as is then. Thanks. -- Pedro Alves ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [RFA] Checkpoint: wait the defunct process when delete it 2010-05-17 10:45 ` Pedro Alves @ 2010-05-18 17:18 ` Hui Zhu 0 siblings, 0 replies; 23+ messages in thread From: Hui Zhu @ 2010-05-18 17:18 UTC (permalink / raw) To: Pedro Alves; +Cc: Michael Snyder, gdb-patches On Mon, May 17, 2010 at 18:33, Pedro Alves <pedro@codesourcery.com> wrote: > On Monday 17 May 2010 07:37:01, Hui Zhu wrote: > >> At this time, "find_thread_ptid (pptid) && is_stopped (pptid)" this >> line will handle it. > > I see. I'd prefer to not have these subtle assumptions, but > the patch is okay as is then. Thanks. > > -- > Pedro Alves > Thanks for your help, Pedro. Checked in. Best, Hui ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [RFA] Checkpoint: wait the defunct process when delete it 2010-05-14 15:08 ` Hui Zhu 2010-05-14 16:19 ` Pedro Alves @ 2010-05-14 19:29 ` Michael Snyder 2010-05-17 8:11 ` Hui Zhu 1 sibling, 1 reply; 23+ messages in thread From: Michael Snyder @ 2010-05-14 19:29 UTC (permalink / raw) To: Hui Zhu; +Cc: Pedro Alves, gdb-patches Did this get checked in? I didn't think the discussion was finished. ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [RFA] Checkpoint: wait the defunct process when delete it 2010-05-14 19:29 ` Michael Snyder @ 2010-05-17 8:11 ` Hui Zhu 0 siblings, 0 replies; 23+ messages in thread From: Hui Zhu @ 2010-05-17 8:11 UTC (permalink / raw) To: Michael Snyder; +Cc: Pedro Alves, gdb-patches On Sat, May 15, 2010 at 03:08, Michael Snyder <msnyder@vmware.com> wrote: > Did this get checked in? > > I didn't think the discussion was finished. > > Sorry the prev patch was checked in. But it has some bug. So I post a new patch to fix them in http://sourceware.org/ml/gdb-patches/2010-05/msg00299.html Thanks, Hui ^ permalink raw reply [flat|nested] 23+ messages in thread
end of thread, other threads:[~2010-05-18 2:49 UTC | newest] Thread overview: 23+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2010-05-09 6:23 [RFA] Checkpoint: wait the defunct process when delete it Hui Zhu 2010-05-10 19:31 ` Michael Snyder 2010-05-10 23:30 ` Pedro Alves 2010-05-11 21:50 ` Michael Snyder 2010-05-11 22:28 ` Michael Snyder 2010-05-12 0:02 ` Pedro Alves 2010-05-11 22:43 ` Michael Snyder 2010-05-12 0:05 ` Pedro Alves 2010-05-12 0:27 ` Michael Snyder 2010-05-12 4:19 ` Hui Zhu 2010-05-12 18:39 ` Pedro Alves 2010-05-12 18:57 ` Pedro Alves 2010-05-13 9:11 ` Hui Zhu 2010-05-13 11:50 ` Pedro Alves 2010-05-14 11:05 ` Hui Zhu 2010-05-14 14:43 ` Pedro Alves 2010-05-14 15:08 ` Hui Zhu 2010-05-14 16:19 ` Pedro Alves 2010-05-17 6:41 ` Hui Zhu 2010-05-17 10:45 ` Pedro Alves 2010-05-18 17:18 ` Hui Zhu 2010-05-14 19:29 ` Michael Snyder 2010-05-17 8:11 ` Hui Zhu
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox