From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 9694 invoked by alias); 24 May 2009 20:27:48 -0000 Received: (qmail 9685 invoked by uid 22791); 24 May 2009 20:27:44 -0000 X-SWARE-Spam-Status: No, hits=-0.2 required=5.0 tests=AWL,BAYES_50,J_CHICKENPOX_64,SARE_MSGID_LONG40,SPF_PASS X-Spam-Check-By: sourceware.org Received: from smtp-out.google.com (HELO smtp-out.google.com) (216.239.33.17) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Sun, 24 May 2009 20:27:37 +0000 Received: from spaceape8.eur.corp.google.com (spaceape8.eur.corp.google.com [172.28.16.142]) by smtp-out.google.com with ESMTP id n4OKRXI7030214 for ; Sun, 24 May 2009 21:27:33 +0100 Received: from gxk21 (gxk21.prod.google.com [10.202.11.21]) by spaceape8.eur.corp.google.com with ESMTP id n4OKRV86003399 for ; Sun, 24 May 2009 13:27:31 -0700 Received: by gxk21 with SMTP id 21so7280824gxk.7 for ; Sun, 24 May 2009 13:27:30 -0700 (PDT) MIME-Version: 1.0 Received: by 10.90.80.4 with SMTP id d4mr3697919agb.62.1243196850836; Sun, 24 May 2009 13:27:30 -0700 (PDT) Date: Sun, 24 May 2009 20:27:00 -0000 Message-ID: Subject: [RFA] Fix build failure [was Re: [RFC] fork in multi-threaded apps, per-thread pending_fork, other follow-fork cleanups.] From: Doug Evans To: Pedro Alves Cc: gdb-patches@sourceware.org Content-Type: text/plain; charset=windows-1252 Content-Transfer-Encoding: quoted-printable X-System-Of-Record: true X-IsSubscribed: yes Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org X-SW-Source: 2009-05/txt/msg00537.txt.bz2 On Sun, May 24, 2009 at 11:01 AM, Pedro Alves wrot= e: > [...] > We're not worse than before, so I checked in this revision of that > patch with a few extra comments and small cleanups. > > -- > Pedro Alves > > gdb/ > 2009-05-24 =A0Pedro Alves =A0 > > =A0 =A0 =A0 =A0* gdbthread.h (struct thread_info): New `pending_follow' f= ield. > =A0 =A0 =A0 =A0* thread.c (new_thread): New function. > =A0 =A0 =A0 =A0(add_thread_silent): Use it. > =A0 =A0 =A0 =A0* breakpoint.c (internal_breakpoint_number): New global, m= oved > =A0 =A0 =A0 =A0from inside... > =A0 =A0 =A0 =A0(create_internal_breakpoint): ... this. > =A0 =A0 =A0 =A0(clone_momentary_breakpoint): New. > =A0 =A0 =A0 =A0* breakpoint.h (clone_momentary_breakpoint): Declare. > =A0 =A0 =A0 =A0* infrun.c (nullify_last_target_wait_ptid): Move declarati= on > =A0 =A0 =A0 =A0higher. > =A0 =A0 =A0 =A0(pending_follow): Delete. > =A0 =A0 =A0 =A0(follow_fork): Handle pending follow fork event here. =A0M= oved the > =A0 =A0 =A0 =A0preserving of thread stepping state here. > =A0 =A0 =A0 =A0(resume): Don't handle pending follow fork events here. = =A0Only > =A0 =A0 =A0 =A0install the inferior's terminal modes if we're about to re= sume it. > =A0 =A0 =A0 =A0(proceed): Handle possible pending follow fork events here. > =A0 =A0 =A0 =A0(init_wait_for_inferior): No need to clear pending_follow = anymore, > =A0 =A0 =A0 =A0it's gone. > =A0 =A0 =A0 =A0(handle_inferior_event): Adjust to per-thread `pending_fol= low'. > =A0 =A0 =A0 =A0Call `follow_fork' to handle following the fork. =A0If the > =A0 =A0 =A0 =A0follow-fork is cancelled, stop stepping. > =A0 =A0 =A0 =A0* linux-nat.c (linux_child_follow_fork): Adjust to per-thr= ead > =A0 =A0 =A0 =A0`pending_follow' events. =A0Remove code that handled prese= rving the > =A0 =A0 =A0 =A0thread stepping state. > =A0 =A0 =A0 =A0* inf-ptrace.c (inf_ptrace_follow_fork): Ditto. > =A0 =A0 =A0 =A0* inf-ttrace.c (inf_ttrace_follow_fork): Ditto. > > gdb/testsuite/ > 2009-05-24 =A0Pedro Alves =A0 > > =A0 =A0 =A0 =A0* gdb.threads/fork-thread-pending.c: New. > =A0 =A0 =A0 =A0* gdb.threads/fork-thread-pending.exp: New. > > --- > =A0gdb/breakpoint.c =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 = =A0 =A0 =A0 =A0| =A0 40 +++ > =A0gdb/breakpoint.h =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 = =A0 =A0 =A0 =A0| =A0 =A02 > =A0gdb/gdbthread.h =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 = =A0 =A0 =A0 =A0 | =A0 =A05 > =A0gdb/inf-ptrace.c =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 = =A0 =A0 =A0 =A0| =A0 36 --- > =A0gdb/inf-ttrace.c =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 = =A0 =A0 =A0 =A0| =A0 44 ---- > =A0gdb/infrun.c =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 = =A0 =A0 =A0 =A0 =A0| =A0241 ++++++++++++++++------ > =A0gdb/linux-nat.c =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 = =A0 =A0 =A0 =A0 | =A0 37 --- > =A0gdb/testsuite/gdb.threads/fork-thread-pending.c =A0 | =A0109 +++++++++ > =A0gdb/testsuite/gdb.threads/fork-thread-pending.exp | =A0128 +++++++++++ > =A0gdb/thread.c =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 = =A0 =A0 =A0 =A0 =A0| =A0 37 ++- > =A010 files changed, 508 insertions(+), 171 deletions(-) > > Index: src/gdb/gdbthread.h > =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D > --- src.orig/gdb/gdbthread.h =A0 =A02009-05-21 23:45:24.000000000 +0100 > +++ src/gdb/gdbthread.h 2009-05-24 17:09:03.000000000 +0100 > @@ -165,6 +165,11 @@ struct thread_info > =A0 =A0 =A0next time inferior stops if it stops due to stepping. =A0*/ > =A0 int step_multi; > > + =A0/* This is used to remember when a fork or vfork event was caught by > + =A0 =A0 a catchpoint, and thus the event is to be followed at the next > + =A0 =A0 resume of the thread, and not immediately. =A0*/ > + =A0struct target_waitstatus pending_follow; > + > =A0 /* Last signal that the inferior received (why it stopped). =A0*/ > =A0 enum target_signal stop_signal; > > Index: src/gdb/thread.c > =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D > --- src.orig/gdb/thread.c =A0 =A0 =A0 2009-05-21 23:45:24.000000000 +0100 > +++ src/gdb/thread.c =A0 =A02009-05-24 17:14:18.000000000 +0100 > @@ -141,6 +141,28 @@ init_thread_list (void) > =A0 thread_list =3D NULL; > =A0} > > +/* Allocate a new thread with target id PTID and add it to the thread > + =A0 list. =A0*/ > + > +static struct thread_info * > +new_thread (ptid_t ptid) > +{ > + =A0struct thread_info *tp; > + > + =A0tp =3D xcalloc (1, sizeof (*tp)); > + > + =A0tp->ptid =3D ptid; > + =A0tp->num =3D ++highest_thread_num; > + =A0tp->next =3D thread_list; > + =A0thread_list =3D tp; > + > + =A0/* Nothing to follow yet. =A0*/ > + =A0tp->pending_follow.kind =3D TARGET_WAITKIND_SPURIOUS; > + =A0tp->state_ =3D THREAD_STOPPED; > + > + =A0return tp; > +} > + > =A0struct thread_info * > =A0add_thread_silent (ptid_t ptid) > =A0{ > @@ -162,12 +184,7 @@ add_thread_silent (ptid_t ptid) > > =A0 =A0 =A0 if (ptid_equal (inferior_ptid, ptid)) > =A0 =A0 =A0 =A0{ > - =A0 =A0 =A0 =A0 tp =3D xmalloc (sizeof (*tp)); > - =A0 =A0 =A0 =A0 memset (tp, 0, sizeof (*tp)); > - =A0 =A0 =A0 =A0 tp->ptid =3D minus_one_ptid; > - =A0 =A0 =A0 =A0 tp->num =3D ++highest_thread_num; > - =A0 =A0 =A0 =A0 tp->next =3D thread_list; > - =A0 =A0 =A0 =A0 thread_list =3D tp; > + =A0 =A0 =A0 =A0 tp =3D new_thread (ptid); > > =A0 =A0 =A0 =A0 =A0/* Make switch_to_thread not read from the thread. =A0= */ > =A0 =A0 =A0 =A0 =A0tp->state_ =3D THREAD_EXITED; > @@ -191,13 +208,7 @@ add_thread_silent (ptid_t ptid) > =A0 =A0 =A0 =A0delete_thread (ptid); > =A0 =A0 } > > - =A0tp =3D (struct thread_info *) xmalloc (sizeof (*tp)); > - =A0memset (tp, 0, sizeof (*tp)); > - =A0tp->ptid =3D ptid; > - =A0tp->num =3D ++highest_thread_num; > - =A0tp->next =3D thread_list; > - =A0thread_list =3D tp; > - > + =A0tp =3D new_thread (ptid); > =A0 observer_notify_new_thread (tp); > > =A0 return tp; > Index: src/gdb/breakpoint.c > =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D > --- src.orig/gdb/breakpoint.c =A0 2009-05-23 18:24:43.000000000 +0100 > +++ src/gdb/breakpoint.c =A0 =A0 =A0 =A02009-05-24 17:18:54.000000000 +01= 00 > @@ -1456,10 +1456,11 @@ reattach_breakpoints (int pid) > =A0 return 0; > =A0} > > +static int internal_breakpoint_number =3D -1; > + > =A0static struct breakpoint * > =A0create_internal_breakpoint (CORE_ADDR address, enum bptype type) > =A0{ > - =A0static int internal_breakpoint_number =3D -1; > =A0 struct symtab_and_line sal; > =A0 struct breakpoint *b; > > @@ -5007,6 +5008,43 @@ set_momentary_breakpoint (struct symtab_ > =A0 return b; > =A0} > > +/* Make a deep copy of momentary breakpoint ORIG. =A0Returns NULL if > + =A0 ORIG is NULL. =A0*/ > + > +struct breakpoint * > +clone_momentary_breakpoint (struct breakpoint *orig) > +{ > + =A0struct breakpoint *copy; > + > + =A0/* If there's nothing to clone, then return nothing. =A0*/ > + =A0if (orig =3D=3D NULL) > + =A0 =A0return NULL; > + > + =A0copy =3D set_raw_breakpoint_without_location (orig->type); > + =A0copy->loc =3D allocate_bp_location (copy); > + =A0set_breakpoint_location_function (copy->loc); > + > + =A0copy->loc->requested_address =3D orig->loc->requested_address; > + =A0copy->loc->address =3D orig->loc->address; > + =A0copy->loc->section =3D orig->loc->section; > + > + =A0if (orig->source_file =3D=3D NULL) > + =A0 =A0copy->source_file =3D NULL; > + =A0else > + =A0 =A0copy->source_file =3D xstrdup (orig->source_file); > + > + =A0copy->line_number =3D orig->line_number; > + =A0copy->frame_id =3D orig->frame_id; > + =A0copy->thread =3D orig->thread; > + > + =A0copy->enable_state =3D bp_enabled; > + =A0copy->disposition =3D disp_donttouch; > + =A0copy->number =3D internal_breakpoint_number--; > + > + =A0update_global_location_list_nothrow (0); > + =A0return copy; > +} > + > =A0struct breakpoint * > =A0set_momentary_breakpoint_at_pc (CORE_ADDR pc, enum bptype type) > =A0{ > Index: src/gdb/breakpoint.h > =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D > --- src.orig/gdb/breakpoint.h =A0 2009-05-21 23:45:24.000000000 +0100 > +++ src/gdb/breakpoint.h =A0 =A0 =A0 =A02009-05-24 17:09:03.000000000 +01= 00 > @@ -696,6 +696,8 @@ extern struct breakpoint *set_momentary_ > =A0extern struct breakpoint *set_momentary_breakpoint_at_pc > =A0 (CORE_ADDR pc, enum bptype type); > > +extern struct breakpoint *clone_momentary_breakpoint (struct breakpoint = *bpkt); > + > =A0extern void set_ignore_count (int, int, int); > > =A0extern void set_default_breakpoint (int, CORE_ADDR, struct symtab *, i= nt); > Index: src/gdb/infrun.c > =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D > --- src.orig/gdb/infrun.c =A0 =A0 =A0 2009-05-24 17:02:20.000000000 +0100 > +++ src/gdb/infrun.c =A0 =A02009-05-24 17:13:31.000000000 +0100 > @@ -83,6 +83,8 @@ static int prepare_to_proceed (int); > > =A0void _initialize_infrun (void); > > +void nullify_last_target_wait_ptid (void); > + > =A0/* When set, stop the 'step' command if we enter a function which has > =A0 =A0no line number information. =A0The normal behavior is that we step > =A0 =A0over such function. =A0*/ > @@ -255,21 +257,6 @@ void init_thread_stepping_state (struct > > =A0void init_infwait_state (void); > > -/* This is used to remember when a fork or vfork event was caught by a > - =A0 catchpoint, and thus the event is to be followed at the next resume > - =A0 of the inferior, and not immediately. =A0*/ > -static struct > -{ > - =A0enum target_waitkind kind; > - =A0struct > - =A0{ > - =A0 =A0ptid_t parent_pid; > - =A0 =A0ptid_t child_pid; > - =A0} > - =A0fork_event; > -} > -pending_follow; > - > =A0static const char follow_fork_mode_child[] =3D "child"; > =A0static const char follow_fork_mode_parent[] =3D "parent"; > > @@ -290,12 +277,157 @@ Debugger response to a program call of f > =A0} > > > +/* Tell the target to follow the fork we're stopped at. =A0Returns true > + =A0 if the inferior should be resumed; false, if the target for some > + =A0 reason decided it's best not to resume. =A0*/ > + > =A0static int > =A0follow_fork (void) > =A0{ > =A0 int follow_child =3D (follow_fork_mode_string =3D=3D follow_fork_mode= _child); > + =A0int should_resume =3D 1; > + =A0struct thread_info *tp; > + > + =A0/* Copy user stepping state to the new inferior thread. =A0FIXME: the > + =A0 =A0 followed fork child thread should have a copy of most of the > + =A0 =A0 parent thread structure's run control related fields, not just > + =A0 =A0 these. =A0*/ > + =A0struct breakpoint *step_resume_breakpoint; > + =A0CORE_ADDR step_range_start; > + =A0CORE_ADDR step_range_end; > + =A0struct frame_id step_frame_id; > + > + =A0if (!non_stop) > + =A0 =A0{ > + =A0 =A0 =A0ptid_t wait_ptid; > + =A0 =A0 =A0struct target_waitstatus wait_status; > + > + =A0 =A0 =A0/* Get the last target status returned by target_wait(). =A0= */ > + =A0 =A0 =A0get_last_target_status (&wait_ptid, &wait_status); > + > + =A0 =A0 =A0/* If not stopped at a fork event, then there's nothing else= to > + =A0 =A0 =A0 =A0do. =A0*/ > + =A0 =A0 =A0if (wait_status.kind !=3D TARGET_WAITKIND_FORKED > + =A0 =A0 =A0 =A0 && wait_status.kind !=3D TARGET_WAITKIND_VFORKED) > + =A0 =A0 =A0 return 1; > + > + =A0 =A0 =A0/* Check if we switched over from WAIT_PTID, since the event= was > + =A0 =A0 =A0 =A0reported. =A0*/ > + =A0 =A0 =A0if (!ptid_equal (wait_ptid, minus_one_ptid) > + =A0 =A0 =A0 =A0 && !ptid_equal (inferior_ptid, wait_ptid)) > + =A0 =A0 =A0 { > + =A0 =A0 =A0 =A0 /* We did. =A0Switch back to WAIT_PTID thread, to tell = the > + =A0 =A0 =A0 =A0 =A0 =A0target to follow it (in either direction). =A0We= 'll > + =A0 =A0 =A0 =A0 =A0 =A0afterwards refuse to resume, and inform the user= what > + =A0 =A0 =A0 =A0 =A0 =A0happened. =A0*/ > + =A0 =A0 =A0 =A0 switch_to_thread (wait_ptid); > + =A0 =A0 =A0 =A0 should_resume =3D 0; > + =A0 =A0 =A0 } > + =A0 =A0} > + > + =A0tp =3D inferior_thread (); > + > + =A0/* If there were any forks/vforks that were caught and are now to be > + =A0 =A0 followed, then do so now. =A0*/ > + =A0switch (tp->pending_follow.kind) > + =A0 =A0{ > + =A0 =A0case TARGET_WAITKIND_FORKED: > + =A0 =A0case TARGET_WAITKIND_VFORKED: > + =A0 =A0 =A0{ > + =A0 =A0 =A0 ptid_t parent, child; > + > + =A0 =A0 =A0 /* If the user did a next/step, etc, over a fork call, > + =A0 =A0 =A0 =A0 =A0preserve the stepping state in the fork child. =A0*/ > + =A0 =A0 =A0 if (follow_child && should_resume) > + =A0 =A0 =A0 =A0 { > + =A0 =A0 =A0 =A0 =A0 step_resume_breakpoint > + =A0 =A0 =A0 =A0 =A0 =A0 =3D clone_momentary_breakpoint (tp->step_resume= _breakpoint); > + =A0 =A0 =A0 =A0 =A0 step_range_start =3D tp->step_range_start; > + =A0 =A0 =A0 =A0 =A0 step_range_end =3D tp->step_range_end; > + =A0 =A0 =A0 =A0 =A0 step_frame_id =3D tp->step_frame_id; > + > + =A0 =A0 =A0 =A0 =A0 /* For now, delete the parent's sr breakpoint, othe= rwise, > + =A0 =A0 =A0 =A0 =A0 =A0 =A0parent/child sr breakpoints are considered d= uplicates, > + =A0 =A0 =A0 =A0 =A0 =A0 =A0and the child version will not be installed.= =A0Remove > + =A0 =A0 =A0 =A0 =A0 =A0 =A0this when the breakpoints module becomes awa= re of > + =A0 =A0 =A0 =A0 =A0 =A0 =A0inferiors and address spaces. =A0*/ > + =A0 =A0 =A0 =A0 =A0 delete_step_resume_breakpoint (tp); > + =A0 =A0 =A0 =A0 =A0 tp->step_range_start =3D 0; > + =A0 =A0 =A0 =A0 =A0 tp->step_range_end =3D 0; > + =A0 =A0 =A0 =A0 =A0 tp->step_frame_id =3D null_frame_id; > + =A0 =A0 =A0 =A0 } > + > + =A0 =A0 =A0 parent =3D inferior_ptid; > + =A0 =A0 =A0 child =3D tp->pending_follow.value.related_pid; > + > + =A0 =A0 =A0 /* Tell the target to do whatever is necessary to follow > + =A0 =A0 =A0 =A0 =A0either parent or child. =A0*/ > + =A0 =A0 =A0 if (target_follow_fork (follow_child)) > + =A0 =A0 =A0 =A0 { > + =A0 =A0 =A0 =A0 =A0 /* Target refused to follow, or there's some other = reason > + =A0 =A0 =A0 =A0 =A0 =A0 =A0we shouldn't resume. =A0*/ > + =A0 =A0 =A0 =A0 =A0 should_resume =3D 0; > + =A0 =A0 =A0 =A0 } > + =A0 =A0 =A0 else > + =A0 =A0 =A0 =A0 { > + =A0 =A0 =A0 =A0 =A0 /* This pending follow fork event is now handled, o= ne way > + =A0 =A0 =A0 =A0 =A0 =A0 =A0or another. =A0The previous selected thread = may be gone > + =A0 =A0 =A0 =A0 =A0 =A0 =A0from the lists by now, but if it is still ar= ound, need > + =A0 =A0 =A0 =A0 =A0 =A0 =A0to clear the pending follow request. =A0*/ > + =A0 =A0 =A0 =A0 =A0 tp =3D find_thread_pid (parent); > + =A0 =A0 =A0 =A0 =A0 if (tp) > + =A0 =A0 =A0 =A0 =A0 =A0 tp->pending_follow.kind =3D TARGET_WAITKIND_SPU= RIOUS; > + > + =A0 =A0 =A0 =A0 =A0 /* This makes sure we don't try to apply the "Switc= hed > + =A0 =A0 =A0 =A0 =A0 =A0 =A0over from WAIT_PID" logic above. =A0*/ > + =A0 =A0 =A0 =A0 =A0 nullify_last_target_wait_ptid (); > + > + =A0 =A0 =A0 =A0 =A0 /* If we followed the child, switch to it... */ > + =A0 =A0 =A0 =A0 =A0 if (follow_child) > + =A0 =A0 =A0 =A0 =A0 =A0 { > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 switch_to_thread (child); > + > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 /* ... and preserve the stepping state, in = case the > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0user was stepping over the fork call= . =A0*/ > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (should_resume) > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 { > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 tp =3D inferior_thread (); > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 tp->step_resume_breakpoint =3D step= _resume_breakpoint; > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 tp->step_range_start =3D step_range= _start; > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 tp->step_range_end =3D step_range_e= nd; > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 tp->step_frame_id =3D step_frame_id; > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 } > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 else > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 { > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 /* If we get here, it was because w= e're trying to > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0resume from a fork catchpoin= t, but, the user > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0has switched threads away fr= om the thread that > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0forked. =A0In that case, the= resume command > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0issued is most likely not ap= plicable to the > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0child, so just warn, and ref= use to resume. =A0*/ > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 warning (_("\ > +Not resuming: switched threads before following fork child.\n")); > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 } > + > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 /* Reset breakpoints in the child as approp= riate. =A0*/ > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 follow_inferior_reset_breakpoints (); > + =A0 =A0 =A0 =A0 =A0 =A0 } > + =A0 =A0 =A0 =A0 =A0 else > + =A0 =A0 =A0 =A0 =A0 =A0 switch_to_thread (parent); > + =A0 =A0 =A0 =A0 } > + =A0 =A0 =A0} > + =A0 =A0 =A0break; > + =A0 =A0case TARGET_WAITKIND_SPURIOUS: > + =A0 =A0 =A0/* Nothing to follow. =A0*/ > + =A0 =A0 =A0break; > + =A0 =A0default: > + =A0 =A0 =A0internal_error (__FILE__, __LINE__, > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 "Unexpected pending_follow.kind= %d\n", > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 tp->pending_follow.kind); > + =A0 =A0 =A0break; > + =A0 =A0} > > - =A0return target_follow_fork (follow_child); > + =A0return should_resume; > =A0} > > =A0void > @@ -987,8 +1119,6 @@ resume (int step, enum target_signal sig > =A0{ > =A0 int should_resume =3D 1; > =A0 struct cleanup *old_cleanups =3D make_cleanup (resume_cleanups, 0); > - > - =A0/* Note that these must be reset if we follow a fork below. =A0*/ > =A0 struct regcache *regcache =3D get_current_regcache (); > =A0 struct gdbarch *gdbarch =3D get_regcache_arch (regcache); > =A0 struct thread_info *tp =3D inferior_thread (); > @@ -1058,31 +1188,6 @@ a command like `return' or `jump' to con > =A0 if (step) > =A0 =A0 step =3D maybe_software_singlestep (gdbarch, pc); > > - =A0/* If there were any forks/vforks/execs that were caught and are > - =A0 =A0 now to be followed, then do so. =A0*/ > - =A0switch (pending_follow.kind) > - =A0 =A0{ > - =A0 =A0case TARGET_WAITKIND_FORKED: > - =A0 =A0case TARGET_WAITKIND_VFORKED: > - =A0 =A0 =A0pending_follow.kind =3D TARGET_WAITKIND_SPURIOUS; > - =A0 =A0 =A0if (follow_fork ()) > - =A0 =A0 =A0 should_resume =3D 0; > - > - =A0 =A0 =A0/* Following a child fork will change our notion of current > - =A0 =A0 =A0 =A0thread. =A0*/ > - =A0 =A0 =A0tp =3D inferior_thread (); > - =A0 =A0 =A0regcache =3D get_current_regcache (); > - =A0 =A0 =A0gdbarch =3D get_regcache_arch (regcache); > - =A0 =A0 =A0pc =3D regcache_read_pc (regcache); > - =A0 =A0 =A0break; > - > - =A0 =A0default: > - =A0 =A0 =A0break; > - =A0 =A0} > - > - =A0/* Install inferior's terminal modes. =A0*/ > - =A0target_terminal_inferior (); > - > =A0 if (should_resume) > =A0 =A0 { > =A0 =A0 =A0 ptid_t resume_ptid; > @@ -1164,6 +1269,9 @@ a command like `return' or `jump' to con > =A0 =A0 =A0 =A0 =A0 displaced_step_dump_bytes (gdb_stdlog, buf, sizeof (b= uf)); > =A0 =A0 =A0 =A0 } > > + =A0 =A0 =A0/* Install inferior's terminal modes. =A0*/ > + =A0 =A0 =A0target_terminal_inferior (); > + > =A0 =A0 =A0 /* Avoid confusing the next resume, if the next stop/resume > =A0 =A0 =A0 =A0 happens to apply to another thread. =A0*/ > =A0 =A0 =A0 tp->stop_signal =3D TARGET_SIGNAL_0; > @@ -1305,12 +1413,26 @@ prepare_to_proceed (int step) > =A0void > =A0proceed (CORE_ADDR addr, enum target_signal siggnal, int step) > =A0{ > - =A0struct regcache *regcache =3D get_current_regcache (); > - =A0struct gdbarch *gdbarch =3D get_regcache_arch (regcache); > + =A0struct regcache *regcache; > + =A0struct gdbarch *gdbarch; > =A0 struct thread_info *tp; > - =A0CORE_ADDR pc =3D regcache_read_pc (regcache); > + =A0CORE_ADDR pc; > =A0 int oneproc =3D 0; > > + =A0/* If we're stopped at a fork/vfork, follow the branch set by the > + =A0 =A0 "set follow-fork-mode" command; otherwise, we'll just proceed > + =A0 =A0 resuming the current thread. =A0*/ > + =A0if (!follow_fork ()) > + =A0 =A0{ > + =A0 =A0 =A0/* The target for some reason decided not to resume. =A0*/ > + =A0 =A0 =A0normal_stop (); > + =A0 =A0 =A0return; > + =A0 =A0} > + > + =A0regcache =3D get_current_regcache (); > + =A0gdbarch =3D get_regcache_arch (regcache); > + =A0pc =3D regcache_read_pc (regcache); > + > =A0 if (step > 0) > =A0 =A0 step_start_function =3D find_pc_function (pc); > =A0 if (step < 0) > @@ -1517,9 +1639,6 @@ init_wait_for_inferior (void) > > =A0 breakpoint_init_inferior (inf_starting); > > - =A0/* The first resume is not following a fork/vfork/exec. */ > - =A0pending_follow.kind =3D TARGET_WAITKIND_SPURIOUS; =A0 =A0 =A0/* I.e.= , none. */ > - > =A0 clear_proceed_status (); > > =A0 stepping_past_singlestep_breakpoint =3D 0; > @@ -1698,8 +1817,6 @@ infrun_thread_stop_requested (ptid_t pti > =A0 iterate_over_threads (infrun_thread_stop_requested_callback, &ptid); > =A0} > > -void nullify_last_target_wait_ptid (void); > - > =A0static void > =A0infrun_thread_thread_exit (struct thread_info *tp, int silent) > =A0{ > @@ -2407,10 +2524,6 @@ handle_inferior_event (struct execution_ > =A0 =A0 case TARGET_WAITKIND_VFORKED: > =A0 =A0 =A0 if (debug_infrun) > =A0 =A0 =A0 =A0 fprintf_unfiltered (gdb_stdlog, "infrun: TARGET_WAITKIND_= FORKED\n"); > - =A0 =A0 =A0pending_follow.kind =3D ecs->ws.kind; > - > - =A0 =A0 =A0pending_follow.fork_event.parent_pid =3D ecs->ptid; > - =A0 =A0 =A0pending_follow.fork_event.child_pid =3D ecs->ws.value.relate= d_pid; > > =A0 =A0 =A0 if (!ptid_equal (ecs->ptid, inferior_ptid)) > =A0 =A0 =A0 =A0{ > @@ -2439,6 +2552,11 @@ handle_inferior_event (struct execution_ > =A0 =A0 =A0 =A0 =A0detach_breakpoints (child_pid); > =A0 =A0 =A0 =A0} > > + =A0 =A0 =A0/* In case the event is caught by a catchpoint, remember that > + =A0 =A0 =A0 =A0the event is to be followed at the next resume of the th= read, > + =A0 =A0 =A0 =A0and not immediately. =A0*/ > + =A0 =A0 =A0ecs->event_thread->pending_follow =3D ecs->ws; > + > =A0 =A0 =A0 stop_pc =3D regcache_read_pc (get_thread_regcache (ecs->ptid)= ); > > =A0 =A0 =A0 ecs->event_thread->stop_bpstat =3D bpstat_stop_status (stop_p= c, ecs->ptid); > @@ -2448,8 +2566,19 @@ handle_inferior_event (struct execution_ > =A0 =A0 =A0 /* If no catchpoint triggered for this, then keep going. =A0*/ > =A0 =A0 =A0 if (ecs->random_signal) > =A0 =A0 =A0 =A0{ > + =A0 =A0 =A0 =A0 int should_resume; > + > =A0 =A0 =A0 =A0 =A0ecs->event_thread->stop_signal =3D TARGET_SIGNAL_0; > - =A0 =A0 =A0 =A0 keep_going (ecs); > + > + =A0 =A0 =A0 =A0 should_resume =3D follow_fork (); > + > + =A0 =A0 =A0 =A0 ecs->event_thread =3D inferior_thread (); > + =A0 =A0 =A0 =A0 ecs->ptid =3D inferior_ptid; > + > + =A0 =A0 =A0 =A0 if (should_resume) > + =A0 =A0 =A0 =A0 =A0 keep_going (ecs); > + =A0 =A0 =A0 =A0 else > + =A0 =A0 =A0 =A0 =A0 stop_stepping (ecs); > =A0 =A0 =A0 =A0 =A0return; > =A0 =A0 =A0 =A0} > =A0 =A0 =A0 ecs->event_thread->stop_signal =3D TARGET_SIGNAL_TRAP; > Index: src/gdb/linux-nat.c > =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D > --- src.orig/gdb/linux-nat.c =A0 =A02009-05-21 23:45:24.000000000 +0100 > +++ src/gdb/linux-nat.c 2009-05-24 17:09:03.000000000 +0100 > @@ -575,19 +575,17 @@ static int > =A0linux_child_follow_fork (struct target_ops *ops, int follow_child) > =A0{ > =A0 sigset_t prev_mask; > - =A0ptid_t last_ptid; > - =A0struct target_waitstatus last_status; > =A0 int has_vforked; > =A0 int parent_pid, child_pid; > > =A0 block_child_signals (&prev_mask); > > - =A0get_last_target_status (&last_ptid, &last_status); > - =A0has_vforked =3D (last_status.kind =3D=3D TARGET_WAITKIND_VFORKED); > - =A0parent_pid =3D ptid_get_lwp (last_ptid); > + =A0has_vforked =3D (inferior_thread ()->pending_follow.kind > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=3D=3D TARGET_WAITKIND_VFORKED); > + =A0parent_pid =3D ptid_get_lwp (inferior_ptid); > =A0 if (parent_pid =3D=3D 0) > - =A0 =A0parent_pid =3D ptid_get_pid (last_ptid); > - =A0child_pid =3D PIDGET (last_status.value.related_pid); > + =A0 =A0parent_pid =3D ptid_get_pid (inferior_ptid); > + =A0child_pid =3D PIDGET (inferior_thread ()->pending_follow.value.relat= ed_pid); > > =A0 if (! follow_child) > =A0 =A0 { > @@ -625,7 +623,7 @@ linux_child_follow_fork (struct target_o > =A0 =A0 =A0 =A0 =A0/* Add process to GDB's tables. =A0*/ > =A0 =A0 =A0 =A0 =A0child_inf =3D add_inferior (child_pid); > > - =A0 =A0 =A0 =A0 parent_inf =3D find_inferior_pid (GET_PID (last_ptid)); > + =A0 =A0 =A0 =A0 parent_inf =3D current_inferior (); > =A0 =A0 =A0 =A0 =A0child_inf->attach_flag =3D parent_inf->attach_flag; > =A0 =A0 =A0 =A0 =A0copy_terminal_info (child_inf, parent_inf); > > @@ -692,21 +690,9 @@ linux_child_follow_fork (struct target_o > =A0 =A0 } > =A0 else > =A0 =A0 { > - =A0 =A0 =A0struct thread_info *last_tp =3D find_thread_pid (last_ptid); > =A0 =A0 =A0 struct thread_info *tp; > - =A0 =A0 =A0char child_pid_spelling[40]; > =A0 =A0 =A0 struct inferior *parent_inf, *child_inf; > > - =A0 =A0 =A0/* Copy user stepping state to the new inferior thread. =A0*/ > - =A0 =A0 =A0struct breakpoint *step_resume_breakpoint =3D last_tp->step_= resume_breakpoint; > - =A0 =A0 =A0CORE_ADDR step_range_start =3D last_tp->step_range_start; > - =A0 =A0 =A0CORE_ADDR step_range_end =3D last_tp->step_range_end; > - =A0 =A0 =A0struct frame_id step_frame_id =3D last_tp->step_frame_id; > - > - =A0 =A0 =A0/* Otherwise, deleting the parent would get rid of this > - =A0 =A0 =A0 =A0breakpoint. =A0*/ > - =A0 =A0 =A0last_tp->step_resume_breakpoint =3D NULL; > - > =A0 =A0 =A0 /* Before detaching from the parent, remove all breakpoints f= rom it. */ > =A0 =A0 =A0 remove_breakpoints (); > > @@ -723,7 +709,7 @@ linux_child_follow_fork (struct target_o > > =A0 =A0 =A0 child_inf =3D add_inferior (child_pid); > > - =A0 =A0 =A0parent_inf =3D find_inferior_pid (GET_PID (last_ptid)); > + =A0 =A0 =A0parent_inf =3D current_inferior (); > =A0 =A0 =A0 child_inf->attach_flag =3D parent_inf->attach_flag; > =A0 =A0 =A0 copy_terminal_info (child_inf, parent_inf); > > @@ -772,15 +758,6 @@ linux_child_follow_fork (struct target_o > > =A0 =A0 =A0 linux_nat_switch_fork (inferior_ptid); > =A0 =A0 =A0 check_for_thread_db (); > - > - =A0 =A0 =A0tp =3D inferior_thread (); > - =A0 =A0 =A0tp->step_resume_breakpoint =3D step_resume_breakpoint; > - =A0 =A0 =A0tp->step_range_start =3D step_range_start; > - =A0 =A0 =A0tp->step_range_end =3D step_range_end; > - =A0 =A0 =A0tp->step_frame_id =3D step_frame_id; > - > - =A0 =A0 =A0/* Reset breakpoints in the child as appropriate. =A0*/ > - =A0 =A0 =A0follow_inferior_reset_breakpoints (); > =A0 =A0 } > > =A0 restore_child_signals_mask (&prev_mask); > Index: src/gdb/inf-ptrace.c > =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D > --- src.orig/gdb/inf-ptrace.c =A0 2009-05-21 23:45:24.000000000 +0100 > +++ src/gdb/inf-ptrace.c =A0 =A0 =A0 =A02009-05-24 18:20:14.000000000 +01= 00 > @@ -46,20 +46,8 @@ inf_ptrace_follow_fork (struct target_op > =A0{ > =A0 pid_t pid, fpid; > =A0 ptrace_state_t pe; > - =A0struct thread_info *last_tp =3D NULL; > > - =A0/* FIXME: kettenis/20050720: This stuff should really be passed as > - =A0 =A0 an argument by our caller. =A0*/ > - =A0{ > - =A0 =A0ptid_t ptid; > - =A0 =A0struct target_waitstatus status; > - > - =A0 =A0get_last_target_status (&ptid, &status); > - =A0 =A0gdb_assert (status.kind =3D=3D TARGET_WAITKIND_FORKED); > - > - =A0 =A0pid =3D ptid_get_pid (ptid); > - =A0 =A0last_tp =3D find_thread_pid (ptid); > - =A0} > + =A0pid =3D ptid_get_pid (inferior_ptid); > > =A0 if (ptrace (PT_GET_PROCESS_STATE, pid, > =A0 =A0 =A0 =A0 =A0 =A0 =A0 (PTRACE_TYPE_ARG3)&pe, sizeof pe) =3D=3D -1) > @@ -70,18 +58,9 @@ inf_ptrace_follow_fork (struct target_op > > =A0 if (follow_child) > =A0 =A0 { > - =A0 =A0 =A0/* Copy user stepping state to the new inferior thread. =A0*/ > - =A0 =A0 =A0struct breakpoint *step_resume_breakpoint =3D last_tp->step_= resume_breakpoint; > - =A0 =A0 =A0CORE_ADDR step_range_start =3D last_tp->step_range_start; > - =A0 =A0 =A0CORE_ADDR step_range_end =3D last_tp->step_range_end; > - =A0 =A0 =A0struct frame_id step_frame_id =3D last_tp->step_frame_id; > =A0 =A0 =A0 struct inferior *parent_inf, *child_inf; > =A0 =A0 =A0 struct thread_info *tp; > > - =A0 =A0 =A0/* Otherwise, deleting the parent would get rid of this > - =A0 =A0 =A0 =A0breakpoint. =A0*/ > - =A0 =A0 =A0last_tp->step_resume_breakpoint =3D NULL; > - > =A0 =A0 =A0 parent_inf =3D find_inferior_pid (pid); > > =A0 =A0 =A0 /* Add the child. =A0*/ > @@ -102,26 +81,15 @@ inf_ptrace_follow_fork (struct target_op > =A0 =A0 =A0 /* Delete the parent. =A0*/ > =A0 =A0 =A0 detach_inferior (pid); > > - =A0 =A0 =A0tp =3D add_thread_silent (inferior_ptid); > - > - =A0 =A0 =A0tp->step_resume_breakpoint =3D step_resume_breakpoint; > - =A0 =A0 =A0tp->step_range_start =3D step_range_start; > - =A0 =A0 =A0tp->step_range_end =3D step_range_end; > - =A0 =A0 =A0tp->step_frame_id =3D step_frame_id; > - > - =A0 =A0 =A0/* Reset breakpoints in the child as appropriate. =A0*/ > - =A0 =A0 =A0follow_inferior_reset_breakpoints (); > + =A0 =A0 =A0add_thread_silent (inferior_ptid); > =A0 =A0 } > =A0 else > =A0 =A0 { > - =A0 =A0 =A0inferior_ptid =3D pid_to_ptid (pid); > - > =A0 =A0 =A0 /* Breakpoints have already been detached from the child by > =A0 =A0 =A0 =A0 infrun.c. =A0*/ > > =A0 =A0 =A0 if (ptrace (PT_DETACH, fpid, (PTRACE_TYPE_ARG3)1, 0) =3D=3D -= 1) > =A0 =A0 =A0 =A0perror_with_name (("ptrace")); > - =A0 =A0 =A0detach_inferior (pid); > =A0 =A0 } > > =A0 return 0; > Index: src/gdb/inf-ttrace.c > =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D > --- src.orig/gdb/inf-ttrace.c =A0 2009-05-21 23:45:24.000000000 +0100 > +++ src/gdb/inf-ttrace.c =A0 =A0 =A0 =A02009-05-24 17:09:03.000000000 +01= 00 > @@ -412,25 +412,13 @@ inf_ttrace_follow_fork (struct target_op > =A0 pid_t pid, fpid; > =A0 lwpid_t lwpid, flwpid; > =A0 ttstate_t tts; > - =A0struct thread_info *last_tp =3D NULL; > - =A0struct breakpoint *step_resume_breakpoint =3D NULL; > - =A0CORE_ADDR step_range_start =3D 0, step_range_end =3D 0; > - =A0struct frame_id step_frame_id =3D null_frame_id; > - > - =A0/* FIXME: kettenis/20050720: This stuff should really be passed as > - =A0 =A0 an argument by our caller. =A0*/ > - =A0{ > - =A0 =A0ptid_t ptid; > - =A0 =A0struct target_waitstatus status; > - > - =A0 =A0get_last_target_status (&ptid, &status); > - =A0 =A0gdb_assert (status.kind =3D=3D TARGET_WAITKIND_FORKED > - =A0 =A0 =A0 =A0 =A0 =A0 =A0 || status.kind =3D=3D TARGET_WAITKIND_VFORK= ED); > - > - =A0 =A0pid =3D ptid_get_pid (ptid); > - =A0 =A0lwpid =3D ptid_get_lwp (ptid); > - =A0 =A0last_tp =3D find_thread_pid (ptid); > - =A0} > + =A0struct thread_info *tp =3D inferior_thread (); > + > + =A0gdb_assert (tp->pending_follow.kind =3D=3D TARGET_WAITKIND_FORKED > + =A0 =A0 =A0 =A0 =A0 =A0 || tp->pending_follow.kind =3D=3D TARGET_WAITKI= ND_VFORKED); > + > + =A0pid =3D ptid_get_pid (inferior_ptid); > + =A0lwpid =3D ptid_get_lwp (inferior_ptid); > > =A0 /* Get all important details that core GDB doesn't (and shouldn't) > =A0 =A0 =A0know about. =A0*/ > @@ -462,16 +450,6 @@ inf_ttrace_follow_fork (struct target_op > > =A0 =A0 =A0 parent_inf =3D find_inferior_pid (pid); > > - =A0 =A0 =A0/* Copy user stepping state to the new inferior thread. =A0*/ > - =A0 =A0 =A0step_resume_breakpoint =3D last_tp->step_resume_breakpoint; > - =A0 =A0 =A0step_range_start =3D last_tp->step_range_start; > - =A0 =A0 =A0step_range_end =3D last_tp->step_range_end; > - =A0 =A0 =A0step_frame_id =3D last_tp->step_frame_id; > - > - =A0 =A0 =A0/* Otherwise, deleting the parent would get rid of this > - =A0 =A0 =A0 =A0breakpoint. =A0*/ > - =A0 =A0 =A0last_tp->step_resume_breakpoint =3D NULL; > - > =A0 =A0 =A0 inferior_ptid =3D ptid_build (fpid, flwpid, 0); > =A0 =A0 =A0 inf =3D add_inferior (fpid); > =A0 =A0 =A0 inf->attach_flag =3D parent_inf->attach_flag; > @@ -553,14 +531,6 @@ Detaching after fork from child process > =A0 =A0 =A0 =A0xmalloc (sizeof (struct inf_ttrace_private_thread_info)); > =A0 =A0 =A0 memset (ti->private, 0, > =A0 =A0 =A0 =A0 =A0 =A0 =A0sizeof (struct inf_ttrace_private_thread_info)= ); > - > - =A0 =A0 =A0ti->step_resume_breakpoint =3D step_resume_breakpoint; > - =A0 =A0 =A0ti->step_range_start =3D step_range_start; > - =A0 =A0 =A0ti->step_range_end =3D step_range_end; > - =A0 =A0 =A0ti->step_frame_id =3D step_frame_id; > - > - =A0 =A0 =A0/* Reset breakpoints in the child as appropriate. =A0*/ > - =A0 =A0 =A0follow_inferior_reset_breakpoints (); > =A0 =A0 } > > =A0 return 0; > Index: src/gdb/testsuite/gdb.threads/fork-thread-pending.c > =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D > --- /dev/null =A0 1970-01-01 00:00:00.000000000 +0000 > +++ src/gdb/testsuite/gdb.threads/fork-thread-pending.c 2009-05-24 17:09:= 03.000000000 +0100 > @@ -0,0 +1,109 @@ > +/* This testcase is part of GDB, the GNU debugger. > + > + =A0 Copyright 2008, 2009 Free Software Foundation, Inc. > + > + =A0 This program is free software; you can redistribute it and/or modify > + =A0 it under the terms of the GNU General Public License as published by > + =A0 the Free Software Foundation; either version 3 of the License, or > + =A0 (at your option) any later version. > + > + =A0 This program is distributed in the hope that it will be useful, > + =A0 but WITHOUT ANY WARRANTY; without even the implied warranty of > + =A0 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. =A0See the > + =A0 GNU General Public License for more details. > + > + =A0 You should have received a copy of the GNU General Public License > + =A0 along with this program. =A0If not, see . =A0*/ > + > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > + > +#define NUMTHREADS 10 > + > +volatile int done =3D 0; > + > +static void * > +start (void *arg) > +{ > + =A0while (!done) > + =A0 =A0usleep (100); > + =A0assert (0); > + =A0return arg; > +} > + > +void * > +thread_function (void *arg) > +{ > + =A0int x =3D * (int *) arg; > + > + =A0printf ("Thread <%d> executing\n", x); > + > + =A0while (!done) > + =A0 =A0usleep (100); > + > + =A0return NULL; > +} > + > +void * > +thread_forker (void *arg) > +{ > + =A0int x =3D * (int *) arg; > + =A0pid_t pid; > + =A0int rv; > + =A0int i; > + =A0pthread_t thread; > + > + =A0printf ("Thread forker <%d> executing\n", x); > + > + =A0switch ((pid =3D fork ())) > + =A0 =A0{ > + =A0 =A0case -1: > + =A0 =A0 =A0assert (0); > + =A0 =A0default: > + =A0 =A0 =A0wait (&rv); > + =A0 =A0 =A0done =3D 1; > + =A0 =A0 =A0break; > + =A0 =A0case 0: > + =A0 =A0 =A0i =3D pthread_create (&thread, NULL, start, NULL); > + =A0 =A0 =A0assert (i =3D=3D 0); > + =A0 =A0 =A0i =3D pthread_join (thread, NULL); > + =A0 =A0 =A0assert (i =3D=3D 0); > + > + =A0 =A0 =A0assert (0); > + =A0 =A0} > + > + =A0return NULL; > +} > + > +int > +main (void) > +{ > + =A0pthread_t threads[NUMTHREADS]; > + =A0int args[NUMTHREADS]; > + =A0int i, j; > + > + =A0/* Create a few threads that do mostly nothing, and then one that > + =A0 =A0 forks. =A0*/ > + =A0for (j =3D 0; j < NUMTHREADS - 1; ++j) > + =A0 =A0{ > + =A0 =A0 =A0args[j] =3D j; > + =A0 =A0 =A0pthread_create (&threads[j], NULL, thread_function, &args[j]= ); > + =A0 =A0} > + > + =A0args[j] =3D j; > + =A0pthread_create (&threads[j], NULL, thread_forker, &args[j]); > + > + =A0for (j =3D 0; j < NUMTHREADS; ++j) > + =A0 =A0{ > + =A0 =A0 =A0pthread_join (threads[j], NULL); > + =A0 =A0} > + > + =A0return 0; > +} > Index: src/gdb/testsuite/gdb.threads/fork-thread-pending.exp > =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D > --- /dev/null =A0 1970-01-01 00:00:00.000000000 +0000 > +++ src/gdb/testsuite/gdb.threads/fork-thread-pending.exp =A0 =A0 =A0 200= 9-05-24 17:29:19.000000000 +0100 > @@ -0,0 +1,128 @@ > +# Copyright (C) 2009 Free Software Foundation, Inc. > + > +# This program is free software; you can redistribute it and/or modify > +# it under the terms of the GNU General Public License as published by > +# the Free Software Foundation; either version 3 of the License, or > +# (at your option) any later version. > +# > +# This program is distributed in the hope that it will be useful, > +# but WITHOUT ANY WARRANTY; without even the implied warranty of > +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. =A0See the > +# GNU General Public License for more details. > +# > +# You should have received a copy of the GNU General Public License > +# along with this program. =A0If not, see . > + > +# There's no support for `set follow-fork-mode' in the remote > +# protocol. > +if { [is_remote target] } { > + =A0 =A0return 0 > +} > + > +# Only GNU/Linux is known to support `set follow-fork-mode child'. > +# > +if { ! [istarget "*-*-linux*"] } { > + =A0 =A0return 0 > +} > + > +set testfile fork-thread-pending > +set srcfile ${testfile}.c > +set binfile ${objdir}/${subdir}/${testfile} > + > +if {[gdb_compile_pthreads "${srcdir}/${subdir}/${srcfile}" "${binfile}" = executable {debug}] !=3D "" } { > + =A0 =A0return -1 > +} > + > +gdb_exit > +gdb_start > +gdb_reinitialize_dir $srcdir/$subdir > + > +gdb_load ${binfile} > +if ![runto_main] then { > + =A0 fail "Can't run to main" > + =A0 return 0 > +} > + > +gdb_test "set follow-fork-mode child" "" "1, set follow-fork-mode child" > +gdb_test "catch fork" "Catchpoint \[0-9\]* \\(fork\\)" "1, insert fork c= atchpoint" > +gdb_breakpoint "start" "" "1, set breakpoint at start" > + > +gdb_test "continue" "Catchpoint.*" "1, get to the fork event" > + > +gdb_test "info threads" " Thread .* Thread .* Thread .* Thread .*" "1, m= ultiple threads found" > + > +gdb_test "thread 2" "" "1, switched away from event thread" > + > +gdb_test "continue" "Not resuming.*" "1, refused to resume" > + > +set test "1, followed to the child, found one thread" > +gdb_test_multiple "info threads" "metest" { > + =A0 =A0-re " Thread .* Thread .*$gdb_prompt $" { > + =A0 =A0 =A0 fail "$test" > + =A0 =A0} > + =A0 =A0-re " Thread .*$gdb_prompt $" { > + =A0 =A0 =A0 pass "$test" > + =A0 =A0} > + =A0 =A0-re "$gdb_prompt $" { > + =A0 =A0 =A0 fail "$test (unknown output)" > + =A0 =A0} > + =A0 =A0timeout { > + =A0 =A0 =A0 fail "$test (timeout)" > + =A0 =A0} > +} > + > +gdb_test "continue" "Breakpoint 3, start.*" "1, get to the spawned threa= d in fork child" > + > +set test "1, followed to the child, found two threads" > +gdb_test_multiple "info threads" "$test" { > + =A0 =A0-re " Thread .* Thread .* Thread .*$gdb_prompt $" { > + =A0 =A0 =A0 fail "$test" > + =A0 =A0} > + =A0 =A0-re " Thread .* Thread .*$gdb_prompt $" { > + =A0 =A0 =A0 pass "$test" > + =A0 =A0} > + =A0 =A0-re "$gdb_prompt $" { > + =A0 =A0 =A0 fail "$test (unknown output)" > + =A0 =A0} > + =A0 =A0timeout { > + =A0 =A0 =A0 fail "$test (timeout)" > + =A0 =A0} > +} > + > +# Start over, but this time, don't switch away from the fork event threa= d. > + > +gdb_exit > +gdb_start > +gdb_reinitialize_dir $srcdir/$subdir > + > +gdb_load ${binfile} > +if ![runto_main] then { > + =A0 fail "Can't run to main" > + =A0 return 0 > +} > + > +gdb_test "set follow-fork-mode child" "" "2, set follow-fork-mode child" > +gdb_test "catch fork" "Catchpoint \[0-9\]* \\(fork\\)" "2, insert fork c= atchpoint" > +gdb_breakpoint "start" > + > +gdb_test "continue" "Catchpoint.*" "2, get to the fork event" > + > +gdb_test "info threads" " Thread .* Thread .* Thread .* Thread .*" "2, m= ultiple threads found" > + > +gdb_test "continue" "Breakpoint 3, start.*" "2, get to the spawned threa= d in fork child" > + > +set test "2, followed to the child, found two threads" > +gdb_test_multiple "info threads" "$test" { > + =A0 =A0-re " Thread .* Thread .* Thread .*$gdb_prompt $" { > + =A0 =A0 =A0 fail "$test" > + =A0 =A0} > + =A0 =A0-re " Thread .* Thread .*$gdb_prompt $" { > + =A0 =A0 =A0 pass "$test" > + =A0 =A0} > + =A0 =A0-re "$gdb_prompt $" { > + =A0 =A0 =A0 fail "$test (unknown output)" > + =A0 =A0} > + =A0 =A0timeout { > + =A0 =A0 =A0 fail "$test (timeout)" > + =A0 =A0} > +} > fyi, I just did an update and am getting a build failure (i686-linux). gcc -m32 -g -O2 -I. -I../../../src/gdb -I../../../src/gdb/common -I../../../src/gdb/config -DLOCALEDIR=3D"\"/usr/share/locale\"" -DHAVE_CONFIG_H -I../../../src/\ gdb/../include/opcode -I../../../src/gdb/../readline/.. -I../bfd -I../../../src/gdb/../bfd -I../../../src/gdb/../include -I../libdecnumber -I../../../src/gdb/..\ /libdecnumber -I../../../src/gdb/gnulib -Ignulib -DMI_OUT=3D1 -DTUI=3D1 -Wall -Wdeclaration-after-statement -Wpointer-arith -Wformat-nonliteral -Wno-pointer-sign\ -Wno-unused -Wno-switch -Wno-char-subscripts -Werror -c -o infrun.o -MT infrun.o -MMD -MP -MF .deps/infrun.Tpo ../../../src/gdb/infrun.c cc1: warnings being treated as errors ../../../src/gdb/infrun.c: In function =91follow_fork=92: ../../../src/gdb/infrun.c:298: warning: =91step_frame_id.special_addr_p=92 may be used uninitialized in this function ../../../src/gdb/infrun.c:298: warning: =91step_frame_id.code_addr_p=92 may be used uninitialized in this function ../../../src/gdb/infrun.c:298: warning: =91step_frame_id.stack_addr_p=92 may be used uninitialized in this function ../../../src/gdb/infrun.c:298: warning: =91step_frame_id.special_addr=92 may be used uninitialized in this function ../../../src/gdb/infrun.c:298: warning: =91step_frame_id.code_addr=92 may be used uninitialized in this function ../../../src/gdb/infrun.c:298: warning: =91step_frame_id.stack_addr=92 may be used uninitialized in this function ../../../src/gdb/infrun.c:297: warning: =91step_range_end=92 may be used uninitialized in this function ../../../src/gdb/infrun.c:296: warning: =91step_range_start=92 may be used uninitialized in this function ../../../src/gdb/infrun.c:295: warning: =91step_resume_breakpoint=92 may be used uninitialized in this function make: *** [infrun.o] Error 1 gcc's not smart enough to detect it's actually ok. 2009-05-24 Doug Evans * infrun.c (follow_fork): Initialize new step_* locals to avoid "may be used uninitialized" warnings. Index: infrun.c =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D RCS file: /cvs/src/src/gdb/infrun.c,v retrieving revision 1.377 diff -u -p -r1.377 infrun.c --- infrun.c 24 May 2009 18:00:08 -0000 1.377 +++ infrun.c 24 May 2009 20:26:28 -0000 @@ -290,12 +290,12 @@ follow_fork (void) /* Copy user stepping state to the new inferior thread. FIXME: the followed fork child thread should have a copy of most of the - parent thread structure's run control related fields, not just - these. */ - struct breakpoint *step_resume_breakpoint; - CORE_ADDR step_range_start; - CORE_ADDR step_range_end; - struct frame_id step_frame_id; + parent thread structure's run control related fields, not just these. + Initialized to avoid "may be used uninitialized" warnings from gcc. = */ + struct breakpoint *step_resume_breakpoint =3D NULL; + CORE_ADDR step_range_start =3D 0; + CORE_ADDR step_range_end =3D 0; + struct frame_id step_frame_id =3D { 0 }; if (!non_stop) {