From patchwork Fri Jan 5 11:48:35 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrew Burgess X-Patchwork-Id: 83395 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 6CE12385C413 for ; Fri, 5 Jan 2024 11:50:49 +0000 (GMT) X-Original-To: gdb-patches@sourceware.org Delivered-To: gdb-patches@sourceware.org Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by sourceware.org (Postfix) with ESMTPS id 82848385773F for ; Fri, 5 Jan 2024 11:48:59 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 82848385773F Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=redhat.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=redhat.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org 82848385773F Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=170.10.133.124 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1704455342; cv=none; b=X8BUACbElu8oiINb/WKbs9my9Z3o5QmRBkLtG+58AqjCQOHS3qmyyQ2RHqcpOPPDP80AkRtFs3UBgowVtY3dCLTtp668VxdQGq+IEb/pVzGZ0g+poau+4b/3eSwpzNHolQfbZOmWKrOrZbZp+OteXY3SQIfT95QrVK7R7L2DNsw= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1704455342; c=relaxed/simple; bh=I3NiweyDJ6ujHWyYvR5zFJsVtvEo9RsuhoI+KZ+cdfM=; h=DKIM-Signature:From:To:Subject:Date:Message-Id:MIME-Version; b=Uuh1OG0gdITg0jVcxhySDAEtIF8Hv2toUOpFPxEEFsHTzRlFb5rAiKndOHd4l3AxQ2BcMGuL0vIZ3OuOI8pYzHPnzlNbExpUXl7GFnN4t06/l2MnhrwH199M2ox5gz/AAmQ/NaOR+8uvmydXoKMg+kIS9Em8Zh8MsbCFkWgCBx4= ARC-Authentication-Results: i=1; server2.sourceware.org DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1704455339; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=w6nzeiYdwUWe8jFBRaSup9KdOjCmvB104h73GOz+nWA=; b=YTUy/igZNBLZyoP0bd4x4vZp9cyRey77Z/Rdqh/U2zSrA0fo6jdyH/vWQZHmBEeMbey4U8 2eSlaWw+JKbSBlnXLIhOSMe6yNRVKm7d6RsCvWERvR/faD7+z/9EaCsBQLM6kdAxfVO5k9 LYFIU9SSlxtHf6Ps5weRmkKEdNAFGdQ= Received: from mail-ej1-f71.google.com (mail-ej1-f71.google.com [209.85.218.71]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-490-99LsQJOrOlexOUANjhkDgA-1; Fri, 05 Jan 2024 06:48:52 -0500 X-MC-Unique: 99LsQJOrOlexOUANjhkDgA-1 Received: by mail-ej1-f71.google.com with SMTP id a640c23a62f3a-a28d6f071b2so57213566b.0 for ; Fri, 05 Jan 2024 03:48:52 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1704455331; x=1705060131; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=w6nzeiYdwUWe8jFBRaSup9KdOjCmvB104h73GOz+nWA=; b=i9bp487AGyu8JuwqlEORfgfg3Qp89mW1hmqxqwAhoHB0MNED5j/lhcojVslPobPa7z D9p5iUN6kxrwEsIZlRcUlKrd1qfBKqrRnef9NKK8gc4plONpT4siXf8HJCxyRag7SL/+ EsW6aabnrgTq07dWifNYlVsNMm+rLzZ7gznGBoC622MJFSappvwAAjfua2KuCvCApC+C 5R0PSeA+g0OiX/70pDbR4rKCESyJEsaFg98/kZoZSQF9aXLOp+Z8zUua9KvJzfY21l39 sU4TZMC7msExYd74SkypU45br6a+PsI3AiJEb9lsd5WvPWKYWbM5y8YswlAoJrb6wzlF RaaQ== X-Gm-Message-State: AOJu0YxQFokNXv15L+gSMRc18d5d1kpMhL2VFg3kBJtU/OQ5YVuBoGhn rcgQI3nSkfVjGH/PCxUl9wHg6KIwZvrfXxlAHLg8K2GVh5Z+qfKPLIjsbF0T6lfet5wtwfjMqxQ WA780xrHU9xp9MZpoJRBziL34h0owUWQS3Dgmktm3cUs8UIFQDlMDk2MfUdNsipBjXzcnj1LshD 7EawETKM6dUGHXrw== X-Received: by 2002:a17:906:185:b0:a28:fdc0:e704 with SMTP id 5-20020a170906018500b00a28fdc0e704mr755913ejb.53.1704455330889; Fri, 05 Jan 2024 03:48:50 -0800 (PST) X-Google-Smtp-Source: AGHT+IFtFB0jGwk/DnewKAw+B8E1572RF2wOg1OZnaEUZYJ9ldAoUIe62TDWSylci9caoTEIFjQxRQ== X-Received: by 2002:a17:906:185:b0:a28:fdc0:e704 with SMTP id 5-20020a170906018500b00a28fdc0e704mr755905ejb.53.1704455330458; Fri, 05 Jan 2024 03:48:50 -0800 (PST) Received: from localhost (185.223.159.143.dyn.plus.net. [143.159.223.185]) by smtp.gmail.com with ESMTPSA id v14-20020a1709060b4e00b00a27ac0895ecsm798273ejg.9.2024.01.05.03.48.49 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 05 Jan 2024 03:48:49 -0800 (PST) From: Andrew Burgess To: gdb-patches@sourceware.org Cc: Andrew Burgess Subject: [PATCH 6/6] gdb/python: Add gdb.InferiorThread.__dict__ attribute Date: Fri, 5 Jan 2024 11:48:35 +0000 Message-Id: <6fdf97c5f147a7e71fc0ca4de9e49961c067bae1.1704455158.git.aburgess@redhat.com> X-Mailer: git-send-email 2.25.4 In-Reply-To: References: MIME-Version: 1.0 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com X-Spam-Status: No, score=-13.5 required=5.0 tests=BAYES_00, DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H3, RCVD_IN_MSPIKE_WL, SPF_HELO_NONE, SPF_NONE, TXREP, T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: gdb-patches@sourceware.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Gdb-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: gdb-patches-bounces+patchwork=sourceware.org@sourceware.org The gdb.Objfile, gdb.Progspace, gdb.Type, and gdb.Inferior Python types already have a __dict__ attribute, which allows users to create user defined attributes within the objects. This is useful if the user wants to cache information within an object. This commit adds the same functionality to the gdb.InferiorThread type. After this commit there is a new gdb.InferiorThread.__dict__ attribute, which is a dictionary. A user can, for example, do this: (gdb) pi >>> t = gdb.selected_thread() >>> t._user_attribute = 123 >>> t._user_attribute 123 >>> There's a new test included. Reviewed-By: Eli Zaretskii --- gdb/NEWS | 4 +++ gdb/doc/python.texi | 31 ++++++++++++++++++++++++ gdb/python/py-infthread.c | 17 +++++++++++-- gdb/python/python-internal.h | 4 +++ gdb/testsuite/gdb.python/py-inferior.exp | 17 +++++++++++++ 5 files changed, 71 insertions(+), 2 deletions(-) diff --git a/gdb/NEWS b/gdb/NEWS index 500d5ab7160..c4862a8beb6 100644 --- a/gdb/NEWS +++ b/gdb/NEWS @@ -96,6 +96,10 @@ show remote thread-options-packet these will be stored in the object's new Inferior.__dict__ attribute. + ** User defined attributes can be added to a gdb.InferiorThread + object, these will be stored in the object's new + InferiorThread.__dict__ attribute. + * Debugger Adapter Protocol changes ** GDB now emits the "process" event. diff --git a/gdb/doc/python.texi b/gdb/doc/python.texi index 721f0100178..ecba7cfa89c 100644 --- a/gdb/doc/python.texi +++ b/gdb/doc/python.texi @@ -4173,6 +4173,37 @@ a @code{gdb.Type} for the handle type. @end defun +One may add arbitrary attributes to @code{gdb.InferiorThread} objects +in the usual Python way. This is useful if, for example, one needs to +do some extra record keeping associated with the thread. + +In this contrived example we record the time when a thread last +stopped: + +@smallexample +(gdb) python +import datetime + +def thread_stopped(event): + if event.inferior_thread is not None: + thread = event.inferior_thread + else: + thread = gdb.selected_thread() + thread._last_stop_time = datetime.datetime.today() + +gdb.events.stop.connect(thread_stopped) +(gdb) file /tmp/hello +Reading symbols from /tmp/hello... +(gdb) start +Temporary breakpoint 1 at 0x401198: file /tmp/hello.c, line 18. +Starting program: /tmp/hello + +Temporary breakpoint 1, main () at /tmp/hello.c:18 +18 printf ("Hello World\n"); +(gdb) python print(gdb.selected_thread()._last_stop_time) +2024-01-04 14:48:41.347036 +@end smallexample + @node Recordings In Python @subsubsection Recordings In Python @cindex recordings in python diff --git a/gdb/python/py-infthread.c b/gdb/python/py-infthread.c index 2d892b10b69..fa24ef3b9ca 100644 --- a/gdb/python/py-infthread.c +++ b/gdb/python/py-infthread.c @@ -49,6 +49,10 @@ create_thread_object (struct thread_info *tp) if (thread_obj == NULL) return NULL; + thread_obj->dict = PyDict_New (); + if (thread_obj->dict == nullptr) + return nullptr; + thread_obj->thread = tp; thread_obj->inf_obj = (PyObject *) inf_obj.release (); @@ -58,7 +62,14 @@ create_thread_object (struct thread_info *tp) static void thpy_dealloc (PyObject *self) { - Py_DECREF (((thread_object *) self)->inf_obj); + thread_object *thr_obj = (thread_object *) self; + + gdb_assert (thr_obj->inf_obj != nullptr); + gdb_assert (thr_obj->dict != nullptr); + + Py_DECREF (thr_obj->inf_obj); + Py_DECREF (thr_obj->dict); + Py_TYPE (self)->tp_free (self); } @@ -394,6 +405,8 @@ GDBPY_INITIALIZE_FILE (gdbpy_initialize_thread); static gdb_PyGetSetDef thread_object_getset[] = { + { "__dict__", gdb_py_generic_dict, nullptr, + "The __dict__ for this thread.", &thread_object_type }, { "name", thpy_get_name, thpy_set_name, "The name of the thread, as set by the user or the OS.", NULL }, { "details", thpy_get_details, NULL, @@ -471,7 +484,7 @@ PyTypeObject thread_object_type = 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ + offsetof (thread_object, dict), /* tp_dictoffset */ 0, /* tp_init */ 0 /* tp_alloc */ }; diff --git a/gdb/python/python-internal.h b/gdb/python/python-internal.h index 8ff9af650c2..e01557edeb7 100644 --- a/gdb/python/python-internal.h +++ b/gdb/python/python-internal.h @@ -356,6 +356,10 @@ struct thread_object /* The Inferior object to which this thread belongs. */ PyObject *inf_obj; + + /* Dictionary holding user-added attributes. This is the __dict__ + attribute of the object. */ + PyObject *dict; }; struct inferior_object; diff --git a/gdb/testsuite/gdb.python/py-inferior.exp b/gdb/testsuite/gdb.python/py-inferior.exp index 0e00636fa1c..d1cd29f734b 100644 --- a/gdb/testsuite/gdb.python/py-inferior.exp +++ b/gdb/testsuite/gdb.python/py-inferior.exp @@ -107,6 +107,19 @@ gdb_test "python print(last_thread)" \ "" \ "test repr of a valid thread" +# Add a user defined attribute to this thread, check the attribute can +# be read back, and check the attribute is not present on other +# threads. +gdb_test_no_output "python last_thread._user_attribute = 123" \ + "add user defined attribute to InferiorThread object" +gdb_test "python print(last_thread._user_attribute)" "123" \ + "read back user defined attribute" +gdb_test "python print(i0.threads ()\[0\]._user_attribute)" \ + [multi_line \ + "AttributeError: 'gdb\\.InferiorThread' object has no attribute '_user_attribute'" \ + "Error while executing Python code\\."] \ + "attempt to read non-existent user defined attribute" + # Proceed to the next test. gdb_breakpoint [gdb_get_line_number "Break here."] @@ -117,6 +130,10 @@ gdb_test "python print(last_thread)" \ "" \ "test repr of an invalid thread" +# Check the user defined attribute is still present on the invalid thread object. +gdb_test "python print(last_thread._user_attribute)" "123" \ + "check user defined attribute on an invalid InferiorThread object" + # Test memory read and write operations. gdb_py_test_silent_cmd "python addr = gdb.selected_frame ().read_var ('str')" \