public inbox for gdb-patches@sourceware.org
 help / color / mirror / Atom feed
From: Simon Marchi <simon.marchi@polymtl.ca>
To: Andrew Burgess <andrew.burgess@embecosm.com>, gdb-patches@sourceware.org
Subject: Re: [PATCHv3 1/3] gdb/python: introduce gdb.TargetConnection object type
Date: Wed, 20 Oct 2021 22:00:37 -0400	[thread overview]
Message-ID: <2e4bfc98-842e-2035-2cf3-26c8fddd15dd@polymtl.ca> (raw)
In-Reply-To: <b2a47740d7e99b46b49f96f775b39c11929141f1.1634638441.git.andrew.burgess@embecosm.com>



On 2021-10-19 06:17, Andrew Burgess wrote:
> This commit adds a new object type gdb.TargetConnection.  This new
> type represents a connection within GDB (a connection as displayed by
> 'info connections').
> 
> There's three ways to find a gdb.TargetConnection, there's a new
> 'gdb.connections()' function, which returns a list of all currently
> active connections.
> 
> Or you can read the new 'connection' property on the gdb.Inferior
> object type, this contains the connection for that inferior (or None
> if the inferior has no connection, for example, it is exited).
> 
> Finally, there's a new gdb.events.connection_removed event registry,
> this emits a new gdb.ConnectionEvent whenever a connection is removed
> from GDB (this happens when all inferiors using a connection exit).
> The gdb.ConnectionEvent has a 'connection' property, which is the
> gdb.TargetConnection being removed from GDB.
> 
> The gdb.TargetConnection has a 'is_valid()' method.  A connection
> object becomes invalid when the underlying connection is removed from
> GDB (all inferiors using the connection exit).
> 
> The gdb.TargetConnection has the following read-only properties:
> 
>   'num': The number for this connection,
> 
>   'type': e.g. 'native', 'remove', 'sim', etc
> 
>   'description': The longer description as seen in the 'info
>                  connections' command output.
> 
>   'details': A string or None.  Extra details for the connection, for
>              example, a remote connection's details might be
>              'hostname:port'.
> ---
>  gdb/Makefile.in                               |   1 +
>  gdb/NEWS                                      |  16 +
>  gdb/doc/python.texi                           |  92 ++++-
>  gdb/observable.c                              |   1 +
>  gdb/observable.h                              |   3 +
>  gdb/python/py-all-events.def                  |   1 +
>  gdb/python/py-connection.c                    | 366 ++++++++++++++++++
>  gdb/python/py-event-types.def                 |   5 +
>  gdb/python/py-inferior.c                      |  16 +
>  gdb/python/python-internal.h                  |   6 +
>  gdb/python/python.c                           |   5 +
>  gdb/target-connection.c                       |   4 +
>  .../gdb.multi/multi-target-info-inferiors.exp |  38 ++
>  .../gdb.multi/multi-target-info-inferiors.py  |  63 +++
>  gdb/testsuite/gdb.python/py-connection.c      |  22 ++
>  gdb/testsuite/gdb.python/py-connection.exp    |  63 +++
>  gdb/testsuite/gdb.python/py-inferior.exp      |  20 +-
>  17 files changed, 718 insertions(+), 4 deletions(-)
>  create mode 100644 gdb/python/py-connection.c
>  create mode 100644 gdb/testsuite/gdb.multi/multi-target-info-inferiors.py
>  create mode 100644 gdb/testsuite/gdb.python/py-connection.c
>  create mode 100644 gdb/testsuite/gdb.python/py-connection.exp
> 
> diff --git a/gdb/Makefile.in b/gdb/Makefile.in
> index 4201f65e68d..5ec58aba439 100644
> --- a/gdb/Makefile.in
> +++ b/gdb/Makefile.in
> @@ -392,6 +392,7 @@ SUBDIR_PYTHON_SRCS = \
>  	python/py-breakpoint.c \
>  	python/py-cmd.c \
>  	python/py-continueevent.c \
> +	python/py-connection.c \

