diff options
author | Antoine Pitrou <solipsis@pitrou.net> | 2012-03-31 19:09:00 (GMT) |
---|---|---|
committer | Antoine Pitrou <solipsis@pitrou.net> | 2012-03-31 19:09:00 (GMT) |
commit | 682d443e011a213ba577c6eed3a9c67508cc039e (patch) | |
tree | 6e0053ebe5ea21a3c20d034034a3bfc86e571d6d /Doc/library | |
parent | 8b34b53c52ce604bc48b39f83089cd404201de1b (diff) | |
parent | 6afd11c762ad9f135ce7aaf1f9fa1e3856984bf1 (diff) | |
download | cpython-682d443e011a213ba577c6eed3a9c67508cc039e.zip cpython-682d443e011a213ba577c6eed3a9c67508cc039e.tar.gz cpython-682d443e011a213ba577c6eed3a9c67508cc039e.tar.bz2 |
Issue #14456: improve documentation of the signal module w.r.t. threads.
Diffstat (limited to 'Doc/library')
-rw-r--r-- | Doc/library/signal.rst | 107 |
1 files changed, 65 insertions, 42 deletions
diff --git a/Doc/library/signal.rst b/Doc/library/signal.rst index 04afd9e..f3ac55b 100644 --- a/Doc/library/signal.rst +++ b/Doc/library/signal.rst @@ -5,43 +5,61 @@ :synopsis: Set handlers for asynchronous events. -This module provides mechanisms to use signal handlers in Python. Some general -rules for working with signals and their handlers: - -* A handler for a particular signal, once set, remains installed until it is - explicitly reset (Python emulates the BSD style interface regardless of the - underlying implementation), with the exception of the handler for - :const:`SIGCHLD`, which follows the underlying implementation. - -* Although Python signal handlers are called asynchronously as far as the Python - user is concerned, they can only occur between the "atomic" instructions of the - Python interpreter. This means that signals arriving during long calculations - implemented purely in C (such as regular expression matches on large bodies of - text) may be delayed for an arbitrary amount of time. - -* When a signal arrives during an I/O operation, it is possible that the I/O - operation raises an exception after the signal handler returns. This is - dependent on the underlying Unix system's semantics regarding interrupted system - calls. - -* Because the C signal handler always returns, it makes little sense to catch - synchronous errors like :const:`SIGFPE` or :const:`SIGSEGV`. - -* Python installs a small number of signal handlers by default: :const:`SIGPIPE` - is ignored (so write errors on pipes and sockets can be reported as ordinary - Python exceptions) and :const:`SIGINT` is translated into a - :exc:`KeyboardInterrupt` exception. All of these can be overridden. - -* Some care must be taken if both signals and threads are used in the same - program. The fundamental thing to remember in using signals and threads - simultaneously is: always perform :func:`signal` operations in the main thread - of execution. Any thread can perform an :func:`alarm`, :func:`getsignal`, - :func:`pause`, :func:`setitimer` or :func:`getitimer`; only the main thread - can set a new signal handler, and the main thread will be the only one to - receive signals (this is enforced by the Python :mod:`signal` module, even - if the underlying thread implementation supports sending signals to - individual threads). This means that signals can't be used as a means of - inter-thread communication. Use locks instead. +This module provides mechanisms to use signal handlers in Python. + + +General rules +------------- + +The :func:`signal.signal` function allows to define custom handlers to be +executed when a signal is received. A small number of default handlers are +installed: :const:`SIGPIPE` is ignored (so write errors on pipes and sockets +can be reported as ordinary Python exceptions) and :const:`SIGINT` is +translated into a :exc:`KeyboardInterrupt` exception. + +A handler for a particular signal, once set, remains installed until it is +explicitly reset (Python emulates the BSD style interface regardless of the +underlying implementation), with the exception of the handler for +:const:`SIGCHLD`, which follows the underlying implementation. + +There is no way to "block" signals temporarily from critical sections (since +this is not supported by all Unix flavors). + + +Execution of Python signal handlers +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +A Python signal handler does not get executed inside the low-level (C) signal +handler. Instead, the low-level signal handler sets a flag which tells the +:term:`virtual machine` to execute the corresponding Python signal handler +at a later point(for example at the next :term:`bytecode` instruction). +This has consequences: + +* It makes little sense to catch synchronous errors like :const:`SIGFPE` or + :const:`SIGSEGV`. + +* A long-running calculation implemented purely in C (such as regular + expression matching on a large body of text) may run uninterrupted for an + arbitrary amount of time, regardless of any signals received. The Python + signal handlers will be called when the calculation finishes. + + +.. _signals-and-threads: + + +Signals and threads +^^^^^^^^^^^^^^^^^^^ + +Python signal handlers are always executed in the main Python thread, +even if the signal was received in another thread. This means that signals +can't be used as a means of inter-thread communication. You can use +the synchronization primitives from the :mod:`threading` module instead. + +Besides, only the main thread is allowed to set a new signal handler. + + +Module contents +--------------- The variables defined in the :mod:`signal` module are: @@ -189,15 +207,20 @@ The :mod:`signal` module defines the following functions: .. function:: pthread_kill(thread_id, signum) - Send the signal *signum* to the thread *thread_id*, another thread in the same - process as the caller. The signal is asynchronously directed to thread. + Send the signal *signum* to the thread *thread_id*, another thread in the + same process as the caller. The target thread can be executing any code + (Python or not). However, if the target thread is executing the Python + interpreter, the Python signal handlers will be :ref:`executed by the main + thread <signals-and-threads>`. Therefore, the only point of sending a signal to a particular + Python thread would be to force a running system call to fail with + :exc:`InterruptedError`. Use :func:`threading.get_ident()` or the :attr:`~threading.Thread.ident` - attribute of :attr:`threading.Thread` to get a 'thread identifier' for - *thread_id*. + attribute of :class:`threading.Thread` objects to get a suitable value + for *thread_id*. If *signum* is 0, then no signal is sent, but error checking is still - performed; this can be used to check if a thread is still running. + performed; this can be used to check if the target thread is still running. Availability: Unix (see the man page :manpage:`pthread_kill(3)` for further information). |