From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 2205) id 8F8EB3858D33; Thu, 22 Feb 2024 10:35:38 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 8F8EB3858D33 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sourceware.org; s=default; t=1708598139; bh=oyZUx3ouPaSd/roRHKLi4CBwdXD6lvElAfAGSdoIUNM=; h=From:To:Subject:Date:From; b=tGwZnFwNfKdXJ+Dc7TZC8/iiTFFdoTLOj3P6DM3GYlyPD/Ypts7P3dgQwCb7AQokH AXcqc2O7kYE1XLVIJryOgZsrnOAVL1SAIie3HQBvw8wAzHZfFkOC4UMk6AbYVRG28N DLIhmrMPE7ushX35UtSfufyteF3I2SmEphp/QiMA= Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable From: Tom de Vries To: gdb-cvs@sourceware.org Subject: [binutils-gdb] [gdb/dap] Fix race between dap startup and dap log file X-Act-Checkin: binutils-gdb X-Git-Author: Tom de Vries X-Git-Refname: refs/heads/master X-Git-Oldrev: 67cf0bd885e3862fb77de0039208d39cc89dba91 X-Git-Newrev: 05bf17f03b890424312163463754de63cee73074 Message-Id: <20240222103539.8F8EB3858D33@sourceware.org> Date: Thu, 22 Feb 2024 10:35:38 +0000 (GMT) List-Id: https://sourceware.org/git/gitweb.cgi?p=3Dbinutils-gdb.git;h=3D05bf17f03b89= 0424312163463754de63cee73074 commit 05bf17f03b890424312163463754de63cee73074 Author: Tom de Vries Date: Thu Feb 22 11:35:26 2024 +0100 [gdb/dap] Fix race between dap startup and dap log file =20 In dap_gdb_start we do: ... append GDBFLAGS " -iex \"set debug dap-log-file $logfile\" -q -= i=3Ddap" ... =20 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 initialize= d. =20 Consequently, there's a race between dap interpreter startup and dap lo= g file initialization. =20 This cannot be fixed by using -eiex instead. Before the interpreter is started, the "set debug dap-log-file" command is not yet registered. =20 Fix this by postponing the start of the DAP server until GDB has proces= sed all command files. =20 Tested on aarch64-linux. =20 Approved-By: Tom Tromey =20 PR dap/31386 Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=3D31386 Diff: --- gdb/python/lib/gdb/dap/__init__.py | 20 +++++++++++++++++++- gdb/python/py-dap.c | 23 ++++++++++++++++++++--- gdb/testsuite/gdb.dap/eof.exp | 3 +++ gdb/testsuite/lib/dap-support.exp | 10 ++++++++++ 4 files changed, 52 insertions(+), 4 deletions(-) diff --git a/gdb/python/lib/gdb/dap/__init__.py b/gdb/python/lib/gdb/dap/__= init__.py index f60b3fda1db..86da9b8ef3c 100644 --- a/gdb/python/lib/gdb/dap/__init__.py +++ b/gdb/python/lib/gdb/dap/__init__.py @@ -69,5 +69,23 @@ def run(): os.close(wfd) =20 # Note the inferior output is opened in text mode. + global server server =3D Server(open(saved_in, "rb"), open(saved_out, "wb"), open(rf= d, "r")) - startup.start_dap(server.main_loop) + + +# Whether the interactive session has started. +session_started =3D False + + +def pre_command_loop(): + """DAP's pre_command_loop interpreter hook. This is called by the GDB= DAP + interpreter.""" + global session_started + if not session_started: + # The pre_command_loop interpreter hook can be called several time= s. + # The first time it's called, it means we're starting an interacti= ve + # session. + session_started =3D True + startup.thread_log("starting DAP server") + global server + startup.start_dap(server.main_loop) diff --git a/gdb/python/py-dap.c b/gdb/python/py-dap.c index 5757c150165..2034105c939 100644 --- a/gdb/python/py-dap.c +++ b/gdb/python/py-dap.c @@ -61,13 +61,18 @@ public: return m_ui_out.get (); } =20 + void pre_command_loop () override; + private: =20 std::unique_ptr m_ui_out; }; =20 -void -dap_interp::init (bool top_level) + +/* Call function FN_NAME from module gdb.dap. */ + +static void +call_dap_fn (const char *fn_name) { gdbpy_enter enter_py; =20 @@ -75,18 +80,30 @@ dap_interp::init (bool top_level) if (dap_module =3D=3D nullptr) gdbpy_handle_exception (); =20 - gdbpy_ref<> func (PyObject_GetAttrString (dap_module.get (), "run")); + gdbpy_ref<> func (PyObject_GetAttrString (dap_module.get (), fn_name)); if (func =3D=3D nullptr) gdbpy_handle_exception (); =20 gdbpy_ref<> result_obj (PyObject_CallObject (func.get (), nullptr)); if (result_obj =3D=3D nullptr) gdbpy_handle_exception (); +} + +void +dap_interp::init (bool top_level) +{ + call_dap_fn ("run"); =20 current_ui->input_fd =3D -1; current_ui->m_input_interactive_p =3D false; } =20 +void +dap_interp::pre_command_loop () +{ + call_dap_fn ("pre_command_loop"); +} + void _initialize_py_interp (); void _initialize_py_interp () diff --git a/gdb/testsuite/gdb.dap/eof.exp b/gdb/testsuite/gdb.dap/eof.exp index 9c17725c0d0..a84b1d21e04 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 =20 dap_check_log_file + +# Check that first log message is present. +dap_check_log_file_re [string_to_regexp "starting DAP server"] diff --git a/gdb/testsuite/lib/dap-support.exp b/gdb/testsuite/lib/dap-supp= ort.exp index 38b00693790..72c22d00711 100644 --- a/gdb/testsuite/lib/dap-support.exp +++ b/gdb/testsuite/lib/dap-support.exp @@ -385,6 +385,16 @@ proc dap_check_log_file {} { } } =20 +# 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}} {