From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 6184 invoked by alias); 1 May 2009 16:24:51 -0000 Received: (qmail 5867 invoked by uid 22791); 1 May 2009 16:24:48 -0000 X-SWARE-Spam-Status: No, hits=-2.1 required=5.0 tests=AWL,BAYES_00,SARE_SUB_GETRID,SPF_PASS X-Spam-Check-By: sourceware.org Received: from mail.codesourcery.com (HELO mail.codesourcery.com) (65.74.133.4) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Fri, 01 May 2009 16:24:39 +0000 Received: (qmail 8081 invoked from network); 1 May 2009 16:24:37 -0000 Received: from unknown (HELO orlando) (pedro@127.0.0.2) by mail.codesourcery.com with ESMTPA; 1 May 2009 16:24:37 -0000 From: Pedro Alves To: gdb-patches@sourceware.org, Eli Zaretskii Subject: Re: Can we get rid of go32_stop? (and its normal_stop call?) Date: Fri, 01 May 2009 16:24:00 -0000 User-Agent: KMail/1.9.10 References: <200905011514.27632.pedro@codesourcery.com> <83vdokddvk.fsf@gnu.org> In-Reply-To: <83vdokddvk.fsf@gnu.org> MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Content-Disposition: inline Message-Id: <200905011724.36973.pedro@codesourcery.com> 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/msg00026.txt.bz2 On Friday 01 May 2009 16:47:11, Eli Zaretskii wrote: > > From: Pedro Alves > > Date: Fri, 1 May 2009 15:14:27 +0100 > > Cc: Eli Zaretskii > > > > - 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? Nothing at all. The default implementation of to_stop is target_ignore. > > 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. Not at all. I knew that there are no 2 separate processes involved, but, your description is very enlightening. IMO, it would be nice to paste your description below at the top of go32-nat.c. > 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. I see. To be clear, in this case, is the debuggee considered dead and gone? No further debugging possible? > In this situation, can we still be > sure that go32_kill_inferior or go32_mourn_inferior would be called? I think so. Currently, this "just-in-case" cleanup, is done on go32_create_inferior, so only on the next "run". If for some reason, some abnormal event happens, and the user is dropped into GDB's shell, the next "run" will clean up. But, notice one thing --- the go32_ops target will still be pushed on the stack, and so the current target still is considered to have execution (target_has_execution is true, and inferior_ptid will still point at SOME_PID). So, when the user does "run", GDB will ask if the user wants to kill the current program, and will refuse to go ahead if the user says "no". If the user says "yes", then, target_kill is called to kill the current program (which ends up in go32_kill_inferior), all before reaching go32_create_inferior. This is run_command->kill_if_already_running->target_kill. So, if we do the said cleaning up on go32_mourn_inferior, and make sure that go32_mourn_inferior is called from go32_kill_inferior, I think you'll get the same ammount of "cleanup after the fact" as we have currently. In fact, you'll have more --- if something goes wild, the user will be able to do full cleaning up with the "kill" command. Currently, "kill" doesn't call `cleanup_client', after my changes, it will --- I'm assuming that to be a good thing. > 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. :-) I think that with my proposed change, we get the same ammount of paranoia (even more), but, this needs to be at least minimally tested, of course. > 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. I don't think that's required, for the reasons described above. BTW, have you ever had any success running djgpp from inside an emulator on linux, say, 'dosemu'? -- Pedro Alves