This is not in alphabetical order :).

>  	python/py-event.c \
>  	python/py-evtregistry.c \
>  	python/py-evts.c \
> diff --git a/gdb/NEWS b/gdb/NEWS
> index bd26d2b1ec2..43b81df526d 100644
> --- a/gdb/NEWS
> +++ b/gdb/NEWS
> @@ -45,6 +45,22 @@ maint show internal-warning backtrace
>       event is triggered once GDB decides it is going to exit, but
>       before GDB starts to clean up its internal state.
>  
> +  ** New gdb.TargetConnection object type that represents a connection
> +     (as displayed by the 'info connections' command).
> +
> +  ** The gdb.Inferior type now has a 'connection' property which is an
> +     instance of gdb.TargetConnection, the connection used by this
> +     inferior.  This can be None if the inferior has no connection
> +     (for example, when exited).

"when exited" is not completely accurate (see below, I wrote that other
comment before).

> +A @code{gdb.TargetConnection} has the following method:
> +
> +@defun TargetConnection.is_valid ()
> +Return @code{True} if the @code{gdb.TargetConnection} object is valid,
> +@code{False} if not.  A @code{gdb.TargetConnection} will become
> +invalid if the connection no longer exists within @value{GDBN}, this
> +will happen when all the inferiors using that connection exit.

I don't think the last part is completely accurate.  In some cases,
an inferior will keep its process target (and therefore keep the
connection alive) after exiting.  For instance, if you push the native
target explicitly, or if you connect using the extended-remote protocol.
You could say "this will happen when no inferior use the connection" or
something along those lines.

