Skip to content

bpo-35749: Don't log exception if event loop wakeup pipe is full #11577

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 4 additions & 5 deletions Lib/asyncio/proactor_events.py
Original file line number Diff line number Diff line change
Expand Up @@ -490,7 +490,7 @@ def __init__(self, proactor):
proactor.set_loop(self)
self._make_self_pipe()
self_no = self._csock.fileno()
signal.set_wakeup_fd(self_no)
signal.set_wakeup_fd(self_no, warn_on_full_buffer=False)

def _make_socket_transport(self, sock, protocol, waiter=None,
extra=None, server=None):
Expand Down Expand Up @@ -639,10 +639,9 @@ def _write_to_self(self):
try:
self._csock.send(b'\0')
except OSError:
if self._debug:
logger.debug("Fail to write a null byte into the "
"self-pipe socket",
exc_info=True)
# Ignore the error,
# See https://bugs.python.org/issue35749
pass

def _start_serving(self, protocol_factory, sock,
sslcontext=None, server=None, backlog=100,
Expand Down
15 changes: 9 additions & 6 deletions Lib/asyncio/selector_events.py
Original file line number Diff line number Diff line change
Expand Up @@ -105,20 +105,24 @@ def _make_self_pipe(self):
self._internal_fds += 1
self._add_reader(self._ssock.fileno(), self._read_from_self)

def _process_self_data(self, data):
def _process_self_data(self):
pass

def _read_from_self(self):
wakeup = False
while True:
try:
data = self._ssock.recv(4096)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can use sock.recv_into() here. Not sure if it worth to change

if not data:
break
self._process_self_data(data)
else:
wakeup = True
except InterruptedError:
continue
except BlockingIOError:
break
if wakeup:
self._process_self_data()

def _write_to_self(self):
# This may be called from a different thread, possibly after
Expand All @@ -131,10 +135,9 @@ def _write_to_self(self):
try:
csock.send(b'\0')
except OSError:
if self._debug:
logger.debug("Fail to write a null byte into the "
"self-pipe socket",
exc_info=True)
# Ignore the error,
# See https://bugs.python.org/issue35749
pass

def _start_serving(self, protocol_factory, sock,
sslcontext=None, server=None, backlog=100,
Expand Down
29 changes: 14 additions & 15 deletions Lib/asyncio/unix_events.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,6 @@
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.

Expand All @@ -51,6 +46,7 @@ class _UnixSelectorEventLoop(selector_events.BaseSelectorEventLoop):
def __init__(self, selector=None):
super().__init__(selector)
self._signal_handlers = {}
self._occurred_signals = set()

def close(self):
super().close()
Expand All @@ -66,11 +62,13 @@ def close(self):
source=self)
self._signal_handlers.clear()

def _process_self_data(self, data):
for signum in data:
if not signum:
# ignore null bytes written by _write_to_self()
continue
def _sig_handler(self, signum, frame):
self._occurred_signals.add(signum)

def _process_self_data(self):
signals = self._occurred_signals
self._occurred_signals = set()
for signum in signals:
self._handle_signal(signum)

def add_signal_handler(self, sig, callback, *args):
Expand All @@ -90,18 +88,19 @@ def add_signal_handler(self, sig, callback, *args):
# main thread. By calling it early we ensure that an
# event loop running in another thread cannot add a signal
# handler.
signal.set_wakeup_fd(self._csock.fileno())
signal.set_wakeup_fd(self._csock.fileno(),
warn_on_full_buffer=False)
except (ValueError, OSError) as exc:
raise RuntimeError(str(exc))

handle = events.Handle(callback, args, self, None)
self._signal_handlers[sig] = handle

try:
# 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)
# Register a signal handler to save signal number.
# _process_self_data() will
# handle signals by stored signal numbers.
signal.signal(sig, self._sig_handler)

# Set SA_RESTART to limit EINTR occurrences.
signal.siginterrupt(sig, False)
Expand Down
4 changes: 3 additions & 1 deletion Lib/test/test_asyncio/test_unix_events.py
Original file line number Diff line number Diff line change
Expand Up @@ -114,9 +114,11 @@ def test_add_signal_handler_install_error(self, m_signal):
m_signal.NSIG = signal.NSIG
m_signal.valid_signals = signal.valid_signals

def set_wakeup_fd(fd):
def set_wakeup_fd(fd, *, warn_on_full_buffer=True):
if fd == -1:
raise ValueError()
else:
self.assertFalse(warn_on_full_buffer)
m_signal.set_wakeup_fd = set_wakeup_fd

class Err(OSError):
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Don't log exception if event loop wakeup pipe is full