aboutsummaryrefslogtreecommitdiff
path: root/gdb/python
diff options
context:
space:
mode:
authorTom Tromey <tom@tromey.com>2023-07-04 09:15:54 -0600
committerTom Tromey <tom@tromey.com>2023-07-23 14:33:44 -0600
commit560c121c207af3c31c83a815de2569535fcd3aa7 (patch)
tree950e734a9586020f9b2d3f70293eda7957330bb0 /gdb/python
parent8a9da63e407c511df32841abcbe20effe2f3e398 (diff)
downloadgdb-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__.py32
-rw-r--r--gdb/python/lib/gdb/dap/startup.py26
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):