> +gdbpy_ref<>
> +target_to_connection_object (process_stratum_target *target)
> +{
> +  if (target == nullptr)
> +    return gdbpy_ref<>::new_reference (Py_None);
> +
> +  gdbpy_ref <connection_object> conn_obj = all_connection_objects[target];
> +  if (conn_obj == nullptr)
> +    {
> +      conn_obj.reset (PyObject_New (connection_object,
> +				    &connection_object_type));
> +      if (conn_obj == nullptr)
> +	return nullptr;
> +
> +      conn_obj->target = target;
> +
> +      /* PyObject_New initializes the new object with a refcount of 1.  This
> +	 counts for the reference we are keeping in the target_ops data.  */
> +      all_connection_objects[target] = conn_obj;

I find this comment more confusing than helpful.  The strong reference
created by PyObject_New belongs to conn_obj, which is then returned by
this function.  The strong reference belonging to the map (what I
presume you mean by "target_ops data") is created when copying conn_obj
into the map.  In the end all references are the same, I just find it a
bit confusing.

> +/* Callback for the connection_removed observer.  */
> +
> +static void
> +connpy_connection_removed (process_stratum_target *target)
> +{
> +  if (!gdb_python_initialized)
> +    return;
> +
> +  gdbpy_enter enter_py (get_current_arch (), current_language);
> +
> +  if (!evregpy_no_listeners_p (gdb_py_events.connection_removed))
> +    if (emit_connection_event (target, gdb_py_events.connection_removed) < 0)
> +      gdbpy_print_stack ();
> +
> +  gdbpy_ref <connection_object> conn_obj = all_connection_objects[target];
> +  if (conn_obj != nullptr)
> +    {
> +      conn_obj->target = nullptr;
> +      all_connection_objects.erase (target);
> +    }

Watch out with using operator[], that will insert an item for `target`
with value nullptr in the map, if there isn't one already.  Maybe it
doesn't matter in the end, but it brings the situation where a target
without a corresponding Python object can exist in two different states:
no entry in the map, and an entry with value nullptr.  I think it would
be easier to understand / less error prone if all entries in the map
had non-nullptr values, and targets without corresponding Python object
had no entries in the map.

> diff --git a/gdb/testsuite/gdb.python/py-connection.exp b/gdb/testsuite/gdb.python/py-connection.exp
> new file mode 100644
> index 00000000000..b994cec01eb
> --- /dev/null
> +++ b/gdb/testsuite/gdb.python/py-connection.exp
> @@ -0,0 +1,63 @@
> +# Copyright (C) 2021 Free Software Foundation, Inc.
> +
> +# This program is free software; you can redistribute it and/or modify
> +# it under the terms of the GNU General Public License as published by
> +# the Free Software Foundation; either version 3 of the License, or
> +# (at your option) any later version.
> +#
> +# This program is distributed in the hope that it will be useful,
> +# but WITHOUT ANY WARRANTY; without even the implied warranty of
> +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> +# GNU General Public License for more details.
> +#
> +# You should have received a copy of the GNU General Public License
> +# along with this program.  If not, see <http://www.gnu.org/licenses/>.
> +
> +# This file is for testing the gdb.TargetConnection API.  This API is
> +# already tested in gdb.multi/multi-target-info-inferiors.exp and
> +# gdb.python/py-inferior.exp, this file just covers some edge cases
> +# that are not tested in other places.
> +
> +load_lib gdb-python.exp
> +
> +standard_testfile
> +
> +if { [prepare_for_testing "failed to prepare" ${testfile} ${srcfile}] } {
> +    return -1
> +}
> +
> +# Skip all tests if Python scripting is not enabled.
> +if { [skip_python_tests] } { continue }
> +
> +if ![runto_main] then {
> +    fail "can't run to main"
> +    return 0
> +}

Since 4dfef5be6812 ("gdb/testsuite: make runto_main not pass no-message
to runto"), you don't have to make an explicit fail when
runto_main fails.

> +
> +# Create a gdb.TargetConnection object and check it becomes invalid
> +# once the connection has gone away.
> +gdb_test_no_output "python conn = gdb.selected_inferior().connection"
> +gdb_test "python print(conn)" \
> +    "<gdb.TargetConnection num=1, what=\"\[^\"\]+\">" \
> +    "print gdb.TargetConnection while it is still valid"
> +gdb_test "python print(conn.is_valid())" "True" "is_valid returns True"
> +gdb_test "info connections" "\r\n\\* 1 .*" \
> +    "info connections while the connection is still around"
> +gdb_test "kill" "" "kill the inferior" \
> +    "Kill the program being debugged.*y or n. $" "y"
> +gdb_test "info connections" "No connections\\." \
> +    "info connections now all the connections have gone"

The above will fail with the native-extended-gdbserver board, as the
connection will not be gone.  You could maybe use "disconnect", which
should pop the process target, whatever it is.

Simon

  parent reply	other threads:[~2021-10-21  2:00 UTC|newest]

Thread overview: 52+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-09-11 16:03 [PATCH 0/3] Python API for target connections, and packet sending Andrew Burgess
2021-09-11 16:03 ` [PATCH 1/3] gdb/python: introduce gdb.TargetConnection object type Andrew Burgess
2021-09-11 16:19   ` Eli Zaretskii
2021-09-11 16:03 ` [PATCH 2/3] gdb: make packet_command function available outside remote.c Andrew Burgess
2021-09-11 16:03 ` [PATCH 3/3] gdb/python: add TargetConnection.send_remote_packet method Andrew Burgess
2021-09-11 16:10   ` Eli Zaretskii
2021-10-18  9:45 ` [PATCHv2 0/3] Python API for target connections, and packet sending Andrew Burgess
2021-10-18  9:45   ` [PATCHv2 1/3] gdb/python: introduce gdb.TargetConnection object type Andrew Burgess
2021-10-18 12:44     ` Eli Zaretskii
2021-10-18 15:53     ` Simon Marchi
2021-10-18  9:45   ` [PATCHv2 2/3] gdb: make packet_command function available outside remote.c Andrew Burgess
2021-10-18  9:45   ` [PATCHv2 3/3] gdb/python: add TargetConnection.send_remote_packet method Andrew Burgess
2021-10-18 12:57     ` Eli Zaretskii
2021-10-18 15:46     ` Simon Marchi
2021-10-19 10:17   ` [PATCHv3 0/3] Python API for target connections, and packet sending Andrew Burgess
2021-10-19 10:17     ` [PATCHv3 1/3] gdb/python: introduce gdb.TargetConnection object type Andrew Burgess
2021-10-19 12:26       ` Eli Zaretskii
2021-10-20 22:33       ` Lancelot SIX
2021-10-21  2:00       ` Simon Marchi [this message]
2021-10-19 10:17     ` [PATCHv3 2/3] gdb: make packet_command function available outside remote.c Andrew Burgess
2021-10-21  2:23       ` Simon Marchi
2021-10-19 10:17     ` [PATCHv3 3/3] gdb/python: add gdb.RemoteTargetConnection.send_packet Andrew Burgess
2021-10-19 12:28       ` Eli Zaretskii
2021-10-21  2:43       ` Simon Marchi
2021-10-22 11:08         ` Andrew Burgess
2021-10-22 11:18           ` Simon Marchi
2021-10-22 17:11             ` Andrew Burgess
2021-10-22 10:58     ` [PATCHv4 0/4] Python API for target connections, and packet sending Andrew Burgess
2021-10-22 10:58       ` [PATCHv4 1/4] gdb/python: introduce gdb.TargetConnection object type Andrew Burgess
2021-10-22 10:58       ` [PATCHv4 2/4] gdb: make packet_command function available outside remote.c Andrew Burgess
2021-10-22 10:58       ` [PATCHv4 3/4] gdb/python: add gdb.RemoteTargetConnection.send_packet Andrew Burgess
2021-10-22 10:58       ` [PATCHv4 4/4] gdb: handle binary data in 'maint packet' and RemoteTargetConnection.send_packet Andrew Burgess
2021-10-22 17:10       ` [PATCHv5 0/4] Python API for target connections, and packet sending Andrew Burgess
2021-10-22 17:10         ` [PATCHv5 1/4] gdb/python: introduce gdb.TargetConnection object type Andrew Burgess
2021-10-22 17:10         ` [PATCHv5 2/4] gdb: make packet_command function available outside remote.c Andrew Burgess
2021-10-22 17:10         ` [PATCHv5 3/4] gdb/python: add gdb.RemoteTargetConnection.send_packet Andrew Burgess
2021-11-15  2:08           ` Simon Marchi
2021-11-15  9:25             ` Andrew Burgess
2021-11-15 13:16               ` Simon Marchi
2021-10-22 17:10         ` [PATCHv5 4/4] gdb: handle binary data in 'maint packet' and RemoteTargetConnection.send_packet Andrew Burgess
2021-11-15  2:44           ` Simon Marchi
2021-11-09 10:04         ` [PATCHv5 0/4] Python API for target connections, and packet sending Andrew Burgess
2021-11-15 17:40         ` [PATCHv6 0/3] " Andrew Burgess
2021-11-15 17:40           ` [PATCHv6 1/3] gdb/python: introduce gdb.TargetConnection object type Andrew Burgess
2021-11-15 17:40           ` [PATCHv6 2/3] gdb: make packet_command function available outside remote.c Andrew Burgess
2021-11-15 17:40           ` [PATCHv6 3/3] gdb/python: add gdb.RemoteTargetConnection.send_packet Andrew Burgess
2021-11-15 18:42             ` Eli Zaretskii
2021-11-15 19:38               ` Simon Marchi
2021-11-15 19:29             ` Simon Marchi
2021-11-16 12:48             ` Andrew Burgess
2021-11-16 15:10               ` Simon Marchi
2021-11-30 12:15                 ` 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:
  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=2e4bfc98-842e-2035-2cf3-26c8fddd15dd@polymtl.ca \
    --to=simon.marchi@polymtl.ca \
    --cc=andrew.burgess@embecosm.com \
    --cc=gdb-patches@sourceware.org \
    /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).