public inbox for
 help / color / mirror / Atom feed
From: Andrew Burgess <>
Subject: Re: [PATCH v2]     remote.c: Allow inferior to reply with an error
Date: Tue, 17 Jan 2023 16:30:29 +0000	[thread overview]
Message-ID: <> (raw)
In-Reply-To: <>

AlexandraHájková writes:

> From: Alexandra Hájková <>
>     When gdb communicates with some kind of gdbserver or gdbserver
>     stub over the remote protocol, the only possible response to
>     the QSetWorkingDir packet is "OK".  If the remote will reply
>     with anything else, gdb will complain about the unexpected reply.
>     [remote] Sending packet: $QSetWorkingDir:2f746d70#bb
>     [remote] Packet received: E00
>     Remote replied unexpectedly while setting the inferior's working
>     directory: E00
>     (gdb)
>     Allow remote to send an error message over as a QSetWorkingDir
>     packet reply.
>     [remote] Sending packet: $QSetWorkingDir:2f746d70#bb
>     [remote] Packet received: does not exist
>     Remote failed to set working directory: directory does not exist.

So, I started reviewing this patch, and wrote a whole bunch of stuff.
One thing I wrote was, you should really add a test for this that uses
the existing gdbserver.

So, I thought, I wonder what errors gdbserver currently sends back, so I
took a look at the QSetWorkingDir handling in gdbserver/
Weird, I thought, it doesn't appear to send back any errors.

So then I took a look at set_inferior_cwd in gdbserver/, and
all that it does is cache the requested directory.

So, then I went to the docs again, and re-read what we say about

  This packet is used to inform the remote server of the intended
  current working directory for programs that are going to be executed.

Note the use of the word 'intended'.  This packet does not try to change
the directory NOW, it will try to change the directory LATER, when the
inferior is actually executed.

My current reading of the docs is that the QSetWorkingDir packet, is
either not supported, or should never fail.

If you specify an invalid directory then future attempts to start an
inferior will fail, but the QSetWorkingDir packet itself shouldn't

I guess we could decide that we want to extend QSetWorkingDir to allow
for it to send back error packets, I'm not sure that's entirely a good
idea though as that's not how the existing gdbserver works... but if we
did want to do that then we should probably improve the documentation to
explain that some gdbservers will cache the passed in directory and
return an error later, while others might choose to immediately change
directory and return an error now.

Because I already wrote it, I've left all my original review comments
inline below, but I'm not sure if you will want to roll a v3 or not.


> ---
> V2 does not change the behaviour of gdb in a case it wasn't possible to
> set the inferior's working directory. It just allows to pass the error
> message to gdb.
>  gdb/doc/gdb.texinfo |  3 +++
>  gdb/remote.c        | 12 +++++++++---
>  2 files changed, 12 insertions(+), 3 deletions(-)
> diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
> index 9c0018ea5c1..5df9a5a9178 100644
> --- a/gdb/doc/gdb.texinfo
> +++ b/gdb/doc/gdb.texinfo
> @@ -42517,6 +42517,9 @@ Reply:
>  @table @samp
>  @item OK
>  The request succeeded.
> +
> +@item E.errtext
> +An error occurred.  Reply with an error message.

I think that we should not limit the description here to just
'E.errtext', all the other error packets also support the 'Enn' format,
and for consistency, I think we should document that as supported here

>  @end table
>  @item qfThreadInfo
> diff --git a/gdb/remote.c b/gdb/remote.c
> index 218bca30d04..ea89759e85a 100644
> --- a/gdb/remote.c
> +++ b/gdb/remote.c
> @@ -10397,8 +10397,10 @@ remote_target::extended_remote_set_inferior_cwd ()
>    if (packet_support (PACKET_QSetWorkingDir) != PACKET_DISABLE)
>      {
>        const std::string &inferior_cwd = current_inferior ()->cwd ();
> +      char *buf;
>        remote_state *rs = get_remote_state ();
> +      buf = rs-> ();

Given that BUF is only used later within the 'if (packet_ok (...))'
block, I'd move the declaration, and definition of BUF into that block.

Also, for C++, you don't need to declare the variable at the start of
the block, just 'char *buf = ....' is fine.

>        if (!inferior_cwd.empty ())
>  	{
>  	  std::string hexpath
> @@ -10420,11 +10422,15 @@ remote_target::extended_remote_set_inferior_cwd ()
>        getpkt (&rs->buf, 0);
>        if (packet_ok (rs->buf,
>  		     &remote_protocol_packets[PACKET_QSetWorkingDir])
> -	  != PACKET_OK)
> -	error (_("\
> +	  != PACKET_OK) {

A bunch of the following lines are indented entirely with spaces.
Unfortunately GNU style is a mix of tabs and spaces, so you need to
figure out how to configure your editor to indent lines correctly.  I'm
surprised that this doesn't get highlighted in a 'git diff' / 'git show'
output due to our .gitattributes file.

> +          if (buf[0] == 'E' && buf[1] == '.')
> +	    error (_("Remote failed to set working directory: %s"), buf + 2);
> +          else
> +              error (_("\
>  Remote replied unexpectedly while setting the inferior's working\n\

I think we should handle both error packet formats here.  Also, while
looking at this code, I noticed that we don't appear to check the
contents of the reply packet in the PACKET_OK case.  The docs say the
reply should be 'OK', but, we actually accept anything.  Maybe we should
"fix" that while we're here?

I'd suggest something like this:

      switch (packet_ok (rs->buf,
	case PACKET_OK:
	  if (strcmp (rs-> (), "OK") == 0)
	  error (_("\
Remote replied unexpectedly while setting the inferior's working\n	\
directory: %s."),
		 rs-> ());

	    char *buf = rs-> ();
	    if (buf[0] == 'E' && buf[1] == '.' && buf[2] != '\0')
	      error (_("Remote failed to set working directory: %s"), buf + 2);
	      error (_("Remote failed to set working directory: %s"), buf);

	  error (_("Remote does not support changing the working directory"));

This includes support for the 'E.msg' style error that you're adding,
but also allows for the more generic Enn error that all the other
packets seem to support.

In the PACKET_OK case we check that the remote sent back and 'OK', and
if not we get to reuse the existing unexpected reply error.

And finally, we handle the PACKET_UNKNOWN case with an appropriate

> -directory: %s"),
> +directory: %s."),
>  	       rs-> ());

With the definition of BUF now in this block, I'd probably replace the
'rs->' with a reuse of BUF, I think that's going to appear
more consistent.

> +      }
>      }
>  }
> -- 
> 2.39.0

  parent reply	other threads:[~2023-01-17 16:30 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-01-13 11:59 
2023-01-13 13:16 ` Eli Zaretskii
2023-01-17 16:30 ` Andrew Burgess [this message]
2023-01-18  9:48   ` Mark Wielaard
2023-01-18 18:10     ` Andrew Burgess
2023-01-18 13:37   ` Alexandra Petlanova Hajkova
2023-01-18 18:19     ` Andrew Burgess

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:

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

  git send-email \ \ \

* 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).