@ajksunkang-aios/kgraph-linux-x64 0.1.2 → 0.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/kgraph-launcher +15 -3
- package/lib/kgraph/scripts/build-bundle.sh +17 -4
- package/lib/site-packages/outcome/__init__.py +20 -0
- package/lib/site-packages/outcome/_impl.py +239 -0
- package/lib/site-packages/outcome/_util.py +33 -0
- package/lib/site-packages/outcome/_version.py +7 -0
- package/lib/site-packages/outcome/py.typed +0 -0
- package/lib/site-packages/outcome-1.3.0.post0.dist-info/INSTALLER +1 -0
- package/lib/site-packages/outcome-1.3.0.post0.dist-info/LICENSE +3 -0
- package/lib/site-packages/outcome-1.3.0.post0.dist-info/LICENSE.APACHE2 +202 -0
- package/lib/site-packages/outcome-1.3.0.post0.dist-info/LICENSE.MIT +20 -0
- package/lib/site-packages/outcome-1.3.0.post0.dist-info/METADATA +63 -0
- package/lib/site-packages/outcome-1.3.0.post0.dist-info/RECORD +13 -0
- package/lib/site-packages/outcome-1.3.0.post0.dist-info/WHEEL +6 -0
- package/lib/site-packages/outcome-1.3.0.post0.dist-info/top_level.txt +1 -0
- package/lib/site-packages/sniffio/__init__.py +17 -0
- package/lib/site-packages/sniffio/_impl.py +95 -0
- package/lib/site-packages/sniffio/_tests/__init__.py +0 -0
- package/lib/site-packages/sniffio/_tests/test_sniffio.py +84 -0
- package/lib/site-packages/sniffio/_version.py +3 -0
- package/lib/site-packages/sniffio/py.typed +0 -0
- package/lib/site-packages/sniffio-1.3.1.dist-info/INSTALLER +1 -0
- package/lib/site-packages/sniffio-1.3.1.dist-info/LICENSE +3 -0
- package/lib/site-packages/sniffio-1.3.1.dist-info/LICENSE.APACHE2 +202 -0
- package/lib/site-packages/sniffio-1.3.1.dist-info/LICENSE.MIT +20 -0
- package/lib/site-packages/sniffio-1.3.1.dist-info/METADATA +104 -0
- package/lib/site-packages/sniffio-1.3.1.dist-info/RECORD +14 -0
- package/lib/site-packages/sniffio-1.3.1.dist-info/WHEEL +5 -0
- package/lib/site-packages/sniffio-1.3.1.dist-info/top_level.txt +1 -0
- package/lib/site-packages/sortedcontainers/__init__.py +74 -0
- package/lib/site-packages/sortedcontainers/sorteddict.py +812 -0
- package/lib/site-packages/sortedcontainers/sortedlist.py +2646 -0
- package/lib/site-packages/sortedcontainers/sortedset.py +733 -0
- package/lib/site-packages/sortedcontainers-2.4.0.dist-info/INSTALLER +1 -0
- package/lib/site-packages/sortedcontainers-2.4.0.dist-info/LICENSE +13 -0
- package/lib/site-packages/sortedcontainers-2.4.0.dist-info/METADATA +264 -0
- package/lib/site-packages/sortedcontainers-2.4.0.dist-info/RECORD +10 -0
- package/lib/site-packages/sortedcontainers-2.4.0.dist-info/WHEEL +6 -0
- package/lib/site-packages/sortedcontainers-2.4.0.dist-info/top_level.txt +1 -0
- package/lib/site-packages/trio/__init__.py +133 -0
- package/lib/site-packages/trio/__main__.py +3 -0
- package/lib/site-packages/trio/_abc.py +714 -0
- package/lib/site-packages/trio/_channel.py +610 -0
- package/lib/site-packages/trio/_core/__init__.py +94 -0
- package/lib/site-packages/trio/_core/_asyncgens.py +243 -0
- package/lib/site-packages/trio/_core/_concat_tb.py +26 -0
- package/lib/site-packages/trio/_core/_entry_queue.py +223 -0
- package/lib/site-packages/trio/_core/_exceptions.py +169 -0
- package/lib/site-packages/trio/_core/_generated_instrumentation.py +50 -0
- package/lib/site-packages/trio/_core/_generated_io_epoll.py +98 -0
- package/lib/site-packages/trio/_core/_generated_io_kqueue.py +153 -0
- package/lib/site-packages/trio/_core/_generated_io_windows.py +204 -0
- package/lib/site-packages/trio/_core/_generated_run.py +269 -0
- package/lib/site-packages/trio/_core/_generated_windows_ffi.py +10 -0
- package/lib/site-packages/trio/_core/_instrumentation.py +117 -0
- package/lib/site-packages/trio/_core/_io_common.py +31 -0
- package/lib/site-packages/trio/_core/_io_epoll.py +385 -0
- package/lib/site-packages/trio/_core/_io_kqueue.py +292 -0
- package/lib/site-packages/trio/_core/_io_windows.py +1036 -0
- package/lib/site-packages/trio/_core/_ki.py +271 -0
- package/lib/site-packages/trio/_core/_local.py +104 -0
- package/lib/site-packages/trio/_core/_mock_clock.py +165 -0
- package/lib/site-packages/trio/_core/_parking_lot.py +317 -0
- package/lib/site-packages/trio/_core/_run.py +3148 -0
- package/lib/site-packages/trio/_core/_run_context.py +15 -0
- package/lib/site-packages/trio/_core/_tests/__init__.py +0 -0
- package/lib/site-packages/trio/_core/_tests/test_asyncgen.py +339 -0
- package/lib/site-packages/trio/_core/_tests/test_cancelled.py +222 -0
- package/lib/site-packages/trio/_core/_tests/test_exceptiongroup_gc.py +103 -0
- package/lib/site-packages/trio/_core/_tests/test_guest_mode.py +755 -0
- package/lib/site-packages/trio/_core/_tests/test_instrumentation.py +315 -0
- package/lib/site-packages/trio/_core/_tests/test_io.py +522 -0
- package/lib/site-packages/trio/_core/_tests/test_ki.py +703 -0
- package/lib/site-packages/trio/_core/_tests/test_local.py +118 -0
- package/lib/site-packages/trio/_core/_tests/test_mock_clock.py +193 -0
- package/lib/site-packages/trio/_core/_tests/test_parking_lot.py +389 -0
- package/lib/site-packages/trio/_core/_tests/test_run.py +3024 -0
- package/lib/site-packages/trio/_core/_tests/test_thread_cache.py +227 -0
- package/lib/site-packages/trio/_core/_tests/test_tutil.py +13 -0
- package/lib/site-packages/trio/_core/_tests/test_unbounded_queue.py +154 -0
- package/lib/site-packages/trio/_core/_tests/test_windows.py +305 -0
- package/lib/site-packages/trio/_core/_tests/tutil.py +117 -0
- package/lib/site-packages/trio/_core/_tests/type_tests/nursery_start.py +79 -0
- package/lib/site-packages/trio/_core/_tests/type_tests/run.py +51 -0
- package/lib/site-packages/trio/_core/_thread_cache.py +317 -0
- package/lib/site-packages/trio/_core/_traps.py +318 -0
- package/lib/site-packages/trio/_core/_unbounded_queue.py +163 -0
- package/lib/site-packages/trio/_core/_wakeup_socketpair.py +75 -0
- package/lib/site-packages/trio/_core/_windows_cffi.py +313 -0
- package/lib/site-packages/trio/_deprecate.py +171 -0
- package/lib/site-packages/trio/_dtls.py +1380 -0
- package/lib/site-packages/trio/_file_io.py +513 -0
- package/lib/site-packages/trio/_highlevel_generic.py +125 -0
- package/lib/site-packages/trio/_highlevel_open_tcp_listeners.py +251 -0
- package/lib/site-packages/trio/_highlevel_open_tcp_stream.py +397 -0
- package/lib/site-packages/trio/_highlevel_open_unix_stream.py +65 -0
- package/lib/site-packages/trio/_highlevel_serve_listeners.py +148 -0
- package/lib/site-packages/trio/_highlevel_socket.py +423 -0
- package/lib/site-packages/trio/_highlevel_ssl_helpers.py +180 -0
- package/lib/site-packages/trio/_path.py +289 -0
- package/lib/site-packages/trio/_repl.py +159 -0
- package/lib/site-packages/trio/_signals.py +185 -0
- package/lib/site-packages/trio/_socket.py +1326 -0
- package/lib/site-packages/trio/_ssl.py +964 -0
- package/lib/site-packages/trio/_subprocess.py +1178 -0
- package/lib/site-packages/trio/_subprocess_platform/__init__.py +123 -0
- package/lib/site-packages/trio/_subprocess_platform/kqueue.py +48 -0
- package/lib/site-packages/trio/_subprocess_platform/waitid.py +113 -0
- package/lib/site-packages/trio/_subprocess_platform/windows.py +11 -0
- package/lib/site-packages/trio/_sync.py +908 -0
- package/lib/site-packages/trio/_tests/__init__.py +0 -0
- package/lib/site-packages/trio/_tests/astrill-codesigning-cert.cer +0 -0
- package/lib/site-packages/trio/_tests/check_type_completeness.py +247 -0
- package/lib/site-packages/trio/_tests/module_with_deprecations.py +22 -0
- package/lib/site-packages/trio/_tests/pytest_plugin.py +54 -0
- package/lib/site-packages/trio/_tests/test_abc.py +72 -0
- package/lib/site-packages/trio/_tests/test_channel.py +750 -0
- package/lib/site-packages/trio/_tests/test_contextvars.py +56 -0
- package/lib/site-packages/trio/_tests/test_deprecate.py +277 -0
- package/lib/site-packages/trio/_tests/test_deprecate_strict_exception_groups_false.py +64 -0
- package/lib/site-packages/trio/_tests/test_dtls.py +950 -0
- package/lib/site-packages/trio/_tests/test_exports.py +626 -0
- package/lib/site-packages/trio/_tests/test_fakenet.py +317 -0
- package/lib/site-packages/trio/_tests/test_file_io.py +269 -0
- package/lib/site-packages/trio/_tests/test_highlevel_generic.py +98 -0
- package/lib/site-packages/trio/_tests/test_highlevel_open_tcp_listeners.py +419 -0
- package/lib/site-packages/trio/_tests/test_highlevel_open_tcp_stream.py +693 -0
- package/lib/site-packages/trio/_tests/test_highlevel_open_unix_stream.py +86 -0
- package/lib/site-packages/trio/_tests/test_highlevel_serve_listeners.py +186 -0
- package/lib/site-packages/trio/_tests/test_highlevel_socket.py +336 -0
- package/lib/site-packages/trio/_tests/test_highlevel_ssl_helpers.py +169 -0
- package/lib/site-packages/trio/_tests/test_path.py +279 -0
- package/lib/site-packages/trio/_tests/test_repl.py +428 -0
- package/lib/site-packages/trio/_tests/test_scheduler_determinism.py +47 -0
- package/lib/site-packages/trio/_tests/test_signals.py +186 -0
- package/lib/site-packages/trio/_tests/test_socket.py +1253 -0
- package/lib/site-packages/trio/_tests/test_ssl.py +1371 -0
- package/lib/site-packages/trio/_tests/test_subprocess.py +767 -0
- package/lib/site-packages/trio/_tests/test_sync.py +735 -0
- package/lib/site-packages/trio/_tests/test_testing.py +682 -0
- package/lib/site-packages/trio/_tests/test_testing_raisesgroup.py +1128 -0
- package/lib/site-packages/trio/_tests/test_threads.py +1173 -0
- package/lib/site-packages/trio/_tests/test_timeouts.py +281 -0
- package/lib/site-packages/trio/_tests/test_tracing.py +88 -0
- package/lib/site-packages/trio/_tests/test_trio.py +8 -0
- package/lib/site-packages/trio/_tests/test_unix_pipes.py +288 -0
- package/lib/site-packages/trio/_tests/test_util.py +349 -0
- package/lib/site-packages/trio/_tests/test_wait_for_object.py +225 -0
- package/lib/site-packages/trio/_tests/test_windows_pipes.py +112 -0
- package/lib/site-packages/trio/_tests/tools/__init__.py +0 -0
- package/lib/site-packages/trio/_tests/tools/test_gen_exports.py +179 -0
- package/lib/site-packages/trio/_tests/tools/test_mypy_annotate.py +140 -0
- package/lib/site-packages/trio/_tests/tools/test_sync_requirements.py +80 -0
- package/lib/site-packages/trio/_tests/type_tests/check_wraps.py +9 -0
- package/lib/site-packages/trio/_tests/type_tests/open_memory_channel.py +4 -0
- package/lib/site-packages/trio/_tests/type_tests/path.py +140 -0
- package/lib/site-packages/trio/_tests/type_tests/subprocesses.py +23 -0
- package/lib/site-packages/trio/_tests/type_tests/task_status.py +29 -0
- package/lib/site-packages/trio/_threads.py +610 -0
- package/lib/site-packages/trio/_timeouts.py +197 -0
- package/lib/site-packages/trio/_tools/__init__.py +0 -0
- package/lib/site-packages/trio/_tools/gen_exports.py +401 -0
- package/lib/site-packages/trio/_tools/mypy_annotate.py +126 -0
- package/lib/site-packages/trio/_tools/sync_requirements.py +98 -0
- package/lib/site-packages/trio/_tools/windows_ffi_build.py +220 -0
- package/lib/site-packages/trio/_unix_pipes.py +197 -0
- package/lib/site-packages/trio/_util.py +385 -0
- package/lib/site-packages/trio/_version.py +3 -0
- package/lib/site-packages/trio/_wait_for_object.py +67 -0
- package/lib/site-packages/trio/_windows_pipes.py +144 -0
- package/lib/site-packages/trio/abc.py +23 -0
- package/lib/site-packages/trio/from_thread.py +13 -0
- package/lib/site-packages/trio/lowlevel.py +95 -0
- package/lib/site-packages/trio/py.typed +0 -0
- package/lib/site-packages/trio/socket.py +602 -0
- package/lib/site-packages/trio/testing/__init__.py +58 -0
- package/lib/site-packages/trio/testing/_check_streams.py +570 -0
- package/lib/site-packages/trio/testing/_checkpoints.py +69 -0
- package/lib/site-packages/trio/testing/_fake_net.py +584 -0
- package/lib/site-packages/trio/testing/_memory_streams.py +633 -0
- package/lib/site-packages/trio/testing/_network.py +36 -0
- package/lib/site-packages/trio/testing/_raises_group.py +1015 -0
- package/lib/site-packages/trio/testing/_sequencer.py +87 -0
- package/lib/site-packages/trio/testing/_trio_test.py +50 -0
- package/lib/site-packages/trio/to_thread.py +4 -0
- package/lib/site-packages/trio-0.33.0.dist-info/INSTALLER +1 -0
- package/lib/site-packages/trio-0.33.0.dist-info/METADATA +186 -0
- package/lib/site-packages/trio-0.33.0.dist-info/RECORD +156 -0
- package/lib/site-packages/trio-0.33.0.dist-info/REQUESTED +0 -0
- package/lib/site-packages/trio-0.33.0.dist-info/WHEEL +5 -0
- package/lib/site-packages/trio-0.33.0.dist-info/entry_points.txt +2 -0
- package/lib/site-packages/trio-0.33.0.dist-info/licenses/LICENSE +3 -0
- package/lib/site-packages/trio-0.33.0.dist-info/licenses/LICENSE.APACHE2 +202 -0
- package/lib/site-packages/trio-0.33.0.dist-info/licenses/LICENSE.MIT +22 -0
- package/lib/site-packages/trio-0.33.0.dist-info/top_level.txt +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
# Platform-specific subprocess bits'n'pieces.
|
|
2
|
+
from __future__ import annotations
|
|
3
|
+
|
|
4
|
+
import os
|
|
5
|
+
import sys
|
|
6
|
+
from typing import TYPE_CHECKING
|
|
7
|
+
|
|
8
|
+
import trio
|
|
9
|
+
|
|
10
|
+
from .. import _core, _subprocess
|
|
11
|
+
from .._abc import ReceiveStream, SendStream # noqa: TC001
|
|
12
|
+
|
|
13
|
+
_wait_child_exiting_error: ImportError | None = None
|
|
14
|
+
_create_child_pipe_error: ImportError | None = None
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
if TYPE_CHECKING:
|
|
18
|
+
# internal types for the pipe representations used in type checking only
|
|
19
|
+
class ClosableSendStream(SendStream):
|
|
20
|
+
def close(self) -> None: ...
|
|
21
|
+
|
|
22
|
+
class ClosableReceiveStream(ReceiveStream):
|
|
23
|
+
def close(self) -> None: ...
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
# Fallback versions of the functions provided -- implementations
|
|
27
|
+
# per OS are imported atop these at the bottom of the module.
|
|
28
|
+
async def wait_child_exiting(process: _subprocess.Process) -> None:
|
|
29
|
+
"""Block until the child process managed by ``process`` is exiting.
|
|
30
|
+
|
|
31
|
+
It is invalid to call this function if the process has already
|
|
32
|
+
been waited on; that is, ``process.returncode`` must be None.
|
|
33
|
+
|
|
34
|
+
When this function returns, it indicates that a call to
|
|
35
|
+
:meth:`subprocess.Popen.wait` will immediately be able to
|
|
36
|
+
return the process's exit status. The actual exit status is not
|
|
37
|
+
consumed by this call, since :class:`~subprocess.Popen` wants
|
|
38
|
+
to be able to do that itself.
|
|
39
|
+
"""
|
|
40
|
+
raise NotImplementedError from _wait_child_exiting_error # pragma: no cover
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
def create_pipe_to_child_stdin() -> tuple[ClosableSendStream, int]:
|
|
44
|
+
"""Create a new pipe suitable for sending data from this
|
|
45
|
+
process to the standard input of a child we're about to spawn.
|
|
46
|
+
|
|
47
|
+
Returns:
|
|
48
|
+
A pair ``(trio_end, subprocess_end)`` where ``trio_end`` is a
|
|
49
|
+
:class:`~trio.abc.SendStream` and ``subprocess_end`` is
|
|
50
|
+
something suitable for passing as the ``stdin`` argument of
|
|
51
|
+
:class:`subprocess.Popen`.
|
|
52
|
+
"""
|
|
53
|
+
raise NotImplementedError from _create_child_pipe_error # pragma: no cover
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
def create_pipe_from_child_output() -> tuple[ClosableReceiveStream, int]:
|
|
57
|
+
"""Create a new pipe suitable for receiving data into this
|
|
58
|
+
process from the standard output or error stream of a child
|
|
59
|
+
we're about to spawn.
|
|
60
|
+
|
|
61
|
+
Returns:
|
|
62
|
+
A pair ``(trio_end, subprocess_end)`` where ``trio_end`` is a
|
|
63
|
+
:class:`~trio.abc.ReceiveStream` and ``subprocess_end`` is
|
|
64
|
+
something suitable for passing as the ``stdin`` argument of
|
|
65
|
+
:class:`subprocess.Popen`.
|
|
66
|
+
"""
|
|
67
|
+
raise NotImplementedError from _create_child_pipe_error # pragma: no cover
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
try:
|
|
71
|
+
if sys.platform == "win32":
|
|
72
|
+
from .windows import wait_child_exiting
|
|
73
|
+
elif sys.platform != "linux" and (TYPE_CHECKING or hasattr(_core, "wait_kevent")):
|
|
74
|
+
from .kqueue import wait_child_exiting
|
|
75
|
+
else:
|
|
76
|
+
# as it's an exported symbol, noqa'd
|
|
77
|
+
from .waitid import wait_child_exiting # noqa: F401
|
|
78
|
+
except ImportError as ex: # pragma: no cover
|
|
79
|
+
_wait_child_exiting_error = ex
|
|
80
|
+
|
|
81
|
+
try:
|
|
82
|
+
if TYPE_CHECKING:
|
|
83
|
+
# Not worth type checking these definitions
|
|
84
|
+
pass
|
|
85
|
+
|
|
86
|
+
elif os.name == "posix":
|
|
87
|
+
|
|
88
|
+
def create_pipe_to_child_stdin() -> tuple[trio.lowlevel.FdStream, int]:
|
|
89
|
+
rfd, wfd = os.pipe()
|
|
90
|
+
return trio.lowlevel.FdStream(wfd), rfd
|
|
91
|
+
|
|
92
|
+
def create_pipe_from_child_output() -> tuple[trio.lowlevel.FdStream, int]:
|
|
93
|
+
rfd, wfd = os.pipe()
|
|
94
|
+
return trio.lowlevel.FdStream(rfd), wfd
|
|
95
|
+
|
|
96
|
+
elif os.name == "nt":
|
|
97
|
+
import msvcrt
|
|
98
|
+
|
|
99
|
+
# This isn't exported or documented, but it's also not
|
|
100
|
+
# underscore-prefixed, and seems kosher to use. The asyncio docs
|
|
101
|
+
# for 3.5 included an example that imported socketpair from
|
|
102
|
+
# windows_utils (before socket.socketpair existed on Windows), and
|
|
103
|
+
# when asyncio.windows_utils.socketpair was removed in 3.7, the
|
|
104
|
+
# removal was mentioned in the release notes.
|
|
105
|
+
from asyncio.windows_utils import pipe as windows_pipe
|
|
106
|
+
|
|
107
|
+
from .._windows_pipes import PipeReceiveStream, PipeSendStream
|
|
108
|
+
|
|
109
|
+
def create_pipe_to_child_stdin() -> tuple[PipeSendStream, int]:
|
|
110
|
+
# for stdin, we want the write end (our end) to use overlapped I/O
|
|
111
|
+
rh, wh = windows_pipe(overlapped=(False, True))
|
|
112
|
+
return PipeSendStream(wh), msvcrt.open_osfhandle(rh, os.O_RDONLY)
|
|
113
|
+
|
|
114
|
+
def create_pipe_from_child_output() -> tuple[PipeReceiveStream, int]:
|
|
115
|
+
# for stdout/err, it's the read end that's overlapped
|
|
116
|
+
rh, wh = windows_pipe(overlapped=(True, False))
|
|
117
|
+
return PipeReceiveStream(rh), msvcrt.open_osfhandle(wh, 0)
|
|
118
|
+
|
|
119
|
+
else: # pragma: no cover
|
|
120
|
+
raise ImportError("pipes not implemented on this platform")
|
|
121
|
+
|
|
122
|
+
except ImportError as ex: # pragma: no cover
|
|
123
|
+
_create_child_pipe_error = ex
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import select
|
|
4
|
+
import sys
|
|
5
|
+
from typing import TYPE_CHECKING
|
|
6
|
+
|
|
7
|
+
from .. import _core, _subprocess
|
|
8
|
+
|
|
9
|
+
assert (sys.platform != "win32" and sys.platform != "linux") or not TYPE_CHECKING
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
async def wait_child_exiting(process: _subprocess.Process) -> None:
|
|
13
|
+
kqueue = _core.current_kqueue()
|
|
14
|
+
try:
|
|
15
|
+
from select import KQ_NOTE_EXIT
|
|
16
|
+
except ImportError: # pragma: no cover
|
|
17
|
+
# pypy doesn't define KQ_NOTE_EXIT:
|
|
18
|
+
# https://bitbucket.org/pypy/pypy/issues/2921/
|
|
19
|
+
# I verified this value against both Darwin and FreeBSD
|
|
20
|
+
KQ_NOTE_EXIT = 0x80000000 # type: ignore[misc]
|
|
21
|
+
|
|
22
|
+
def make_event(flags: int) -> select.kevent:
|
|
23
|
+
return select.kevent(
|
|
24
|
+
process.pid,
|
|
25
|
+
filter=select.KQ_FILTER_PROC,
|
|
26
|
+
flags=flags,
|
|
27
|
+
fflags=KQ_NOTE_EXIT,
|
|
28
|
+
)
|
|
29
|
+
|
|
30
|
+
try:
|
|
31
|
+
kqueue.control([make_event(select.KQ_EV_ADD | select.KQ_EV_ONESHOT)], 0)
|
|
32
|
+
except ProcessLookupError: # pragma: no cover
|
|
33
|
+
# This can supposedly happen if the process is in the process
|
|
34
|
+
# of exiting, and it can even be the case that kqueue says the
|
|
35
|
+
# process doesn't exist before waitpid(WNOHANG) says it hasn't
|
|
36
|
+
# exited yet. See the discussion in https://chromium.googlesource.com/
|
|
37
|
+
# chromium/src/base/+/master/process/kill_mac.cc .
|
|
38
|
+
# We haven't actually seen this error occur since we added
|
|
39
|
+
# locking to prevent multiple calls to wait_child_exiting()
|
|
40
|
+
# for the same process simultaneously, but given the explanation
|
|
41
|
+
# in Chromium it seems we should still keep the check.
|
|
42
|
+
return
|
|
43
|
+
|
|
44
|
+
def abort(_: _core.RaiseCancelT) -> _core.Abort:
|
|
45
|
+
kqueue.control([make_event(select.KQ_EV_DELETE)], 0)
|
|
46
|
+
return _core.Abort.SUCCEEDED
|
|
47
|
+
|
|
48
|
+
await _core.wait_kevent(process.pid, select.KQ_FILTER_PROC, abort)
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import errno
|
|
2
|
+
import math
|
|
3
|
+
import os
|
|
4
|
+
import sys
|
|
5
|
+
from typing import TYPE_CHECKING
|
|
6
|
+
|
|
7
|
+
from .. import _core, _subprocess
|
|
8
|
+
from .._sync import CapacityLimiter, Event
|
|
9
|
+
from .._threads import to_thread_run_sync
|
|
10
|
+
|
|
11
|
+
assert (sys.platform != "win32" and sys.platform != "darwin") or not TYPE_CHECKING
|
|
12
|
+
|
|
13
|
+
try:
|
|
14
|
+
from os import waitid
|
|
15
|
+
|
|
16
|
+
def sync_wait_reapable(pid: int) -> None:
|
|
17
|
+
waitid(os.P_PID, pid, os.WEXITED | os.WNOWAIT)
|
|
18
|
+
|
|
19
|
+
except ImportError:
|
|
20
|
+
# pypy doesn't define os.waitid so we need to pull it out ourselves
|
|
21
|
+
# using cffi: https://bitbucket.org/pypy/pypy/issues/2922/
|
|
22
|
+
import cffi
|
|
23
|
+
|
|
24
|
+
waitid_ffi = cffi.FFI()
|
|
25
|
+
|
|
26
|
+
# Believe it or not, siginfo_t starts with fields in the
|
|
27
|
+
# same layout on both Linux and Darwin. The Linux structure
|
|
28
|
+
# is bigger so that's what we use to size `pad`; while
|
|
29
|
+
# there are a few extra fields in there, most of it is
|
|
30
|
+
# true padding which would not be written by the syscall.
|
|
31
|
+
waitid_ffi.cdef(
|
|
32
|
+
"""
|
|
33
|
+
typedef struct siginfo_s {
|
|
34
|
+
int si_signo;
|
|
35
|
+
int si_errno;
|
|
36
|
+
int si_code;
|
|
37
|
+
int si_pid;
|
|
38
|
+
int si_uid;
|
|
39
|
+
int si_status;
|
|
40
|
+
int pad[26];
|
|
41
|
+
} siginfo_t;
|
|
42
|
+
int waitid(int idtype, int id, siginfo_t* result, int options);
|
|
43
|
+
""",
|
|
44
|
+
)
|
|
45
|
+
waitid_cffi = waitid_ffi.dlopen(None).waitid # type: ignore[attr-defined]
|
|
46
|
+
|
|
47
|
+
def sync_wait_reapable(pid: int) -> None:
|
|
48
|
+
P_PID = 1
|
|
49
|
+
WEXITED = 0x00000004
|
|
50
|
+
if sys.platform == "darwin": # pragma: no cover
|
|
51
|
+
# waitid() is not exposed on Python on Darwin but does
|
|
52
|
+
# work through CFFI; note that we typically won't get
|
|
53
|
+
# here since Darwin also defines kqueue
|
|
54
|
+
WNOWAIT = 0x00000020
|
|
55
|
+
else:
|
|
56
|
+
WNOWAIT = 0x01000000
|
|
57
|
+
result = waitid_ffi.new("siginfo_t *")
|
|
58
|
+
while waitid_cffi(P_PID, pid, result, WEXITED | WNOWAIT) < 0:
|
|
59
|
+
got_errno = waitid_ffi.errno
|
|
60
|
+
if got_errno == errno.EINTR:
|
|
61
|
+
continue
|
|
62
|
+
raise OSError(got_errno, os.strerror(got_errno))
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
# adapted from
|
|
66
|
+
# https://github.com/python-trio/trio/issues/4#issuecomment-398967572
|
|
67
|
+
|
|
68
|
+
waitid_limiter = CapacityLimiter(math.inf)
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
async def _waitid_system_task(pid: int, event: Event) -> None:
|
|
72
|
+
"""Spawn a thread that waits for ``pid`` to exit, then wake any tasks
|
|
73
|
+
that were waiting on it.
|
|
74
|
+
"""
|
|
75
|
+
# abandon_on_cancel=True: if this task is cancelled, then we abandon the
|
|
76
|
+
# thread to keep running waitpid in the background. Since this is
|
|
77
|
+
# always run as a system task, this will only happen if the whole
|
|
78
|
+
# call to trio.run is shutting down.
|
|
79
|
+
|
|
80
|
+
try:
|
|
81
|
+
await to_thread_run_sync(
|
|
82
|
+
sync_wait_reapable,
|
|
83
|
+
pid,
|
|
84
|
+
abandon_on_cancel=True,
|
|
85
|
+
limiter=waitid_limiter,
|
|
86
|
+
)
|
|
87
|
+
except OSError:
|
|
88
|
+
# If waitid fails, waitpid will fail too, so it still makes
|
|
89
|
+
# sense to wake up the callers of wait_process_exiting(). The
|
|
90
|
+
# most likely reason for this error in practice is a child
|
|
91
|
+
# exiting when wait() is not possible because SIGCHLD is
|
|
92
|
+
# ignored.
|
|
93
|
+
pass
|
|
94
|
+
finally:
|
|
95
|
+
event.set()
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
async def wait_child_exiting(process: "_subprocess.Process") -> None:
|
|
99
|
+
# Logic of this function:
|
|
100
|
+
# - The first time we get called, we create an Event and start
|
|
101
|
+
# an instance of _waitid_system_task that will set the Event
|
|
102
|
+
# when waitid() completes. If that Event is set before
|
|
103
|
+
# we get cancelled, we're good.
|
|
104
|
+
# - Otherwise, a following call after the cancellation must
|
|
105
|
+
# reuse the Event created during the first call, lest we
|
|
106
|
+
# create an arbitrary number of threads waiting on the same
|
|
107
|
+
# process.
|
|
108
|
+
|
|
109
|
+
if process._wait_for_exit_data is None:
|
|
110
|
+
process._wait_for_exit_data = event = Event()
|
|
111
|
+
_core.spawn_system_task(_waitid_system_task, process.pid, event)
|
|
112
|
+
assert isinstance(process._wait_for_exit_data, Event)
|
|
113
|
+
await process._wait_for_exit_data.wait()
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
from typing import TYPE_CHECKING
|
|
2
|
+
|
|
3
|
+
from .._wait_for_object import WaitForSingleObject
|
|
4
|
+
|
|
5
|
+
if TYPE_CHECKING:
|
|
6
|
+
from .. import _subprocess
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
async def wait_child_exiting(process: "_subprocess.Process") -> None:
|
|
10
|
+
# _handle is not in Popen stubs, though it is present on Windows.
|
|
11
|
+
await WaitForSingleObject(int(process._proc._handle)) # type: ignore[attr-defined]
|