From: Tom de Vries <tdevries@suse.de>
To: gdb-patches@sourceware.org
Subject: [PATCH 3/3] [gdb] Fix backtrace in log file (execinfo case)
Date: Fri, 23 Oct 2026 09:38:13 +0200 [thread overview]
Message-ID: <20261023073813.2224939-4-tdevries@suse.de> (raw)
In-Reply-To: <20261023073813.2224939-1-tdevries@suse.de>
Consider test-case gdb.base/logging-internal-error.exp.
It enables logging to a file log.txt, and then does "maint internal-error".
Now say we build gdb with --disable-libbacktrace, and run the test-case.
In gdb.log we find the expected output:
...
(gdb) maint internal-error
gdb/maint.c:82: internal-error:
A problem internal to GDB has been detected,
further debugging may prove unreliable.
----- Backtrace -----
gdb/gdb() [0x659b60]
...
gdb/gdb() [0xbb2f72]
Backtrace might be incomplete.
---------------------
This is a bug, please report it. For instructions, see:
<https://www.gnu.org/software/gdb/bugs/>.
Command aborted.
(gdb)
...
But in log.txt, we have:
...
gdb/maint.c:82: internal-error:
A problem internal to GDB has been detected,
further debugging may prove unreliable.
----- Backtrace -----
Backtrace might be incomplete.
---------------------
This is a bug, please report it. For instructions, see:
<https://www.gnu.org/software/gdb/bugs/>.
Command aborted.
...
Make the test-case detect this by making a regexp a bit stricter.
The problem is in gdb_internal_backtrace_1, where we do:
...
int fd = ((gdb_stderr == nullptr || gdb_stderr->fd () == -1)
? 2
: gdb_stderr->fd ());
backtrace_symbols_fd (buffer, frames, fd);
...
We want to write to two files, but there's just one file descriptor.
Fix this by adding a new member function ui_file::for_each_fd, and using it in
gdb_internal_backtrace_1 to call backtrace_symbols_fd.
---
gdb/bt-utils.c | 12 ++++++++----
gdb/cli/cli-logging.c | 14 ++++++++++++++
gdb/logging-file.h | 1 +
.../gdb.base/logging-internal-error.exp | 2 +-
gdb/ui-file.h | 16 ++++++++++++++++
5 files changed, 40 insertions(+), 5 deletions(-)
diff --git a/gdb/bt-utils.c b/gdb/bt-utils.c
index fcb912c8021..b0000e92da2 100644
--- a/gdb/bt-utils.c
+++ b/gdb/bt-utils.c
@@ -134,10 +134,14 @@ gdb_internal_backtrace_1 ()
void *buffer[25];
int frames = backtrace (buffer, ARRAY_SIZE (buffer));
- int fd = ((gdb_stderr == nullptr || gdb_stderr->fd () == -1)
- ? 2
- : gdb_stderr->fd ());
- backtrace_symbols_fd (buffer, frames, fd);
+ bool handled = (gdb_stderr != nullptr
+ && gdb_stderr->for_each_fd ([&] (int fd)
+ {
+ backtrace_symbols_fd (buffer, frames, fd);
+ }));
+ if (!handled)
+ backtrace_symbols_fd (buffer, frames, 2);
+
if (frames == ARRAY_SIZE (buffer))
sig_write (_("Backtrace might be incomplete.\n"));
}
diff --git a/gdb/cli/cli-logging.c b/gdb/cli/cli-logging.c
index d8212de4abb..53fc66dda56 100644
--- a/gdb/cli/cli-logging.c
+++ b/gdb/cli/cli-logging.c
@@ -187,6 +187,20 @@ logging_file<T>::write_async_safe (const char *buf, long length_buf)
/* See logging-file.h. */
+template<typename T>
+bool
+logging_file<T>::for_each_fd (gdb::function_view<void (int)> f)
+{
+ bool handled = false;
+ if (log_file != nullptr)
+ handled = log_file->for_each_fd (f);
+ if (ordinary_output ())
+ handled = m_out->for_each_fd (f);
+ return handled;
+}
+
+/* See logging-file.h. */
+
template<typename T>
void
logging_file<T>::puts (const char *linebuffer)
diff --git a/gdb/logging-file.h b/gdb/logging-file.h
index f8b9f101150..7a4c265ed08 100644
--- a/gdb/logging-file.h
+++ b/gdb/logging-file.h
@@ -47,6 +47,7 @@ class logging_file : public ui_file
bool can_page () const override;
void emit_style_escape (const ui_file_style &style) override;
void puts_unfiltered (const char *str) override;
+ bool for_each_fd (gdb::function_view<void (int)> f) override;
bool isatty () override
{
diff --git a/gdb/testsuite/gdb.base/logging-internal-error.exp b/gdb/testsuite/gdb.base/logging-internal-error.exp
index b121ca42612..9a46ed7c3e2 100644
--- a/gdb/testsuite/gdb.base/logging-internal-error.exp
+++ b/gdb/testsuite/gdb.base/logging-internal-error.exp
@@ -69,7 +69,7 @@ close $fd
set test "Logged backtrace"
if {$seen_bt} {
- gdb_assert {[regexp $re_bt $data]} $test
+ gdb_assert {[regexp $re_bt.*$hex $data]} $test
} else {
unsupported $test
}
diff --git a/gdb/ui-file.h b/gdb/ui-file.h
index 23cbd2c7e78..6ef9722ead8 100644
--- a/gdb/ui-file.h
+++ b/gdb/ui-file.h
@@ -22,6 +22,7 @@
#include <string>
#include <tuple>
#include "ui-style.h"
+#include "gdbsupport/function-view.h"
/* The abstract ui_file base class. */
@@ -117,6 +118,18 @@ class ui_file
virtual int fd () const
{ return -1; }
+ /* Use this function to write to a file descriptor, rather than using
+ write (fd (), ...). In some cases, multiple descriptors need to be
+ written. Return true if the write was handled. */
+ virtual bool for_each_fd (gdb::function_view<void (int)> f)
+ {
+ int fd = this->fd ();
+ if (fd == -1)
+ return false;
+ f (fd);
+ return true;
+ }
+
/* Return true if this object supports paging, false otherwise. */
virtual bool can_page () const
{
@@ -436,6 +449,9 @@ class wrapped_file : public ui_file
int fd () const override
{ return m_stream->fd (); }
+ bool for_each_fd (gdb::function_view<void (int)> f) override
+ { return m_stream->for_each_fd (f); }
+
void puts_unfiltered (const char *str) override
{ m_stream->puts_unfiltered (str); }
--
2.51.0
prev parent reply other threads:[~2026-10-23 7:38 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-23 7:38 [PATCH 0/3] [gdb] Fix backtrace in log file Tom de Vries
2026-10-23 7:38 ` [PATCH 1/3] [gdb] Fix backtrace in log file (libbacktrace case) Tom de Vries
2026-10-23 7:38 ` [PATCH 2/3] [gdb] Don't flush in handle_fatal_signal Tom de Vries
2026-10-23 7:38 ` Tom de Vries [this message]
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=20261023073813.2224939-4-tdevries@suse.de \
--to=tdevries@suse.de \
--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