From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 42895 invoked by alias); 19 Jun 2019 15:29:40 -0000 Mailing-List: contact gdb-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-owner@sourceware.org Received: (qmail 42800 invoked by uid 89); 19 Jun 2019 15:29:40 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-6.0 required=5.0 tests=AWL,BAYES_00,SPF_HELO_PASS,SPF_PASS autolearn=ham version=3.3.1 spammy=shoes, everybody, race, H*r:172.16.0 X-HELO: simark.ca Received: from simark.ca (HELO simark.ca) (158.69.221.121) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Wed, 19 Jun 2019 15:29:38 +0000 Received: from [172.16.0.120] (192-222-181-218.qc.cable.ebox.net [192.222.181.218]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by simark.ca (Postfix) with ESMTPSA id 7D3621E7C0; Wed, 19 Jun 2019 11:29:35 -0400 (EDT) Subject: Re: MI3 and async notifications To: Jan Vrany , "gdb@sourceware.org" Cc: Joel Brobecker , Tom Tromey , =?UTF-8?B?QW5kcsOpIFDDtm5pdHo=?= , Jonah Graham References: <70fdd9107d9bb3cee0a1a342aedc05bf3c8e9bae.camel@fit.cvut.cz> <7530cc91-5457-0a84-57a4-5b64ddb95f13@simark.ca> <70be86e627f6ec578217f01df9af914080b181c2.camel@fit.cvut.cz> From: Simon Marchi Message-ID: Date: Wed, 19 Jun 2019 15:29:00 -0000 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:60.0) Gecko/20100101 Thunderbird/60.7.0 MIME-Version: 1.0 In-Reply-To: <70be86e627f6ec578217f01df9af914080b181c2.camel@fit.cvut.cz> Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 7bit X-SW-Source: 2019-06/txt/msg00056.txt.bz2 On 2019-06-18 4:38 p.m., Jan Vrany wrote: > Hi, > >> I am skeptical about the complex logic you are talking about to handle both >> =breakpoint-created notifications and responses to the -break-insert. Both contain pretty >> much the same information. So rather than adding an option in GDB for emitting async >> notifications unconditionally, can't you just process both using the same function? That >> doesn't really complicated, but maybe I am misunderstanding your problemi, in which case >> please expand. > > OK, let me expand (hopefully not too much) > > I have a (general purpose) library that provides higher-level interface > to GDB/MI. Strictly speaking, it is not bound to any particular UI frontend. > > This library essentially provides three things: > > (i) (supposedly) easy to use API to send MI commands, like: > > gdb send: (GDBMI_break_insert arguments: { 'main' }) andWithResultDo:[ :result | > result isSuccess ifTrue:[ > Stdout print: 'Breakpoint inserted' > ] ifFalse:[ > Stderr print: 'Oops, something went wrong!' > ] > ] > > (sorry for bit arcane syntax, hope you can make sense of it) > > (ii) provide object model of the debugger and its state (like, inferiors, their threads, > frames in thread, variables, registers, breakpoints) like: > > "/ Prints the stack of first thread" > gdb selectedInferior threads first stack do:[:frame| > Stdout print: frame printString > ] > > The idea is that if the inferior is stopped, the model is up-to-date, when it's running, > then "reasonable up-to-date", no guarantees. > > (iii) provide a way to get notified of changes, like: > > gdb when: GDBBreakpointModifiedEvent do: [:event | > "/ something has changed, redraw the list to display > "/ up-to-date information > breakpointListPane redraw. > ] > > This is essential to build an UI on top of this library > > All the above is API exposed to library user. This design has the advantages > of being flexible - users can issue commands on their own, I do not have to > implement and maintain wrapping API rich enough to handle all cases - and > and because is close to GDB/MI, I don't really need to document it in depth, looking to > GDB documentation gives you very good idea what how to use it. Reusing GDB events > to notify clients of my library has the same advantage - no need to implement my > own event hierarchy and document them. > > But if I don't get events in cases when they're result of an MI command, the only > way I can think of handling it is to intercept command result event and: > 1) examine the result (and sometimes the originating command itself) and do the > processing > 2) synthesize an event as if it were send by gdb and push it back so it's delivered > to users of the library - but in this case I have to make sure it is delivered only > to "external" observers and not "internal" observers which are responsible of keeping > the model up-to-date. > > Both steps have to cared for case-by-case (like, -break-insert response carries data > - the breakpoint inserted - while response to -gdb-set is plain ^done so in order to > update model I have to dig into the command itself, retrieve it's parameters and > reconstruct data from there). > > All this is indeed doable and in fact, I do this already for some commands to meet my > need back then, but then I realized I need more of this and was thinking how to avoid > all that code. A quick experiment shows that always emitting a notification solves > most (all?) issues I experienced, which is why brought it here. > > Does it make sense? Hi Jan, Thanks for the detailed explanation. I am not in your shoes, so I might have a wrong picture of the situation, but this doesn't sound really complicated. Isn't "synthesizing" an event from the command result just calling the same function as you do when getting a =breakpoint-created. Or am I missing something? I don't really understand the difference between external and internal observers (that's probably specific to your design). Specifically, I don't see what's the difference between a "real" event that would come from GDB, versus an synthetic event that you would have injected in your system from the -break-insert response. Let's say you do get async events for breakpoints you create with -break-insert, then you would forward these events to all these observers? So in the case where you generate these events yourself based on the -break-insert response, why shouldn't you also send them to all observers? The observers wouldn't know whether it's a "real" event coming from GDB or one you created yourself, so it shouldn't make any difference to them. Or (re-reading your message, I realized that this is what you might be trying to explain) are you saying that your library is very low level, and that users of the library send "-break-insert" on their own and your library just forwards the MI command to GDB, so your library doesn't really know (unless it sniffs the user command) that a -break-insert command has been issued? If so, that might explain my incomprehension. All the MI-handling code I have been exposed to has been a bit more high level, where the user calls some "breakInsert" function of the library. The library knows it's sending a -break-insert, so it can easily handle the response however it wants (including generating a "breakpoint created" event if it wants to). >> It would be useful to have a very concrete use case where you could point out "see here, >> I am missing some info and a notification would be useful". It could very well be that >> some notifications are just missing. > > To make me clear, I'm not saying that some information is missing, just that the way > it is delivered seem to be inconvenient given the way I use it. It may well be I use it > the wrong way :-) We'll see once we understand each other better :). >> Also, I am a bit worried by a proposal in the thread, which would be to remove information >> from the -break-insert ^done response, arguing that the async notification would have already >> been emitted. It is clear and unambiguous how to map a response to a request, but it would not >> be obvious to map an async notification to a request. So it appears to me as a regression in >> functionality. > > This is why I said that - for example - for -break-insert we need to respond with - at least - > ^done,bkpt-number=1. For some other. like -gdb-set I don't think we need to What I am worried about is that doing a change like this has a pretty big cost for on all frontends that have this currently implemented, so it needs to have a pretty strong justification. It's not just moving the data fields a little bit, or adding something that everybody else can ignore, it would require a significant flow change. A frontend that is just interested in setting a breakpoint and getting the result of that (i.e. the simple case) now needs to do something non-trivial: send the command, listen for an event, store it somewhere, handle it when receiving the ^done corresponding to the command. This brings some concurrency/race condition problems that are just not there in the request-response scheme. So at least, if we end up choosing to unconditionally emit the =breakpoint-created event, I would prefer keeping the -break-insert response as-is, for backwards compatibility (for existing frontends) and simplicity (for basic use cases), even if it means there's some redundancy. Simon