public inbox for gdb-patches@sourceware.org
 help / color / mirror / Atom feed
From: Tom de Vries <tdevries@suse.de>
To: gdb-patches@sourceware.org
Subject: [PATCH 5/8] [gdb/dap] Fix race between dap startup and dap log file
Date: Mon, 19 Feb 2024 09:23:38 +0100	[thread overview]
Message-ID: <20240219082341.21313-5-tdevries@suse.de> (raw)
In-Reply-To: <20240219082341.21313-1-tdevries@suse.de>

In dap_gdb_start we do:
...
        append GDBFLAGS " -iex \"set debug dap-log-file $logfile\" -q -i=dap"
...

While the dap log file setting comes before the dap interpreter setting,
the order is the other way around:
- first, the dap interpreter is started
- second, the -iex commands are executed and the log file is initialized.

Consequently, there's a race between dap interpreter startup and dap log file
initialization.

This cannot be fixed by using -eiex instead.  Before the interpreter is
started, the "set debug dap-log-file" command is not yet registered.

Fix this by:
- initially logging to a string instead, and
- dumping the string to the log file once the log file is initialized.

This has the drawback that the string can keep growing indefinitely if a log
file is never set, this will be addressed in a following commit.

Tested on aarch64-linux.

PR dap/31386
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=31386
---
 gdb/python/lib/gdb/dap/startup.py | 17 ++++++++++++++---
 gdb/testsuite/gdb.dap/eof.exp     |  3 +++
 gdb/testsuite/lib/dap-support.exp | 10 ++++++++++
 3 files changed, 27 insertions(+), 3 deletions(-)

diff --git a/gdb/python/lib/gdb/dap/startup.py b/gdb/python/lib/gdb/dap/startup.py
index fc86442db42..596012688ac 100644
--- a/gdb/python/lib/gdb/dap/startup.py
+++ b/gdb/python/lib/gdb/dap/startup.py
@@ -21,6 +21,7 @@ import queue
 import threading
 import traceback
 import sys
+import io
 
 from enum import IntEnum, auto
 
@@ -147,7 +148,7 @@ class LoggingParam(gdb.Parameter):
 
     lock = threading.Lock()
     with lock:
-        log_file = None
+        log_file = io.StringIO()
 
     def __init__(self):
         super().__init__(
@@ -157,12 +158,20 @@ class LoggingParam(gdb.Parameter):
 
     def get_set_string(self):
         with dap_log.lock:
+            initial_log = None
+            if isinstance(self.log_file, io.StringIO):
+                initial_log = self.log_file.getvalue()
+                self.log_file.close()
+                self.log_file = None
             # Close any existing log file, no matter what.
             if self.log_file is not None:
                 self.log_file.close()
                 self.log_file = None
             if self.value is not None:
                 self.log_file = open(self.value, "w")
+                if initial_log != None:
+                    print(initial_log, file=self.log_file)
+                    self.log_file.flush()
         return ""
 
 
@@ -174,7 +183,8 @@ def log(something, level=LogLevel.DEFAULT):
     with dap_log.lock:
         if dap_log.log_file is not None and level <= _log_level.value:
             print(something, file=dap_log.log_file)
-            dap_log.log_file.flush()
+            if not isinstance(dap_log.log_file, io.StringIO):
+                dap_log.log_file.flush()
 
 
 def thread_log(something, level=LogLevel.DEFAULT):
@@ -190,7 +200,8 @@ def log_stack(level=LogLevel.DEFAULT):
     with dap_log.lock:
         if dap_log.log_file is not None and level <= _log_level.value:
             traceback.print_exc(file=dap_log.log_file)
-            dap_log.log_file.flush()
+            if not isinstance(dap_log.log_file, io.StringIO):
+                dap_log.log_file.flush()
 
 
 @in_gdb_thread
diff --git a/gdb/testsuite/gdb.dap/eof.exp b/gdb/testsuite/gdb.dap/eof.exp
index 9c17725c0d0..404a069246f 100644
--- a/gdb/testsuite/gdb.dap/eof.exp
+++ b/gdb/testsuite/gdb.dap/eof.exp
@@ -35,3 +35,6 @@ catch "wait -i $gdb_spawn_id"
 unset gdb_spawn_id
 
 dap_check_log_file
+
+# Check that first log message is present.
+dap_check_log_file_re [string_to_regexp "+++ set python print-stack full"]
diff --git a/gdb/testsuite/lib/dap-support.exp b/gdb/testsuite/lib/dap-support.exp
index 31f036eddf2..5818d815df3 100644
--- a/gdb/testsuite/lib/dap-support.exp
+++ b/gdb/testsuite/lib/dap-support.exp
@@ -366,6 +366,16 @@ proc dap_check_log_file {} {
     }
 }
 
+# Read the most recent DAP log file and check that regexp RE matches.
+proc dap_check_log_file_re { re } {
+    set fd [open [current_dap_log_file]]
+    set contents [read $fd]
+    close $fd
+
+    set ok [regexp $re $contents]
+    gdb_assert {$ok} "log file matched $re"
+}
+
 # Cleanly shut down gdb.  TERMINATE is passed as the terminateDebuggee
 # parameter to the request.
 proc dap_shutdown {{terminate false}} {
-- 
2.35.3


  parent reply	other threads:[~2024-02-19  8:23 UTC|newest]

Thread overview: 22+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-02-19  8:23 [PATCH 1/8] [gdb/testsuite] Set up dap log file in gdb.dap/type_checker.exp Tom de Vries
2024-02-19  8:23 ` [PATCH 2/8] [gdb/dap] Factor out thread_log Tom de Vries
2024-02-20 15:30   ` Tom Tromey
2024-02-21 13:30     ` Tom de Vries
2024-02-19  8:23 ` [PATCH 3/8] [gdb/dap] Flush after printing in log_stack Tom de Vries
2024-02-20 15:30   ` Tom Tromey
2024-02-19  8:23 ` [PATCH 4/8] [gdb/dap] Make dap log printing thread-safe Tom de Vries
2024-02-20 15:32   ` Tom Tromey
2024-02-21 13:31     ` Tom de Vries
2024-02-19  8:23 ` Tom de Vries [this message]
2024-02-20 15:38   ` [PATCH 5/8] [gdb/dap] Fix race between dap startup and dap log file Tom Tromey
2024-02-19  8:23 ` [PATCH 6/8] [gdb/dap] Don't let dap log string grow indefinitely Tom de Vries
2024-02-20 15:41   ` Tom Tromey
2024-02-21 13:34     ` Tom de Vries
2024-02-19  8:23 ` [PATCH 7/8] [gdb/dap] Join JSON reader and writer threads with DAP thread Tom de Vries
2024-02-20 15:47   ` Tom Tromey
2024-02-20 20:01   ` Tom Tromey
2024-02-21 13:35     ` Tom de Vries
2024-02-19  8:23 ` [PATCH 8/8] [gdb/dap] Fix race between dap exit and gdb exit Tom de Vries
2024-02-20 15:51   ` Tom Tromey
2024-02-21 13:39     ` Tom de Vries
2024-02-20 15:29 ` [PATCH 1/8] [gdb/testsuite] Set up dap log file in gdb.dap/type_checker.exp 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=20240219082341.21313-5-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;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).