This is the mail archive of the
gdb-patches@sourceware.org
mailing list for the GDB project.
Re: Can we get rid of go32_stop? (and its normal_stop call?)
- From: Eli Zaretskii <eliz at gnu dot org>
- To: Pedro Alves <pedro at codesourcery dot com>
- Cc: gdb-patches at sourceware dot org
- Date: Fri, 01 May 2009 18:47:11 +0300
- Subject: Re: Can we get rid of go32_stop? (and its normal_stop call?)
- References: <200905011514.27632.pedro@codesourcery.com>
- Reply-to: Eli Zaretskii <eliz at gnu dot org>
> From: Pedro Alves <pedro@codesourcery.com>
> Date: Fri, 1 May 2009 15:14:27 +0100
> Cc: Eli Zaretskii <eliz@gnu.org>
>
> - go32_stop is registered as target_stop callback, but,
> target_stop is only useful if the target supports
> asynchronous execution control --- djgpp doesn't support it.
You are probably right about that. But what will happen if to_stop is
not registered and target_stop is somehow called nonetheless?
> if (prog_has_started)
> {
> go32_stop (inferior_ptid);
> go32_kill_inferior (ops);
> }
>
> AFAICS, this is doing cleanup from a previous run. It seems
> weird to call go32_kill_inferior here, since go32_create_inferior
> will only ever be called if the previous inferior is gone already,
> because the "run" command always kills the previous process. If the
> previous process exited by itself, then go32_mourn_inferior is called,
> which itself calls go32_kill_inferior.
I'm less sure about this part. Let me tell you something that I'm not
sure you know about how DJGPP debugging works; apologies if I'm
preaching to the choir.
When the DJGPP port of GDB is debugging a DJGPP program natively,
there are no 2 separate processes, the debuggee and GDB itself, as on
other systems. (This is DOS, where there can only be one active
process at any given time, remember?) Instead, GDB and the debuggee
live in the same process. What go32_create_inferior does (in the
functions it calls from the DJGPP debug support library libdbg.a) is
load the debuggee's executable file, set it up for execution as the
stub loader (a short real-mode program prepended to each DJGPP
executable) normally would, and do a lot of preparations for swapping
between GDB's and debuggee's internal state, primarily the wrt
exception handlers. Then running the debuggee simply means longjmp
into it where its PC is and let it run until it stops for some reason.
When it stops, GDB catches the exception that stopped it and longjmp's
back into its own code. All the possible exit points of the debuggee
are watched; for example, the normal exit point is recognized because
a DOS program issues a special system call to exit. If one of those
exit points is hit, we mourn the inferior and clean up after it.
Cleaning up is very important, even if the process exits normally,
because otherwise we might leave behind traces of previous execution,
and in several cases GDB itself might be left hosed, because all the
exception handlers were not restored.
So far so good. But the plot thickens if abnormal events happen, such
as an exception inside the debuggee or just a Ctrl-C pressed by the
user at a wrong time. We might get back to GDB before we had a chance
to clean up after the debuggee. In this situation, can we still be
sure that go32_kill_inferior or go32_mourn_inferior would be called?
If not, then making sure they are called and the necessary cleanup is
done would not hurt anything.
> AFAICS, go32_kill_inferior is always called either when you kill the
> program or when it exits cleanly
That may be so as far as the normal flow of control is concerned. But
given that there could be a lot of longjmp-ing around, I'm less sure.
Maybe I'm paranoiac.
> It also looks strange to have mourn_inferior call kill_inferior, and
> not the other way around, so I've moved the cleaning up to
> go32_mourn_inferior.
This is okay.
So maybe we should make these changes, but leave alone the call to
go32_kill_inferior inside go32_create_inferior, conditioned on the
prog_has_started flag, just in case.
Thanks.