diff options
author | Tom Tromey <tromey@adacore.com> | 2023-03-21 08:35:09 -0600 |
---|---|---|
committer | Tom Tromey <tromey@adacore.com> | 2023-03-24 07:30:09 -0600 |
commit | 4460691252d5c345f0b34ac366639df23c687832 (patch) | |
tree | 356ee9d7adf9463aed72394489681d8740878c5b /gdb/python | |
parent | ef1398987a132769779679fd9ffd353dce840f95 (diff) | |
download | binutils-4460691252d5c345f0b34ac366639df23c687832.zip binutils-4460691252d5c345f0b34ac366639df23c687832.tar.gz binutils-4460691252d5c345f0b34ac366639df23c687832.tar.bz2 |
Fix race in DAP startup
Internal AdaCore DAP testing on Windows has had occasional failures
that show:
assert threading.current_thread() is _dap_thread
I think this is a race in DAP startup: the _dap_thread global is only
set on return from start_thread, but it seems possible that the thread
itself could already run and encounter a @in_dap_thread decorator.
This patch fixes the problem by setting the global before running any
of the code in the new thread. This also lets us remove a FIXME.
Diffstat (limited to 'gdb/python')
-rw-r--r-- | gdb/python/lib/gdb/dap/server.py | 4 | ||||
-rw-r--r-- | gdb/python/lib/gdb/dap/startup.py | 12 |
2 files changed, 10 insertions, 6 deletions
diff --git a/gdb/python/lib/gdb/dap/server.py b/gdb/python/lib/gdb/dap/server.py index 92b4eee..ff88282 100644 --- a/gdb/python/lib/gdb/dap/server.py +++ b/gdb/python/lib/gdb/dap/server.py @@ -100,9 +100,7 @@ class Server: log("WROTE: <<<" + json.dumps(obj) + ">>>") self.write_queue.put(obj) - # This must be run in the DAP thread, but we can't use - # @in_dap_thread here because the global isn't set until after - # this starts running. FIXME. + @in_dap_thread def main_loop(self): """The main loop of the DAP server.""" # Before looping, start the thread that writes JSON to the diff --git a/gdb/python/lib/gdb/dap/startup.py b/gdb/python/lib/gdb/dap/startup.py index 22246a9..aa834cd 100644 --- a/gdb/python/lib/gdb/dap/startup.py +++ b/gdb/python/lib/gdb/dap/startup.py @@ -59,14 +59,20 @@ def start_thread(name, target, args=()): with blocked_signals(): result = threading.Thread(target=target, args=args, daemon=True) result.start() - return result def start_dap(target): """Start the DAP thread and invoke TARGET there.""" - global _dap_thread exec_and_log("set breakpoint pending on") - _dap_thread = start_thread("DAP", target) + + # Functions in this thread contain assertions that check for this + # global, so we must set it before letting these functions run. + def really_start_dap(): + global _dap_thread + _dap_thread = threading.current_thread() + target() + + start_thread("DAP", really_start_dap) def in_gdb_thread(func): |