remove pop_target

This patch fixes the target double-close problem (PR remote/15266),
and in the process removes pop_target entire (PR remote/15256).

The first issue is that pop_target calls target_close.  However, it
then calls unpush_target, which also calls target_close.  This means
targets must be able to be closed twice.  Not only is this strange,
but it also directly contradicts the contract of to_xclose targets.
(We currently have just a single such target, and it is never pushed;
but I plan to add more, and so this latent bug is triggered.)

The second issue is that it seems to me that calling pop_target is
often unsafe.  This is what cropped up in 15256, where the remote
target assumed that it could pop_target -- but there was another
target higher on the stack, leading to confusion.

But, it is always just as easy to call unpush_target as it is to call
pop_target; and it is also safer.  So, removing pop_target seemed like
an improvement.

Finally, this adds an assertion to target_close to ensure that no
currently-pushed target can be closed.

Built and regtested on x86-64 Fedora 18; both natively and using the
native-gdbserver board file.

	PR remote/15256, PR remote/15266:
	* bfd-target.c (target_bfd_reopen): Initialize to_magic.
	* monitor.c (monitor_detach): Use unpush_target.
	* remote-m32r-sdi.c (m32r_detach): Use unpush_target.
	* remote-mips.c (mips_detach): Use unpush_target.  Don't
	call mips_close.
	* remote-sim.c (gdbsim_detach): Use unpush_target.
	* target.c (pop_target): Remove.
	(pop_all_targets_above): Don't call target_close.
	(target_close): Assert that the target is unpushed.
	* target.h (pop_target): Don't declare.
	* tracepoint.c (tfile_open): Use unpush_target.
This commit is contained in:
Tom Tromey
2013-07-25 14:34:51 +00:00
parent c22a2b88fe
commit 7fdc15218d
9 changed files with 25 additions and 28 deletions

View File

@@ -1093,26 +1093,11 @@ unpush_target (struct target_ops *t)
return 1;
}
void
pop_target (void)
{
target_close (target_stack); /* Let it clean up. */
if (unpush_target (target_stack) == 1)
return;
fprintf_unfiltered (gdb_stderr,
"pop_target couldn't find target %s\n",
current_target.to_shortname);
internal_error (__FILE__, __LINE__,
_("failed internal consistency check"));
}
void
pop_all_targets_above (enum strata above_stratum)
{
while ((int) (current_target.to_stratum) > (int) above_stratum)
{
target_close (target_stack);
if (!unpush_target (target_stack))
{
fprintf_unfiltered (gdb_stderr,
@@ -3781,6 +3766,8 @@ debug_to_open (char *args, int from_tty)
void
target_close (struct target_ops *targ)
{
gdb_assert (!target_is_pushed (targ));
if (targ->to_xclose != NULL)
targ->to_xclose (targ);
else if (targ->to_close != NULL)