f.add_done_callback(self._loop_self_reading)
def _write_to_self(self):
- self._csock.send(b'x')
+ self._csock.send(b'\0')
def _start_serving(self, protocol_factory, sock, ssl=None, server=None):
if ssl:
self._internal_fds += 1
self.add_reader(self._ssock.fileno(), self._read_from_self)
+ def _process_self_data(self, data):
+ pass
+
def _read_from_self(self):
while True:
try:
data = self._ssock.recv(4096)
if not data:
break
+ self._process_self_data(data)
except InterruptedError:
continue
except BlockingIOError:
csock = self._csock
if csock is not None:
try:
- csock.send(b'x')
+ csock.send(b'\0')
except OSError:
pass
raise ImportError('Signals are not really supported on Windows')
+def _sighandler_noop(signum, frame):
+ """Dummy signal handler."""
+ pass
+
+
class _UnixSelectorEventLoop(selector_events.BaseSelectorEventLoop):
"""Unix event loop.
for sig in list(self._signal_handlers):
self.remove_signal_handler(sig)
+ def _process_self_data(self, data):
+ for signum in data:
+ if not signum:
+ # ignore null bytes written by _write_to_self()
+ continue
+ self._handle_signal(signum)
+
def add_signal_handler(self, sig, callback, *args):
"""Add a handler for a signal. UNIX only.
self._signal_handlers[sig] = handle
try:
- signal.signal(sig, self._handle_signal)
+ # Register a dummy signal handler to ask Python to write the signal
+ # number in the wakup file descriptor. _process_self_data() will
+ # read signal numbers from this file descriptor to handle signals.
+ signal.signal(sig, _sighandler_noop)
+
# Set SA_RESTART to limit EINTR occurrences.
signal.siginterrupt(sig, False)
except OSError as exc:
else:
raise
- def _handle_signal(self, sig, arg):
+ def _handle_signal(self, sig):
"""Internal helper that is the actual signal handler."""
handle = self._signal_handlers.get(sig)
if handle is None:
ValueError, self.loop._check_signal, signal.NSIG + 1)
def test_handle_signal_no_handler(self):
- self.loop._handle_signal(signal.NSIG + 1, ())
+ self.loop._handle_signal(signal.NSIG + 1)
def test_handle_signal_cancelled_handler(self):
h = asyncio.Handle(mock.Mock(), (),
h.cancel()
self.loop._signal_handlers[signal.NSIG + 1] = h
self.loop.remove_signal_handler = mock.Mock()
- self.loop._handle_signal(signal.NSIG + 1, ())
+ self.loop._handle_signal(signal.NSIG + 1)
self.loop.remove_signal_handler.assert_called_with(signal.NSIG + 1)
@mock.patch('asyncio.unix_events.signal')