Skip to content

Commit

Permalink
use InterruptedError instead of catching EINTR
Browse files Browse the repository at this point in the history
  • Loading branch information
giampaolo committed Jun 21, 2024
1 parent 9d697bc commit 15bb392
Show file tree
Hide file tree
Showing 4 changed files with 17 additions and 20 deletions.
5 changes: 5 additions & 0 deletions pyftpdlib/_compat.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ def callable(obj):
if PY3:
FileNotFoundError = FileNotFoundError # NOQA
FileExistsError = FileExistsError # NOQA
InterruptedError = InterruptedError # NOQA
else:
# https://github.com/PythonCharmers/python-future/blob/exceptions/
# src/future/types/exceptions/pep3151.py
Expand Down Expand Up @@ -99,6 +100,10 @@ def FileNotFoundError(inst):
def FileExistsError(inst):
return getattr(inst, 'errno', _SENTINEL) == errno.EEXIST

@_instance_checking_exception(EnvironmentError)
def InterruptedError(inst):
return getattr(inst, 'errno', _SENTINEL) == errno.EINTR

if platform.python_implementation() != "CPython":
try:
raise OSError(errno.EEXIST, "perm")
Expand Down
20 changes: 7 additions & 13 deletions pyftpdlib/ioloop.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ def handle_accepted(self, sock, addr):
import traceback

from ._compat import PY3
from ._compat import InterruptedError


try:
Expand Down Expand Up @@ -485,10 +486,8 @@ def modify(self, fd, events):
def poll(self, timeout):
try:
r, w, _ = select.select(self._r, self._w, [], timeout)
except select.error as err:
if getattr(err, "errno", None) == errno.EINTR:
return
raise
except InterruptedError:
return

smap_get = self.socket_map.get
for fd in r:
Expand Down Expand Up @@ -564,11 +563,8 @@ def poll(self, timeout):
timeout = -1 # -1 waits indefinitely
try:
events = self._poller.poll(timeout)
except (IOError, select.error) as err:
# for epoll() and poll() respectively
if err.errno == errno.EINTR:
return
raise
except InterruptedError:
return
# localize variable access to minimize overhead
smap_get = self.socket_map.get
for fd, event in events:
Expand Down Expand Up @@ -767,10 +763,8 @@ def poll(
kevents = self._kqueue.control(
None, _len(self.socket_map), timeout
)
except OSError as err:
if err.errno == errno.EINTR:
return
raise
except InterruptedError:
return
for kevent in kevents:
inst = self.socket_map.get(kevent.ident)
if inst is None:
Expand Down
8 changes: 3 additions & 5 deletions pyftpdlib/prefork.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@

"""Process utils."""

import errno
import os
import sys
import time
Expand All @@ -16,6 +15,7 @@
except ImportError:
multiprocessing = None

from ._compat import InterruptedError
from ._compat import long
from .log import logger

Expand Down Expand Up @@ -98,10 +98,8 @@ def start_child(i):
while children:
try:
pid, status = os.wait()
except OSError as e:
if e.errno == errno.EINTR:
continue
raise
except InterruptedError:
continue
if pid not in children:
continue
id = children.pop(pid)
Expand Down
4 changes: 2 additions & 2 deletions pyftpdlib/test/test_ioloop.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@

import pyftpdlib.ioloop
from pyftpdlib._compat import PY3
from pyftpdlib._compat import InterruptedError
from pyftpdlib._compat import super
from pyftpdlib.ioloop import Acceptor
from pyftpdlib.ioloop import AsyncChat
Expand Down Expand Up @@ -168,9 +169,8 @@ class SelectIOLoopTestCase(PyftpdlibTestCase, BaseIOLoopTestCase):
def test_select_eintr(self):
# EINTR is supposed to be ignored
with mock.patch(
'pyftpdlib.ioloop.select.select', side_effect=select.error()
'pyftpdlib.ioloop.select.select', side_effect=InterruptedError
) as m:
m.side_effect.errno = errno.EINTR
s, rd, wr = self.test_register()
s.poll(0)
# ...but just that
Expand Down

0 comments on commit 15bb392

Please sign in to comment.