Skip to content

Commit

Permalink
gdb: move clearing of tp->pending_follow to follow_fork_inferior
Browse files Browse the repository at this point in the history
A following patch will change targets so that when they detach an
inferior, they also detach any pending fork children this inferior may
have.  While doing this, I hit a case where we couldn't differentiate
two cases, where in one we should detach the fork detach but not in the
other.

Suppose we continue past a fork with "follow-fork-mode == child" &&
"detach-on-fork on".  follow_fork_inferior calls target_detach to detach
the parent.  In that case the target should not detach the fork
child, as we'll continue debugging the child.  As of now, the
tp->pending_follow field of the thread who called fork still contains
the details about the fork.

Then, suppose we run to a fork catchpoint and the user types "detach".
In that case, the target should detach the fork child in addition to the
parent.  In that case as well, the tp->pending_follow field contains
the details about the fork.

To allow targets to differentiate the two cases, clear
tp->pending_follow a bit earlier, when following a fork.  Targets will
then see that tp->pending_follow contains TARGET_WAITKIND_SPURIOUS, and
won't detach the fork child.

As of this patch, no behavior changes are expected.

Change-Id: I537741859ed712cb531baaefc78bb934e2a28153
  • Loading branch information
simark committed Dec 9, 2021
1 parent 28561a6 commit 577d216
Showing 1 changed file with 18 additions and 10 deletions.
28 changes: 18 additions & 10 deletions gdb/infrun.c
Original file line number Diff line number Diff line change
Expand Up @@ -601,6 +601,23 @@ holding the child stopped. Try \"set detach-on-fork\" or \
if (child_inf != nullptr)
gdb_assert (!child_inf->thread_list.empty ());

/* Clear the parent thread's pending follow field. Do this before calling
target_detach, so that the target can differentiate the two following
cases:
- We continue past a fork with "follow-fork-mode == child" &&
"detach-on-fork on", and therefore detach the parent. In that
case the target should not detach the fork child.
- We run to a fork catchpoint and the user types "detach". In that
case, the target should detach the fork child in addition to the
parent.
The former case will have pending_follow cleared, the later will have
pending_follow set. */
thread_info *parent_thread = find_thread_ptid (parent_inf, parent_ptid);
gdb_assert (parent_thread != nullptr);
parent_thread->pending_follow.set_spurious ();

/* Detach the parent if needed. */
if (follow_child)
{
Expand Down Expand Up @@ -668,7 +685,6 @@ follow_fork ()
{
bool follow_child = (follow_fork_mode_string == follow_fork_mode_child);
bool should_resume = true;
struct thread_info *tp;

/* Copy user stepping state to the new inferior thread. FIXME: the
followed fork child thread should have a copy of most of the
Expand Down Expand Up @@ -714,7 +730,7 @@ follow_fork ()
}
}

tp = inferior_thread ();
thread_info *tp = inferior_thread ();

/* If there were any forks/vforks that were caught and are now to be
followed, then do so now. */
Expand Down Expand Up @@ -768,14 +784,6 @@ follow_fork ()
}
else
{
/* This pending follow fork event is now handled, one way
or another. The previous selected thread may be gone
from the lists by now, but if it is still around, need
to clear the pending follow request. */
tp = find_thread_ptid (parent_targ, parent);
if (tp)
tp->pending_follow.set_spurious ();

/* This makes sure we don't try to apply the "Switched
over from WAIT_PID" logic above. */
nullify_last_target_wait_ptid ();
Expand Down

0 comments on commit 577d216

Please sign in to comment.