diff options
author | Tom Tromey <tom@tromey.com> | 2023-07-04 09:15:54 -0600 |
---|---|---|
committer | Tom Tromey <tom@tromey.com> | 2023-07-23 14:33:44 -0600 |
commit | 560c121c207af3c31c83a815de2569535fcd3aa7 (patch) | |
tree | 950e734a9586020f9b2d3f70293eda7957330bb0 /gdb/python | |
parent | 8a9da63e407c511df32841abcbe20effe2f3e398 (diff) | |
download | gdb-560c121c207af3c31c83a815de2569535fcd3aa7.zip gdb-560c121c207af3c31c83a815de2569535fcd3aa7.tar.gz gdb-560c121c207af3c31c83a815de2569535fcd3aa7.tar.bz2 |
Export gdb.block_signals and create gdb.Thread
While working on an experiment, I realized that I needed the DAP
block_signals function. I figured other developers may need it as
well, so this patch moves it from DAP to the gdb module and exports
it.
I also added a new subclass of threading.Thread that ensures that
signals are blocked in the new thread.
Finally, this patch slightly rearranges the documentation so that
gdb-side threading issues and functions are all discussed in a single
node.
Diffstat (limited to 'gdb/python')
-rw-r--r-- | gdb/python/lib/gdb/__init__.py | 32 | ||||
-rw-r--r-- | gdb/python/lib/gdb/dap/startup.py | 26 |
2 files changed, 34 insertions, 24 deletions
diff --git a/gdb/python/lib/gdb/__init__.py b/gdb/python/lib/gdb/__init__.py index 6f3f194..98aadb1 100644 --- a/gdb/python/lib/gdb/__init__.py +++ b/gdb/python/lib/gdb/__init__.py @@ -13,6 +13,8 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. +import signal +import threading import traceback import os import sys @@ -259,3 +261,33 @@ def with_parameter(name, value): yield None finally: set_parameter(name, old_value) + + +@contextmanager +def blocked_signals(): + """A helper function that blocks and unblocks signals.""" + if not hasattr(signal, "pthread_sigmask"): + yield + return + + to_block = {signal.SIGCHLD, signal.SIGINT, signal.SIGALRM, signal.SIGWINCH} + signal.pthread_sigmask(signal.SIG_BLOCK, to_block) + try: + yield None + finally: + signal.pthread_sigmask(signal.SIG_UNBLOCK, to_block) + + +class Thread(threading.Thread): + """A GDB-specific wrapper around threading.Thread + + This wrapper ensures that the new thread blocks any signals that + must be delivered on GDB's main thread.""" + + def start(self): + # GDB requires that these be delivered to the main thread. We + # do this here to avoid any possible race with the creation of + # the new thread. The thread mask is inherited by new + # threads. + with blocked_signals(): + super().start() diff --git a/gdb/python/lib/gdb/dap/startup.py b/gdb/python/lib/gdb/dap/startup.py index aa834cd..15d1fb9 100644 --- a/gdb/python/lib/gdb/dap/startup.py +++ b/gdb/python/lib/gdb/dap/startup.py @@ -18,10 +18,8 @@ import functools import gdb import queue -import signal import threading import traceback -from contextlib import contextmanager import sys @@ -33,32 +31,12 @@ _gdb_thread = threading.current_thread() _dap_thread = None -@contextmanager -def blocked_signals(): - """A helper function that blocks and unblocks signals.""" - if not hasattr(signal, "pthread_sigmask"): - yield - return - - to_block = {signal.SIGCHLD, signal.SIGINT, signal.SIGALRM, signal.SIGWINCH} - signal.pthread_sigmask(signal.SIG_BLOCK, to_block) - try: - yield None - finally: - signal.pthread_sigmask(signal.SIG_UNBLOCK, to_block) - - def start_thread(name, target, args=()): """Start a new thread, invoking TARGET with *ARGS there. This is a helper function that ensures that any GDB signals are correctly blocked.""" - # GDB requires that these be delivered to the gdb thread. We - # do this here to avoid any possible race with the creation of - # the new thread. The thread mask is inherited by new - # threads. - with blocked_signals(): - result = threading.Thread(target=target, args=args, daemon=True) - result.start() + result = gdb.Thread(target=target, args=args, daemon=True) + result.start() def start_dap(target): |