From: "Tomáš Hrnčiar" <thrnciar@redhat.com>
To: gdb-patches@sourceware.org
Cc: tom@tromey.com, "Tomáš Hrnčiar" <thrnciar@redhat.com>,
"Eli Zaretskii" <eliz@gnu.org>
Subject: [PATCH v2] gdb/python: add allow_pending parameter to gdb.Breakpoint constructor
Date: Tue, 27 Oct 2026 09:09:21 +0100 [thread overview]
Message-ID: <20261027080921.2944156-1-thrnciar@redhat.com> (raw)
In-Reply-To: <877bjk46l1.fsf@tromey.com>
Add a new allow_pending parameter to the gdb.Breakpoint constructor.
Setting the new parameter to False causes GDB to raise an error instead
of creating a pending breakpoint. By default this parameter is True,
which allows pending breakpoints to be created, preserving the existing
behaviour.
Reviewed-By: Eli Zaretskii <eliz@gnu.org>
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=12816
---
gdb/NEWS | 6 ++
gdb/doc/python.texi | 17 +++--
gdb/python/py-breakpoint.c | 16 +++--
gdb/testsuite/gdb.python/py-breakpoint.exp | 82 ++++++++++++++++++++--
4 files changed, 109 insertions(+), 12 deletions(-)
diff --git a/gdb/NEWS b/gdb/NEWS
index 5d0c4745653..eb637a21724 100644
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -79,6 +79,12 @@ info locals
The new "-shadowed on|off" option overrides the "set print shadowed"
setting for a single invocation of the command.
+* Python API
+
+ ** The gdb.Breakpoint constructor now takes an optional
+ 'allow_pending' argument. Setting it to False causes GDB to raise
+ an error instead of creating a pending breakpoint.
+
*** Changes in GDB 18
* Support for the Common Trace Format (CTF) has been removed. GDB now
diff --git a/gdb/doc/python.texi b/gdb/doc/python.texi
index ddb347361f7..0b24698a77f 100644
--- a/gdb/doc/python.texi
+++ b/gdb/doc/python.texi
@@ -6953,7 +6953,7 @@ create both breakpoints and watchpoints. The second accepts separate Python
arguments similar to @ref{Explicit Locations}, and can only be used to create
breakpoints.
-@defun Breakpoint.__init__ (spec @r{[}, type @r{][}, wp_class @r{][}, internal @r{][}, temporary @r{][}, qualified @r{]})
+@defun Breakpoint.__init__ (spec @r{[}, type @r{][}, wp_class @r{][}, internal @r{][}, temporary @r{][}, qualified @r{][}, allow_pending @r{]})
Create a new breakpoint according to @var{spec}, which is a string naming the
location of a breakpoint, or an expression that defines a watchpoint. The
string should describe a location in a format recognized by the @code{break}
@@ -6983,16 +6983,25 @@ the function passed in @code{spec} as a fully-qualified name. It is equivalent
to @code{break}'s @code{-qualified} flag (@pxref{Linespec Locations} and
@ref{Explicit Locations}).
+The optional @var{allow_pending} argument is a boolean that controls whether
+the created breakpoint can be pending or not
+(@pxref{Set Breaks,,Pending Breakpoints}). The @var{allow_pending} argument is
+set to @code{True} by default and is only considered when @var{type} is
+@code{gdb.BP_BREAKPOINT} or @code{gdb.BP_HARDWARE_BREAKPOINT}. If
+the @var{allow_pending} argument is set to @code{False} and the breakpoint
+location cannot be resolved, a @code{gdb.error} exception is raised
+instead of creating a pending breakpoint.
+
@end defun
-@defun Breakpoint.__init__ (@r{[} source @r{][}, function @r{][}, label @r{][}, line @r{]}, @r{][} internal @r{][}, temporary @r{][}, qualified @r{]})
+@defun Breakpoint.__init__ (@r{[} source @r{][}, function @r{][}, label @r{][}, line @r{]}, @r{][} internal @r{][}, temporary @r{][}, qualified @r{][}, allow_pending @r{]})
This second form of creating a new breakpoint specifies the explicit
location (@pxref{Explicit Locations}) using keywords. The new breakpoint will
be created in the specified source file @var{source}, at the specified
@var{function}, @var{label} and @var{line}.
-@var{internal}, @var{temporary} and @var{qualified} have the same usage as
-explained previously.
+@var{internal}, @var{temporary}, @var{qualified} and @var{allow_pending} have
+the same usage as explained previously.
@end defun
The available types are represented by constants defined in the @code{gdb}
diff --git a/gdb/python/py-breakpoint.c b/gdb/python/py-breakpoint.c
index b1615db1be3..7261bd8e25b 100644
--- a/gdb/python/py-breakpoint.c
+++ b/gdb/python/py-breakpoint.c
@@ -914,7 +914,8 @@ bppy_init (PyObject *self, PyObject *args, PyObject *kwargs)
{
static const char *keywords[] = { "spec", "type", "wp_class", "internal",
"temporary","source", "function",
- "label", "line", "qualified", NULL };
+ "label", "line", "qualified",
+ "allow_pending", nullptr };
const char *spec = NULL;
enum bptype type = bp_breakpoint;
int access_type = hw_write;
@@ -928,13 +929,16 @@ bppy_init (PyObject *self, PyObject *args, PyObject *kwargs)
char *source = NULL;
char *function = NULL;
PyObject *qualified = Py_False;
+ PyObject *allow_pending = Py_True;
- if (!gdb_PyArg_ParseTupleAndKeywords (args, kwargs, "|siiOOsssOO!", keywords,
+ if (!gdb_PyArg_ParseTupleAndKeywords (args, kwargs, "|siiOOsssOO!O!",
+ keywords,
&spec, &type, &access_type,
&internal,
&temporary, &source,
&function, &label, &lineobj,
- &PyBool_Type, &qualified))
+ &PyBool_Type, &qualified,
+ &PyBool_Type, &allow_pending))
return -1;
@@ -1022,12 +1026,16 @@ bppy_init (PyObject *self, PyObject *args, PyObject *kwargs)
const struct breakpoint_ops *ops
= breakpoint_ops_for_location_spec (locspec.get (), false);
+ auto_boolean pending_enabled
+ = (allow_pending == Py_True
+ ? AUTO_BOOLEAN_TRUE
+ : AUTO_BOOLEAN_FALSE);
create_breakpoint (gdbpy_enter::get_gdbarch (),
locspec.get (), NULL, -1, -1, NULL, false,
0,
temporary_bp, type,
0,
- AUTO_BOOLEAN_TRUE,
+ pending_enabled,
ops,
0, 1, internal_bp, 0);
break;
diff --git a/gdb/testsuite/gdb.python/py-breakpoint.exp b/gdb/testsuite/gdb.python/py-breakpoint.exp
index 8b19a11b1f6..c78a321d055 100644
--- a/gdb/testsuite/gdb.python/py-breakpoint.exp
+++ b/gdb/testsuite/gdb.python/py-breakpoint.exp
@@ -628,10 +628,82 @@ proc_with_prefix test_bkpt_address {} {
}
proc_with_prefix test_bkpt_pending {} {
+ global srcfile testfile
+
+ clean_restart ${testfile}
+
delete_breakpoints
gdb_breakpoint "nosuchfunction" -allow-pending
gdb_test "python print (gdb.breakpoints()\[0\].pending)" "True" \
"Check pending status of pending breakpoint"
+
+ delete_breakpoints
+ with_test_prefix "allow_pending=True" {
+ gdb_test "python bp1 = gdb.Breakpoint (source=\"$srcfile\",\
+ line=\"900\", allow_pending=True)" \
+ [multi_line \
+ "^No compiled code for line 900 in file \[^\r\n\]+\\." \
+ "Breakpoint $::decimal \[^\r\n\]+ pending\\."] \
+ "set pending explicit breakpoint by source and missing line"
+ gdb_test_no_output "python assert(bp1.pending)" \
+ "verify pending explicit breakpoint created for missing line"
+ gdb_test "python bp1 = gdb.Breakpoint (function=\"blah\",\
+ allow_pending=True)" \
+ [multi_line \
+ "Function \"blah\" not defined.*" \
+ "Breakpoint $::decimal \[^\r\n\]+ pending\\."] \
+ "set pending explicit breakpoint by missing function"
+ gdb_test_no_output "python assert(bp1.pending)" \
+ "verify pending explicit breakpoint created for missing function"
+ gdb_test "python bp1 = gdb.Breakpoint (\"missing_function\",\
+ allow_pending=True)" \
+ [multi_line \
+ "Function \"missing_function\" not defined.*" \
+ "Breakpoint $::decimal \[^\r\n\]+ pending\\."] \
+ "set pending breakpoint by missing function"
+ gdb_test_no_output "python assert(bp1.pending)" \
+ "verify pending breakpoint created for missing function"
+ gdb_test_no_output "python assert(len(gdb.breakpoints()) == 3)" \
+ "verify expected number of pending breakpoints were created"
+ }
+
+ delete_breakpoints
+ with_test_prefix "allow_pending=False" {
+ gdb_test "python bp1 = gdb.Breakpoint (source=\"$srcfile\",\
+ line=\"900\", allow_pending=False)" \
+ [multi_line \
+ "Python Exception <class 'gdb.error'>: No compiled code for\
+ line 900 in file \[^\r\n\]+\\." \
+ "Error occurred in Python: No compiled code for line 900 in\
+ file \[^\r\n\]+\\."] \
+ "set invalid explicit breakpoint by source and missing line"
+ gdb_test "python bp1 = gdb.Breakpoint (function=\"blah\",\
+ allow_pending=False)" \
+ [multi_line \
+ "Python Exception <class 'gdb.error'>: Function \"blah\" not\
+ defined\\." \
+ "Error occurred in Python: Function \"blah\" not defined\\."] \
+ "set invalid explicit breakpoint by missing function"
+ gdb_test "python bp1 = gdb.Breakpoint (\"missing_function\",\
+ allow_pending=False)" \
+ [multi_line \
+ "Python Exception <class 'gdb.error'>: Function\
+ \"missing_function\" not defined\\." \
+ "Error occurred in Python: Function \"missing_function\" not\
+ defined\\."] \
+ "set invalid breakpoint by missing function"
+ gdb_test_no_output "python assert(len(gdb.breakpoints()) == 0)" \
+ "verify no pending breakpoints were created"
+ }
+
+ # Test allow_pending with a non-bool type.
+ delete_breakpoints
+ gdb_test "python gdb.Breakpoint (\"multiply\", allow_pending=None)" \
+ [multi_line \
+ "Python Exception <class 'TypeError'>: argument 11 must be bool,\
+ not None" \
+ "Error occurred in Python: argument 11 must be bool, not None"] \
+ "allow_pending non_bool_type"
}
# Helper proc to install an event listener for a given breakpoint
@@ -744,12 +816,14 @@ proc_with_prefix test_bkpt_explicit_loc {} {
"set invalid explicit breakpoint by missing source and line"
gdb_test "python bp1 = gdb.Breakpoint (source=\"$srcfile\", line=\"900\")" \
[multi_line \
- "^No compiled code for line 900 in file \"$srcfile\"\\." \
+ "^No compiled code for line 900 in file \[^\r\n\]+\\." \
"Breakpoint $::decimal \[^\r\n\]+ pending\\."] \
- "set invalid explicit breakpoint by source and invalid line"
+ "set pending explicit breakpoint by source and missing line"
gdb_test "python bp1 = gdb.Breakpoint (function=\"blah\")" \
- "Function \"blah\" not defined.*" \
- "set invalid explicit breakpoint by missing function"
+ [multi_line \
+ "Function \"blah\" not defined.*" \
+ "Breakpoint $::decimal \[^\r\n\]+ pending\\."] \
+ "set pending explicit breakpoint by missing function"
delete_breakpoints
gdb_test "catch throw" "Catchpoint .* \\(throw\\)"
--
2.56.0
next prev parent reply other threads:[~2026-10-27 8:10 UTC|newest]
Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-13 7:47 [PATCH] " Tomáš Hrnčiar
2026-10-13 12:55 ` Eli Zaretskii
2026-10-14 15:58 ` Tom Tromey
2026-10-22 13:54 ` Andrew Burgess
2026-10-22 17:50 ` Simon Marchi
2026-10-22 18:35 ` Tom Tromey
2026-10-27 8:09 ` Tomáš Hrnčiar [this message]
2026-10-27 14:06 ` [PATCH v2] " Tom Tromey
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=20261027080921.2944156-1-thrnciar@redhat.com \
--to=thrnciar@redhat.com \
--cc=eliz@gnu.org \
--cc=gdb-patches@sourceware.org \
--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