/usr/lib/python3/dist-packages/gevent/signal.py is in python3-gevent 1.2.2-2.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 | """
Cooperative implementation of special cases of :func:`signal.signal`.
This module is designed to work with libev's child watchers, as used
by default in :func:`gevent.os.fork` Note that each ``SIGCHLD`` handler
will be run in a new greenlet when the signal is delivered (just like
:class:`gevent.hub.signal`)
The implementations in this module are only monkey patched if
:func:`gevent.os.waitpid` is being used (the default) and if
:const:`signal.SIGCHLD` is available; see :func:`gevent.os.fork` for
information on configuring this not to be the case for advanced uses.
.. versionadded:: 1.1b4
"""
from __future__ import absolute_import
from gevent._util import _NONE as _INITIAL
from gevent._util import copy_globals
import signal as _signal
__implements__ = []
__extensions__ = []
_child_handler = _INITIAL
_signal_signal = _signal.signal
_signal_getsignal = _signal.getsignal
def getsignal(signalnum):
"""
Exactly the same as :func:`signal.signal` except where
:const:`signal.SIGCHLD` is concerned.
For :const:`signal.SIGCHLD`, this cooperates with :func:`signal`
to provide consistent answers.
"""
if signalnum != _signal.SIGCHLD:
return _signal_getsignal(signalnum)
global _child_handler
if _child_handler is _INITIAL:
_child_handler = _signal_getsignal(_signal.SIGCHLD)
return _child_handler
def signal(signalnum, handler):
"""
Exactly the same as :func:`signal.signal` except where
:const:`signal.SIGCHLD` is concerned.
.. note::
A :const:`signal.SIGCHLD` handler installed with this function
will only be triggered for children that are forked using
:func:`gevent.os.fork` (:func:`gevent.os.fork_and_watch`);
children forked before monkey patching, or otherwise by the raw
:func:`os.fork`, will not trigger the handler installed by this
function. (It's unlikely that a SIGCHLD handler installed with
the builtin :func:`signal.signal` would be triggered either;
libev typically overwrites such a handler at the C level. At
the very least, it's full of race conditions.)
.. note::
Use of ``SIG_IGN`` and ``SIG_DFL`` may also have race conditions
with libev child watchers and the :mod:`gevent.subprocess` module.
.. versionchanged:: 1.2a1
If ``SIG_IGN`` or ``SIG_DFL`` are used to ignore ``SIGCHLD``, a
future use of ``gevent.subprocess`` and libev child watchers
will once again work. However, on Python 2, use of ``os.popen``
will fail.
.. versionchanged:: 1.1rc2
Allow using ``SIG_IGN`` and ``SIG_DFL`` to reset and ignore ``SIGCHLD``.
However, this allows the possibility of a race condition if ``gevent.subprocess``
had already been used.
"""
if signalnum != _signal.SIGCHLD:
return _signal_signal(signalnum, handler)
# TODO: raise value error if not called from the main
# greenlet, just like threads
if handler != _signal.SIG_IGN and handler != _signal.SIG_DFL and not callable(handler):
# exact same error message raised by the stdlib
raise TypeError("signal handler must be signal.SIG_IGN, signal.SIG_DFL, or a callable object")
old_handler = getsignal(signalnum)
global _child_handler
_child_handler = handler
if handler == _signal.SIG_IGN or handler == _signal.SIG_DFL:
# Allow resetting/ignoring this signal at the process level.
# Note that this conflicts with gevent.subprocess and other users
# of child watchers, until the next time gevent.subprocess/loop.install_sigchld()
# is called.
from gevent import get_hub # Are we always safe to import here?
_signal_signal(signalnum, handler)
get_hub().loop.reset_sigchld()
return old_handler
def _on_child_hook():
# This is called in the hub greenlet. To let the function
# do more useful work, like use blocking functions,
# we run it in a new greenlet; see gevent.hub.signal
if callable(_child_handler):
# None is a valid value for the frame argument
from gevent import Greenlet
greenlet = Greenlet(_child_handler, _signal.SIGCHLD, None)
greenlet.switch()
import gevent.os
if 'waitpid' in gevent.os.__implements__ and hasattr(_signal, 'SIGCHLD'):
# Tightly coupled here to gevent.os and its waitpid implementation; only use these
# if necessary.
gevent.os._on_child_hook = _on_child_hook
__implements__.append("signal")
__implements__.append("getsignal")
else:
# XXX: This breaks test__all__ on windows
__extensions__.append("signal")
__extensions__.append("getsignal")
__imports__ = copy_globals(_signal, globals(),
names_to_ignore=__implements__ + __extensions__,
dunder_names_to_keep=())
__all__ = __implements__ + __extensions__
|