@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.
Files changed (196) hide show
  1. package/bin/kgraph-launcher +15 -3
  2. package/lib/kgraph/scripts/build-bundle.sh +17 -4
  3. package/lib/site-packages/outcome/__init__.py +20 -0
  4. package/lib/site-packages/outcome/_impl.py +239 -0
  5. package/lib/site-packages/outcome/_util.py +33 -0
  6. package/lib/site-packages/outcome/_version.py +7 -0
  7. package/lib/site-packages/outcome/py.typed +0 -0
  8. package/lib/site-packages/outcome-1.3.0.post0.dist-info/INSTALLER +1 -0
  9. package/lib/site-packages/outcome-1.3.0.post0.dist-info/LICENSE +3 -0
  10. package/lib/site-packages/outcome-1.3.0.post0.dist-info/LICENSE.APACHE2 +202 -0
  11. package/lib/site-packages/outcome-1.3.0.post0.dist-info/LICENSE.MIT +20 -0
  12. package/lib/site-packages/outcome-1.3.0.post0.dist-info/METADATA +63 -0
  13. package/lib/site-packages/outcome-1.3.0.post0.dist-info/RECORD +13 -0
  14. package/lib/site-packages/outcome-1.3.0.post0.dist-info/WHEEL +6 -0
  15. package/lib/site-packages/outcome-1.3.0.post0.dist-info/top_level.txt +1 -0
  16. package/lib/site-packages/sniffio/__init__.py +17 -0
  17. package/lib/site-packages/sniffio/_impl.py +95 -0
  18. package/lib/site-packages/sniffio/_tests/__init__.py +0 -0
  19. package/lib/site-packages/sniffio/_tests/test_sniffio.py +84 -0
  20. package/lib/site-packages/sniffio/_version.py +3 -0
  21. package/lib/site-packages/sniffio/py.typed +0 -0
  22. package/lib/site-packages/sniffio-1.3.1.dist-info/INSTALLER +1 -0
  23. package/lib/site-packages/sniffio-1.3.1.dist-info/LICENSE +3 -0
  24. package/lib/site-packages/sniffio-1.3.1.dist-info/LICENSE.APACHE2 +202 -0
  25. package/lib/site-packages/sniffio-1.3.1.dist-info/LICENSE.MIT +20 -0
  26. package/lib/site-packages/sniffio-1.3.1.dist-info/METADATA +104 -0
  27. package/lib/site-packages/sniffio-1.3.1.dist-info/RECORD +14 -0
  28. package/lib/site-packages/sniffio-1.3.1.dist-info/WHEEL +5 -0
  29. package/lib/site-packages/sniffio-1.3.1.dist-info/top_level.txt +1 -0
  30. package/lib/site-packages/sortedcontainers/__init__.py +74 -0
  31. package/lib/site-packages/sortedcontainers/sorteddict.py +812 -0
  32. package/lib/site-packages/sortedcontainers/sortedlist.py +2646 -0
  33. package/lib/site-packages/sortedcontainers/sortedset.py +733 -0
  34. package/lib/site-packages/sortedcontainers-2.4.0.dist-info/INSTALLER +1 -0
  35. package/lib/site-packages/sortedcontainers-2.4.0.dist-info/LICENSE +13 -0
  36. package/lib/site-packages/sortedcontainers-2.4.0.dist-info/METADATA +264 -0
  37. package/lib/site-packages/sortedcontainers-2.4.0.dist-info/RECORD +10 -0
  38. package/lib/site-packages/sortedcontainers-2.4.0.dist-info/WHEEL +6 -0
  39. package/lib/site-packages/sortedcontainers-2.4.0.dist-info/top_level.txt +1 -0
  40. package/lib/site-packages/trio/__init__.py +133 -0
  41. package/lib/site-packages/trio/__main__.py +3 -0
  42. package/lib/site-packages/trio/_abc.py +714 -0
  43. package/lib/site-packages/trio/_channel.py +610 -0
  44. package/lib/site-packages/trio/_core/__init__.py +94 -0
  45. package/lib/site-packages/trio/_core/_asyncgens.py +243 -0
  46. package/lib/site-packages/trio/_core/_concat_tb.py +26 -0
  47. package/lib/site-packages/trio/_core/_entry_queue.py +223 -0
  48. package/lib/site-packages/trio/_core/_exceptions.py +169 -0
  49. package/lib/site-packages/trio/_core/_generated_instrumentation.py +50 -0
  50. package/lib/site-packages/trio/_core/_generated_io_epoll.py +98 -0
  51. package/lib/site-packages/trio/_core/_generated_io_kqueue.py +153 -0
  52. package/lib/site-packages/trio/_core/_generated_io_windows.py +204 -0
  53. package/lib/site-packages/trio/_core/_generated_run.py +269 -0
  54. package/lib/site-packages/trio/_core/_generated_windows_ffi.py +10 -0
  55. package/lib/site-packages/trio/_core/_instrumentation.py +117 -0
  56. package/lib/site-packages/trio/_core/_io_common.py +31 -0
  57. package/lib/site-packages/trio/_core/_io_epoll.py +385 -0
  58. package/lib/site-packages/trio/_core/_io_kqueue.py +292 -0
  59. package/lib/site-packages/trio/_core/_io_windows.py +1036 -0
  60. package/lib/site-packages/trio/_core/_ki.py +271 -0
  61. package/lib/site-packages/trio/_core/_local.py +104 -0
  62. package/lib/site-packages/trio/_core/_mock_clock.py +165 -0
  63. package/lib/site-packages/trio/_core/_parking_lot.py +317 -0
  64. package/lib/site-packages/trio/_core/_run.py +3148 -0
  65. package/lib/site-packages/trio/_core/_run_context.py +15 -0
  66. package/lib/site-packages/trio/_core/_tests/__init__.py +0 -0
  67. package/lib/site-packages/trio/_core/_tests/test_asyncgen.py +339 -0
  68. package/lib/site-packages/trio/_core/_tests/test_cancelled.py +222 -0
  69. package/lib/site-packages/trio/_core/_tests/test_exceptiongroup_gc.py +103 -0
  70. package/lib/site-packages/trio/_core/_tests/test_guest_mode.py +755 -0
  71. package/lib/site-packages/trio/_core/_tests/test_instrumentation.py +315 -0
  72. package/lib/site-packages/trio/_core/_tests/test_io.py +522 -0
  73. package/lib/site-packages/trio/_core/_tests/test_ki.py +703 -0
  74. package/lib/site-packages/trio/_core/_tests/test_local.py +118 -0
  75. package/lib/site-packages/trio/_core/_tests/test_mock_clock.py +193 -0
  76. package/lib/site-packages/trio/_core/_tests/test_parking_lot.py +389 -0
  77. package/lib/site-packages/trio/_core/_tests/test_run.py +3024 -0
  78. package/lib/site-packages/trio/_core/_tests/test_thread_cache.py +227 -0
  79. package/lib/site-packages/trio/_core/_tests/test_tutil.py +13 -0
  80. package/lib/site-packages/trio/_core/_tests/test_unbounded_queue.py +154 -0
  81. package/lib/site-packages/trio/_core/_tests/test_windows.py +305 -0
  82. package/lib/site-packages/trio/_core/_tests/tutil.py +117 -0
  83. package/lib/site-packages/trio/_core/_tests/type_tests/nursery_start.py +79 -0
  84. package/lib/site-packages/trio/_core/_tests/type_tests/run.py +51 -0
  85. package/lib/site-packages/trio/_core/_thread_cache.py +317 -0
  86. package/lib/site-packages/trio/_core/_traps.py +318 -0
  87. package/lib/site-packages/trio/_core/_unbounded_queue.py +163 -0
  88. package/lib/site-packages/trio/_core/_wakeup_socketpair.py +75 -0
  89. package/lib/site-packages/trio/_core/_windows_cffi.py +313 -0
  90. package/lib/site-packages/trio/_deprecate.py +171 -0
  91. package/lib/site-packages/trio/_dtls.py +1380 -0
  92. package/lib/site-packages/trio/_file_io.py +513 -0
  93. package/lib/site-packages/trio/_highlevel_generic.py +125 -0
  94. package/lib/site-packages/trio/_highlevel_open_tcp_listeners.py +251 -0
  95. package/lib/site-packages/trio/_highlevel_open_tcp_stream.py +397 -0
  96. package/lib/site-packages/trio/_highlevel_open_unix_stream.py +65 -0
  97. package/lib/site-packages/trio/_highlevel_serve_listeners.py +148 -0
  98. package/lib/site-packages/trio/_highlevel_socket.py +423 -0
  99. package/lib/site-packages/trio/_highlevel_ssl_helpers.py +180 -0
  100. package/lib/site-packages/trio/_path.py +289 -0
  101. package/lib/site-packages/trio/_repl.py +159 -0
  102. package/lib/site-packages/trio/_signals.py +185 -0
  103. package/lib/site-packages/trio/_socket.py +1326 -0
  104. package/lib/site-packages/trio/_ssl.py +964 -0
  105. package/lib/site-packages/trio/_subprocess.py +1178 -0
  106. package/lib/site-packages/trio/_subprocess_platform/__init__.py +123 -0
  107. package/lib/site-packages/trio/_subprocess_platform/kqueue.py +48 -0
  108. package/lib/site-packages/trio/_subprocess_platform/waitid.py +113 -0
  109. package/lib/site-packages/trio/_subprocess_platform/windows.py +11 -0
  110. package/lib/site-packages/trio/_sync.py +908 -0
  111. package/lib/site-packages/trio/_tests/__init__.py +0 -0
  112. package/lib/site-packages/trio/_tests/astrill-codesigning-cert.cer +0 -0
  113. package/lib/site-packages/trio/_tests/check_type_completeness.py +247 -0
  114. package/lib/site-packages/trio/_tests/module_with_deprecations.py +22 -0
  115. package/lib/site-packages/trio/_tests/pytest_plugin.py +54 -0
  116. package/lib/site-packages/trio/_tests/test_abc.py +72 -0
  117. package/lib/site-packages/trio/_tests/test_channel.py +750 -0
  118. package/lib/site-packages/trio/_tests/test_contextvars.py +56 -0
  119. package/lib/site-packages/trio/_tests/test_deprecate.py +277 -0
  120. package/lib/site-packages/trio/_tests/test_deprecate_strict_exception_groups_false.py +64 -0
  121. package/lib/site-packages/trio/_tests/test_dtls.py +950 -0
  122. package/lib/site-packages/trio/_tests/test_exports.py +626 -0
  123. package/lib/site-packages/trio/_tests/test_fakenet.py +317 -0
  124. package/lib/site-packages/trio/_tests/test_file_io.py +269 -0
  125. package/lib/site-packages/trio/_tests/test_highlevel_generic.py +98 -0
  126. package/lib/site-packages/trio/_tests/test_highlevel_open_tcp_listeners.py +419 -0
  127. package/lib/site-packages/trio/_tests/test_highlevel_open_tcp_stream.py +693 -0
  128. package/lib/site-packages/trio/_tests/test_highlevel_open_unix_stream.py +86 -0
  129. package/lib/site-packages/trio/_tests/test_highlevel_serve_listeners.py +186 -0
  130. package/lib/site-packages/trio/_tests/test_highlevel_socket.py +336 -0
  131. package/lib/site-packages/trio/_tests/test_highlevel_ssl_helpers.py +169 -0
  132. package/lib/site-packages/trio/_tests/test_path.py +279 -0
  133. package/lib/site-packages/trio/_tests/test_repl.py +428 -0
  134. package/lib/site-packages/trio/_tests/test_scheduler_determinism.py +47 -0
  135. package/lib/site-packages/trio/_tests/test_signals.py +186 -0
  136. package/lib/site-packages/trio/_tests/test_socket.py +1253 -0
  137. package/lib/site-packages/trio/_tests/test_ssl.py +1371 -0
  138. package/lib/site-packages/trio/_tests/test_subprocess.py +767 -0
  139. package/lib/site-packages/trio/_tests/test_sync.py +735 -0
  140. package/lib/site-packages/trio/_tests/test_testing.py +682 -0
  141. package/lib/site-packages/trio/_tests/test_testing_raisesgroup.py +1128 -0
  142. package/lib/site-packages/trio/_tests/test_threads.py +1173 -0
  143. package/lib/site-packages/trio/_tests/test_timeouts.py +281 -0
  144. package/lib/site-packages/trio/_tests/test_tracing.py +88 -0
  145. package/lib/site-packages/trio/_tests/test_trio.py +8 -0
  146. package/lib/site-packages/trio/_tests/test_unix_pipes.py +288 -0
  147. package/lib/site-packages/trio/_tests/test_util.py +349 -0
  148. package/lib/site-packages/trio/_tests/test_wait_for_object.py +225 -0
  149. package/lib/site-packages/trio/_tests/test_windows_pipes.py +112 -0
  150. package/lib/site-packages/trio/_tests/tools/__init__.py +0 -0
  151. package/lib/site-packages/trio/_tests/tools/test_gen_exports.py +179 -0
  152. package/lib/site-packages/trio/_tests/tools/test_mypy_annotate.py +140 -0
  153. package/lib/site-packages/trio/_tests/tools/test_sync_requirements.py +80 -0
  154. package/lib/site-packages/trio/_tests/type_tests/check_wraps.py +9 -0
  155. package/lib/site-packages/trio/_tests/type_tests/open_memory_channel.py +4 -0
  156. package/lib/site-packages/trio/_tests/type_tests/path.py +140 -0
  157. package/lib/site-packages/trio/_tests/type_tests/subprocesses.py +23 -0
  158. package/lib/site-packages/trio/_tests/type_tests/task_status.py +29 -0
  159. package/lib/site-packages/trio/_threads.py +610 -0
  160. package/lib/site-packages/trio/_timeouts.py +197 -0
  161. package/lib/site-packages/trio/_tools/__init__.py +0 -0
  162. package/lib/site-packages/trio/_tools/gen_exports.py +401 -0
  163. package/lib/site-packages/trio/_tools/mypy_annotate.py +126 -0
  164. package/lib/site-packages/trio/_tools/sync_requirements.py +98 -0
  165. package/lib/site-packages/trio/_tools/windows_ffi_build.py +220 -0
  166. package/lib/site-packages/trio/_unix_pipes.py +197 -0
  167. package/lib/site-packages/trio/_util.py +385 -0
  168. package/lib/site-packages/trio/_version.py +3 -0
  169. package/lib/site-packages/trio/_wait_for_object.py +67 -0
  170. package/lib/site-packages/trio/_windows_pipes.py +144 -0
  171. package/lib/site-packages/trio/abc.py +23 -0
  172. package/lib/site-packages/trio/from_thread.py +13 -0
  173. package/lib/site-packages/trio/lowlevel.py +95 -0
  174. package/lib/site-packages/trio/py.typed +0 -0
  175. package/lib/site-packages/trio/socket.py +602 -0
  176. package/lib/site-packages/trio/testing/__init__.py +58 -0
  177. package/lib/site-packages/trio/testing/_check_streams.py +570 -0
  178. package/lib/site-packages/trio/testing/_checkpoints.py +69 -0
  179. package/lib/site-packages/trio/testing/_fake_net.py +584 -0
  180. package/lib/site-packages/trio/testing/_memory_streams.py +633 -0
  181. package/lib/site-packages/trio/testing/_network.py +36 -0
  182. package/lib/site-packages/trio/testing/_raises_group.py +1015 -0
  183. package/lib/site-packages/trio/testing/_sequencer.py +87 -0
  184. package/lib/site-packages/trio/testing/_trio_test.py +50 -0
  185. package/lib/site-packages/trio/to_thread.py +4 -0
  186. package/lib/site-packages/trio-0.33.0.dist-info/INSTALLER +1 -0
  187. package/lib/site-packages/trio-0.33.0.dist-info/METADATA +186 -0
  188. package/lib/site-packages/trio-0.33.0.dist-info/RECORD +156 -0
  189. package/lib/site-packages/trio-0.33.0.dist-info/REQUESTED +0 -0
  190. package/lib/site-packages/trio-0.33.0.dist-info/WHEEL +5 -0
  191. package/lib/site-packages/trio-0.33.0.dist-info/entry_points.txt +2 -0
  192. package/lib/site-packages/trio-0.33.0.dist-info/licenses/LICENSE +3 -0
  193. package/lib/site-packages/trio-0.33.0.dist-info/licenses/LICENSE.APACHE2 +202 -0
  194. package/lib/site-packages/trio-0.33.0.dist-info/licenses/LICENSE.MIT +22 -0
  195. package/lib/site-packages/trio-0.33.0.dist-info/top_level.txt +1 -0
  196. 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]