public inbox for gdb@sourceware.org
 help / color / mirror / Atom feed
From: Simon Marchi <simark@simark.ca>
To: Jan Vrany <jan.vrany@fit.cvut.cz>,
	"gdb@sourceware.org" <gdb@sourceware.org>
Cc: "Joel Brobecker" <brobecker@adacore.com>,
	"Tom Tromey" <tom@tromey.com>,
	"André Pönitz" <apoenitz@t-online.de>,
	"Jonah Graham" <jonah@kichwacoders.com>
Subject: Re: MI3 and async notifications
Date: Wed, 19 Jun 2019 15:29:00 -0000	[thread overview]
Message-ID: <d56154b8-3495-e185-68bc-3e6e05a5f148@simark.ca> (raw)
In-Reply-To: <70be86e627f6ec578217f01df9af914080b181c2.camel@fit.cvut.cz>

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

  reply	other threads:[~2019-06-19 15:29 UTC|newest]

Thread overview: 26+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-06-10 21:19 Jan Vrany
2019-06-10 23:23 ` Jonah Graham
2019-06-11  8:50   ` Jan Vrany
2019-06-11 13:37     ` Jonah Graham
2019-07-05 20:00       ` Pedro Alves
2019-07-05 21:58         ` Jonah Graham
2019-06-15 14:34 ` Tom Tromey
2019-06-17 10:53   ` Jan Vrany
2019-06-17 12:11     ` Jonah Graham
2019-06-17 12:14     ` Joel Brobecker
2019-06-17 12:26       ` Jonah Graham
2019-06-17 12:56         ` Joel Brobecker
2019-06-17 13:12           ` Jan Vrany
2019-06-17 13:23             ` Jonah Graham
2019-06-17 20:45               ` Joel Brobecker
2019-06-17 20:58                 ` Jan Vrany
2019-06-17 21:50                   ` Jonah Graham
2019-06-17 13:12           ` Jonah Graham
2019-06-17 19:52     ` André Pönitz
2019-06-18  3:14 ` Simon Marchi
2019-06-18 20:38   ` Jan Vrany
2019-06-19 15:29     ` Simon Marchi [this message]
2019-06-19 20:58       ` Jan Vrany
2019-06-20 15:31         ` Simon Marchi
2019-06-20 20:46           ` Jan Vrany
2019-07-05 19:35           ` Pedro Alves

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=d56154b8-3495-e185-68bc-3e6e05a5f148@simark.ca \
    --to=simark@simark.ca \
    --cc=apoenitz@t-online.de \
    --cc=brobecker@adacore.com \
    --cc=gdb@sourceware.org \
    --cc=jan.vrany@fit.cvut.cz \
    --cc=jonah@kichwacoders.com \
    --cc=tom@tromey.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).