Skip to content
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

fix: Improve checks for pidfd availability #51

Merged
merged 3 commits into from
Apr 26, 2022
Merged
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
1 change: 1 addition & 0 deletions changes/51.fix.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Improve checks for pidfd availability to avoid corner cases that may fail on Linux kernel 5.1 and 5.2 where `signal.pidfd_send_signal()` is available but `os.pidfd_open()` is not
9 changes: 6 additions & 3 deletions src/aiotools/fork.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,14 @@
logger = logging.getLogger(__name__)

_has_pidfd = False
if hasattr(signal, 'pidfd_send_signal'):
if hasattr(os, 'pidfd_open'):
# signal.pidfd_send_signal() is available in Linux kernel 5.1+
# and os.pidfd_open() is available in Linux kernel 5.3+.
# So let's check with os.pidfd_open() which requires higher version.
try:
signal.pidfd_send_signal(0, 0) # type: ignore
os.pidfd_open(0, 0) # type: ignore
except OSError as e:
if e.errno == errno.EBADF:
if e.errno in (errno.EBADF, errno.EINVAL):
_has_pidfd = True
# if the kernel does not support this,
# it will say errno.ENOSYS or errno.EPERM
Expand Down
9 changes: 6 additions & 3 deletions src/aiotools/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ async def myserver(loop, pidx, args):

from .compat import all_tasks, current_task, get_running_loop
from .context import AbstractAsyncContextManager
from .fork import AbstractChildProcess, afork
from .fork import AbstractChildProcess, afork, _has_pidfd

try:
from typing import Literal
Expand Down Expand Up @@ -251,11 +251,14 @@ def helper(*args, **kwargs):

def setup_child_watcher(loop: asyncio.AbstractEventLoop) -> None:
try:
asyncio.get_child_watcher()
watcher_cls = getattr(asyncio, 'PidfdChildWatcher', None)
if watcher_cls is not None:
if _has_pidfd and watcher_cls:
watcher = watcher_cls()
asyncio.set_child_watcher(watcher)
else:
# Just get the default child watcher.
watcher = asyncio.get_child_watcher()
if not watcher.is_active():
watcher.attach_loop(loop)
except NotImplementedError:
pass # for uvloop
Expand Down