ominfra 0.0.0.dev127__py3-none-any.whl → 0.0.0.dev128__py3-none-any.whl
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.
- ominfra/scripts/supervisor.py +723 -731
- ominfra/supervisor/configs.py +34 -11
- ominfra/supervisor/context.py +5 -9
- ominfra/supervisor/dispatchers.py +4 -3
- ominfra/supervisor/dispatchersimpl.py +10 -9
- ominfra/supervisor/groups.py +1 -1
- ominfra/supervisor/inject.py +5 -5
- ominfra/supervisor/main.py +2 -2
- ominfra/supervisor/pipes.py +15 -13
- ominfra/supervisor/poller.py +36 -35
- ominfra/supervisor/{processes.py → process.py} +2 -1
- ominfra/supervisor/{processesimpl.py → processimpl.py} +35 -40
- ominfra/supervisor/setup.py +1 -1
- ominfra/supervisor/setupimpl.py +4 -3
- ominfra/supervisor/spawning.py +2 -1
- ominfra/supervisor/spawningimpl.py +15 -12
- ominfra/supervisor/supervisor.py +16 -8
- ominfra/supervisor/types.py +7 -9
- ominfra/supervisor/utils/__init__.py +0 -0
- ominfra/supervisor/utils/diag.py +31 -0
- ominfra/supervisor/utils/fds.py +46 -0
- ominfra/supervisor/utils/fs.py +47 -0
- ominfra/supervisor/utils/os.py +45 -0
- ominfra/supervisor/utils/ostypes.py +9 -0
- ominfra/supervisor/utils/strings.py +105 -0
- ominfra/supervisor/{users.py → utils/users.py} +11 -8
- {ominfra-0.0.0.dev127.dist-info → ominfra-0.0.0.dev128.dist-info}/METADATA +3 -3
- {ominfra-0.0.0.dev127.dist-info → ominfra-0.0.0.dev128.dist-info}/RECORD +34 -29
- ominfra/supervisor/datatypes.py +0 -113
- ominfra/supervisor/utils.py +0 -206
- /ominfra/supervisor/{collections.py → utils/collections.py} +0 -0
- /ominfra/supervisor/{signals.py → utils/signals.py} +0 -0
- {ominfra-0.0.0.dev127.dist-info → ominfra-0.0.0.dev128.dist-info}/LICENSE +0 -0
- {ominfra-0.0.0.dev127.dist-info → ominfra-0.0.0.dev128.dist-info}/WHEEL +0 -0
- {ominfra-0.0.0.dev127.dist-info → ominfra-0.0.0.dev128.dist-info}/entry_points.txt +0 -0
- {ominfra-0.0.0.dev127.dist-info → ominfra-0.0.0.dev128.dist-info}/top_level.txt +0 -0
ominfra/supervisor/configs.py
CHANGED
@@ -7,11 +7,21 @@ import typing as ta
|
|
7
7
|
|
8
8
|
from ..configs import ConfigMapping
|
9
9
|
from ..configs import build_config_named_children
|
10
|
-
from .
|
11
|
-
from .
|
12
|
-
from .
|
13
|
-
from .
|
14
|
-
|
10
|
+
from .utils.fs import check_existing_dir
|
11
|
+
from .utils.fs import check_path_with_existing_dir
|
12
|
+
from .utils.strings import parse_bytes_size
|
13
|
+
from .utils.strings import parse_octal
|
14
|
+
|
15
|
+
|
16
|
+
##
|
17
|
+
|
18
|
+
|
19
|
+
class RestartWhenExitUnexpected:
|
20
|
+
pass
|
21
|
+
|
22
|
+
|
23
|
+
class RestartUnconditionally:
|
24
|
+
pass
|
15
25
|
|
16
26
|
|
17
27
|
##
|
@@ -104,12 +114,12 @@ class ServerConfig:
|
|
104
114
|
**kwargs: ta.Any,
|
105
115
|
) -> 'ServerConfig':
|
106
116
|
return cls(
|
107
|
-
umask=
|
108
|
-
directory=
|
109
|
-
logfile=
|
110
|
-
logfile_maxbytes=
|
111
|
-
loglevel=
|
112
|
-
pidfile=
|
117
|
+
umask=parse_octal(umask),
|
118
|
+
directory=check_existing_dir(directory) if directory is not None else None,
|
119
|
+
logfile=check_path_with_existing_dir(logfile),
|
120
|
+
logfile_maxbytes=parse_bytes_size(logfile_maxbytes),
|
121
|
+
loglevel=parse_logging_level(loglevel),
|
122
|
+
pidfile=check_path_with_existing_dir(pidfile),
|
113
123
|
child_logdir=child_logdir if child_logdir else tempfile.gettempdir(),
|
114
124
|
**kwargs,
|
115
125
|
)
|
@@ -129,3 +139,16 @@ def prepare_server_config(dct: ta.Mapping[str, ta.Any]) -> ta.Mapping[str, ta.An
|
|
129
139
|
group_dcts = build_config_named_children(out.get('groups'))
|
130
140
|
out['groups'] = [prepare_process_group_config(group_dct) for group_dct in group_dcts or []]
|
131
141
|
return out
|
142
|
+
|
143
|
+
|
144
|
+
##
|
145
|
+
|
146
|
+
|
147
|
+
def parse_logging_level(value: ta.Union[str, int]) -> int:
|
148
|
+
if isinstance(value, int):
|
149
|
+
return value
|
150
|
+
s = str(value).lower()
|
151
|
+
level = logging.getLevelNamesMapping().get(s.upper())
|
152
|
+
if level is None:
|
153
|
+
raise ValueError(f'bad logging level name {value!r}')
|
154
|
+
return level
|
ominfra/supervisor/context.py
CHANGED
@@ -8,10 +8,11 @@ from omlish.lite.logs import log
|
|
8
8
|
from .configs import ServerConfig
|
9
9
|
from .poller import Poller
|
10
10
|
from .states import SupervisorState
|
11
|
-
from .types import Process
|
12
11
|
from .types import ServerContext
|
13
12
|
from .types import ServerEpoch
|
14
|
-
from .utils import mktempfile
|
13
|
+
from .utils.fs import mktempfile
|
14
|
+
from .utils.ostypes import Pid
|
15
|
+
from .utils.ostypes import Rc
|
15
16
|
|
16
17
|
|
17
18
|
class ServerContextImpl(ServerContext):
|
@@ -28,7 +29,6 @@ class ServerContextImpl(ServerContext):
|
|
28
29
|
self._poller = poller
|
29
30
|
self._epoch = epoch
|
30
31
|
|
31
|
-
self._pid_history: ta.Dict[int, Process] = {}
|
32
32
|
self._state: SupervisorState = SupervisorState.RUNNING
|
33
33
|
|
34
34
|
@property
|
@@ -50,13 +50,9 @@ class ServerContextImpl(ServerContext):
|
|
50
50
|
def set_state(self, state: SupervisorState) -> None:
|
51
51
|
self._state = state
|
52
52
|
|
53
|
-
@property
|
54
|
-
def pid_history(self) -> ta.Dict[int, Process]:
|
55
|
-
return self._pid_history
|
56
|
-
|
57
53
|
#
|
58
54
|
|
59
|
-
def waitpid(self) -> ta.Tuple[ta.Optional[
|
55
|
+
def waitpid(self) -> ta.Tuple[ta.Optional[Pid], ta.Optional[Rc]]:
|
60
56
|
# Need pthread_sigmask here to avoid concurrent sigchld, but Python doesn't offer in Python < 3.4. There is
|
61
57
|
# still a race condition here; we can get a sigchld while we're sitting in the waitpid call. However, AFAICT, if
|
62
58
|
# waitpid is interrupted by SIGCHLD, as long as we call waitpid again (which happens every so often during the
|
@@ -72,7 +68,7 @@ class ServerContextImpl(ServerContext):
|
|
72
68
|
if code == errno.EINTR:
|
73
69
|
log.debug('EINTR during reap')
|
74
70
|
pid, sts = None, None
|
75
|
-
return pid, sts
|
71
|
+
return pid, sts # type: ignore
|
76
72
|
|
77
73
|
def get_auto_child_log_name(self, name: str, identifier: str, channel: str) -> str:
|
78
74
|
prefix = f'{name}-{channel}---{identifier}-'
|
@@ -1,11 +1,12 @@
|
|
1
1
|
# ruff: noqa: UP006 UP007
|
2
|
-
from .collections import KeyedCollection
|
3
2
|
from .types import Dispatcher
|
4
3
|
from .types import OutputDispatcher
|
4
|
+
from .utils.collections import KeyedCollection
|
5
|
+
from .utils.ostypes import Fd
|
5
6
|
|
6
7
|
|
7
|
-
class Dispatchers(KeyedCollection[
|
8
|
-
def _key(self, v: Dispatcher) ->
|
8
|
+
class Dispatchers(KeyedCollection[Fd, Dispatcher]):
|
9
|
+
def _key(self, v: Dispatcher) -> Fd:
|
9
10
|
return v.fd
|
10
11
|
|
11
12
|
#
|
@@ -16,11 +16,12 @@ from .types import Dispatcher
|
|
16
16
|
from .types import InputDispatcher
|
17
17
|
from .types import OutputDispatcher
|
18
18
|
from .types import Process
|
19
|
-
from .utils import
|
20
|
-
from .utils import
|
21
|
-
from .utils import
|
22
|
-
from .utils import
|
23
|
-
from .utils import
|
19
|
+
from .utils.diag import compact_traceback
|
20
|
+
from .utils.fds import read_fd
|
21
|
+
from .utils.ostypes import Fd
|
22
|
+
from .utils.strings import as_bytes
|
23
|
+
from .utils.strings import find_prefix_at_end
|
24
|
+
from .utils.strings import strip_escapes
|
24
25
|
|
25
26
|
|
26
27
|
class BaseDispatcherImpl(Dispatcher, abc.ABC):
|
@@ -28,7 +29,7 @@ class BaseDispatcherImpl(Dispatcher, abc.ABC):
|
|
28
29
|
self,
|
29
30
|
process: Process,
|
30
31
|
channel: str,
|
31
|
-
fd:
|
32
|
+
fd: Fd,
|
32
33
|
*,
|
33
34
|
event_callbacks: EventCallbacks,
|
34
35
|
) -> None:
|
@@ -57,7 +58,7 @@ class BaseDispatcherImpl(Dispatcher, abc.ABC):
|
|
57
58
|
return self._channel
|
58
59
|
|
59
60
|
@property
|
60
|
-
def fd(self) ->
|
61
|
+
def fd(self) -> Fd:
|
61
62
|
return self._fd
|
62
63
|
|
63
64
|
@property
|
@@ -91,7 +92,7 @@ class OutputDispatcherImpl(BaseDispatcherImpl, OutputDispatcher):
|
|
91
92
|
self,
|
92
93
|
process: Process,
|
93
94
|
event_type: ta.Type[ProcessCommunicationEvent],
|
94
|
-
fd:
|
95
|
+
fd: Fd,
|
95
96
|
*,
|
96
97
|
event_callbacks: EventCallbacks,
|
97
98
|
) -> None:
|
@@ -301,7 +302,7 @@ class InputDispatcherImpl(BaseDispatcherImpl, InputDispatcher):
|
|
301
302
|
self,
|
302
303
|
process: Process,
|
303
304
|
channel: str,
|
304
|
-
fd:
|
305
|
+
fd: Fd,
|
305
306
|
*,
|
306
307
|
event_callbacks: EventCallbacks,
|
307
308
|
) -> None:
|
ominfra/supervisor/groups.py
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
# ruff: noqa: UP006 UP007
|
2
2
|
import typing as ta
|
3
3
|
|
4
|
-
from .collections import KeyedCollectionAccessors
|
5
4
|
from .configs import ProcessGroupConfig
|
6
5
|
from .events import EventCallbacks
|
7
6
|
from .events import ProcessGroupAddedEvent
|
8
7
|
from .events import ProcessGroupRemovedEvent
|
9
8
|
from .types import Process
|
10
9
|
from .types import ProcessGroup
|
10
|
+
from .utils.collections import KeyedCollectionAccessors
|
11
11
|
|
12
12
|
|
13
13
|
class ProcessGroupManager(KeyedCollectionAccessors[str, ProcessGroup]):
|
ominfra/supervisor/inject.py
CHANGED
@@ -15,15 +15,14 @@ from .groupsimpl import ProcessFactory
|
|
15
15
|
from .groupsimpl import ProcessGroupImpl
|
16
16
|
from .poller import Poller
|
17
17
|
from .poller import get_poller_impl
|
18
|
-
from .
|
19
|
-
from .
|
20
|
-
from .
|
18
|
+
from .process import PidHistory
|
19
|
+
from .processimpl import ProcessImpl
|
20
|
+
from .processimpl import ProcessSpawningFactory
|
21
21
|
from .setup import DaemonizeListener
|
22
22
|
from .setup import DaemonizeListeners
|
23
23
|
from .setup import SupervisorUser
|
24
24
|
from .setupimpl import SupervisorSetup
|
25
25
|
from .setupimpl import SupervisorSetupImpl
|
26
|
-
from .signals import SignalReceiver
|
27
26
|
from .spawningimpl import InheritedFds
|
28
27
|
from .spawningimpl import InputDispatcherFactory
|
29
28
|
from .spawningimpl import OutputDispatcherFactory
|
@@ -33,7 +32,8 @@ from .supervisor import SignalHandler
|
|
33
32
|
from .supervisor import Supervisor
|
34
33
|
from .types import ServerContext
|
35
34
|
from .types import ServerEpoch
|
36
|
-
from .
|
35
|
+
from .utils.signals import SignalReceiver
|
36
|
+
from .utils.users import get_user
|
37
37
|
|
38
38
|
|
39
39
|
def bind_server(
|
ominfra/supervisor/main.py
CHANGED
@@ -46,9 +46,9 @@ from .context import ServerEpoch
|
|
46
46
|
from .inject import bind_server
|
47
47
|
from .spawningimpl import InheritedFds
|
48
48
|
from .states import SupervisorState
|
49
|
+
from .supervisor import ExitNow
|
49
50
|
from .supervisor import Supervisor
|
50
|
-
from .utils import
|
51
|
-
from .utils import get_open_fds
|
51
|
+
from .utils.fds import get_open_fds
|
52
52
|
|
53
53
|
|
54
54
|
##
|
ominfra/supervisor/pipes.py
CHANGED
@@ -4,24 +4,26 @@ import fcntl
|
|
4
4
|
import os
|
5
5
|
import typing as ta
|
6
6
|
|
7
|
-
from .utils import close_fd
|
7
|
+
from .utils.fds import close_fd
|
8
|
+
from .utils.fds import make_pipe
|
9
|
+
from .utils.ostypes import Fd
|
8
10
|
|
9
11
|
|
10
12
|
@dc.dataclass(frozen=True)
|
11
13
|
class ProcessPipes:
|
12
|
-
child_stdin: ta.Optional[
|
13
|
-
stdin: ta.Optional[
|
14
|
+
child_stdin: ta.Optional[Fd] = None
|
15
|
+
stdin: ta.Optional[Fd] = None
|
14
16
|
|
15
|
-
stdout: ta.Optional[
|
16
|
-
child_stdout: ta.Optional[
|
17
|
+
stdout: ta.Optional[Fd] = None
|
18
|
+
child_stdout: ta.Optional[Fd] = None
|
17
19
|
|
18
|
-
stderr: ta.Optional[
|
19
|
-
child_stderr: ta.Optional[
|
20
|
+
stderr: ta.Optional[Fd] = None
|
21
|
+
child_stderr: ta.Optional[Fd] = None
|
20
22
|
|
21
|
-
def child_fds(self) -> ta.List[
|
23
|
+
def child_fds(self) -> ta.List[Fd]:
|
22
24
|
return [fd for fd in [self.child_stdin, self.child_stdout, self.child_stderr] if fd is not None]
|
23
25
|
|
24
|
-
def parent_fds(self) -> ta.List[
|
26
|
+
def parent_fds(self) -> ta.List[Fd]:
|
25
27
|
return [fd for fd in [self.stdin, self.stdout, self.stderr] if fd is not None]
|
26
28
|
|
27
29
|
|
@@ -31,7 +33,7 @@ def make_process_pipes(stderr=True) -> ProcessPipes:
|
|
31
33
|
read them in the mainloop without blocking. If stderr is False, don't create a pipe for stderr.
|
32
34
|
"""
|
33
35
|
|
34
|
-
pipes: ta.Dict[str, ta.Optional[
|
36
|
+
pipes: ta.Dict[str, ta.Optional[Fd]] = {
|
35
37
|
'child_stdin': None,
|
36
38
|
'stdin': None,
|
37
39
|
|
@@ -43,11 +45,11 @@ def make_process_pipes(stderr=True) -> ProcessPipes:
|
|
43
45
|
}
|
44
46
|
|
45
47
|
try:
|
46
|
-
pipes['child_stdin'], pipes['stdin'] =
|
47
|
-
pipes['stdout'], pipes['child_stdout'] =
|
48
|
+
pipes['child_stdin'], pipes['stdin'] = make_pipe()
|
49
|
+
pipes['stdout'], pipes['child_stdout'] = make_pipe()
|
48
50
|
|
49
51
|
if stderr:
|
50
|
-
pipes['stderr'], pipes['child_stderr'] =
|
52
|
+
pipes['stderr'], pipes['child_stderr'] = make_pipe()
|
51
53
|
|
52
54
|
for fd in (
|
53
55
|
pipes['stdout'],
|
ominfra/supervisor/poller.py
CHANGED
@@ -8,6 +8,7 @@ import typing as ta
|
|
8
8
|
from omlish.lite.logs import log
|
9
9
|
|
10
10
|
from .setup import DaemonizeListener
|
11
|
+
from .utils.ostypes import Fd
|
11
12
|
|
12
13
|
|
13
14
|
class Poller(DaemonizeListener, abc.ABC):
|
@@ -15,23 +16,23 @@ class Poller(DaemonizeListener, abc.ABC):
|
|
15
16
|
super().__init__()
|
16
17
|
|
17
18
|
@abc.abstractmethod
|
18
|
-
def register_readable(self, fd:
|
19
|
+
def register_readable(self, fd: Fd) -> None:
|
19
20
|
raise NotImplementedError
|
20
21
|
|
21
22
|
@abc.abstractmethod
|
22
|
-
def register_writable(self, fd:
|
23
|
+
def register_writable(self, fd: Fd) -> None:
|
23
24
|
raise NotImplementedError
|
24
25
|
|
25
26
|
@abc.abstractmethod
|
26
|
-
def unregister_readable(self, fd:
|
27
|
+
def unregister_readable(self, fd: Fd) -> None:
|
27
28
|
raise NotImplementedError
|
28
29
|
|
29
30
|
@abc.abstractmethod
|
30
|
-
def unregister_writable(self, fd:
|
31
|
+
def unregister_writable(self, fd: Fd) -> None:
|
31
32
|
raise NotImplementedError
|
32
33
|
|
33
34
|
@abc.abstractmethod
|
34
|
-
def poll(self, timeout: ta.Optional[float]) -> ta.Tuple[ta.List[
|
35
|
+
def poll(self, timeout: ta.Optional[float]) -> ta.Tuple[ta.List[Fd], ta.List[Fd]]:
|
35
36
|
raise NotImplementedError
|
36
37
|
|
37
38
|
def before_daemonize(self) -> None: # noqa
|
@@ -48,37 +49,37 @@ class SelectPoller(Poller):
|
|
48
49
|
def __init__(self) -> None:
|
49
50
|
super().__init__()
|
50
51
|
|
51
|
-
self._readable: ta.Set[
|
52
|
-
self._writable: ta.Set[
|
52
|
+
self._readable: ta.Set[Fd] = set()
|
53
|
+
self._writable: ta.Set[Fd] = set()
|
53
54
|
|
54
|
-
def register_readable(self, fd:
|
55
|
+
def register_readable(self, fd: Fd) -> None:
|
55
56
|
self._readable.add(fd)
|
56
57
|
|
57
|
-
def register_writable(self, fd:
|
58
|
+
def register_writable(self, fd: Fd) -> None:
|
58
59
|
self._writable.add(fd)
|
59
60
|
|
60
|
-
def unregister_readable(self, fd:
|
61
|
+
def unregister_readable(self, fd: Fd) -> None:
|
61
62
|
self._readable.discard(fd)
|
62
63
|
|
63
|
-
def unregister_writable(self, fd:
|
64
|
+
def unregister_writable(self, fd: Fd) -> None:
|
64
65
|
self._writable.discard(fd)
|
65
66
|
|
66
67
|
def unregister_all(self) -> None:
|
67
68
|
self._readable.clear()
|
68
69
|
self._writable.clear()
|
69
70
|
|
70
|
-
def poll(self, timeout: ta.Optional[float]) -> ta.Tuple[ta.List[
|
71
|
+
def poll(self, timeout: ta.Optional[float]) -> ta.Tuple[ta.List[Fd], ta.List[Fd]]:
|
71
72
|
try:
|
72
73
|
r, w, x = select.select(
|
73
74
|
self._readable,
|
74
75
|
self._writable,
|
75
76
|
[], timeout,
|
76
77
|
)
|
77
|
-
except OSError as
|
78
|
-
if
|
78
|
+
except OSError as exc:
|
79
|
+
if exc.args[0] == errno.EINTR:
|
79
80
|
log.debug('EINTR encountered in poll')
|
80
81
|
return [], []
|
81
|
-
if
|
82
|
+
if exc.args[0] == errno.EBADF:
|
82
83
|
log.debug('EBADF encountered in poll')
|
83
84
|
self.unregister_all()
|
84
85
|
return [], []
|
@@ -94,30 +95,30 @@ class PollPoller(Poller):
|
|
94
95
|
super().__init__()
|
95
96
|
|
96
97
|
self._poller = select.poll()
|
97
|
-
self._readable: set[
|
98
|
-
self._writable: set[
|
98
|
+
self._readable: set[Fd] = set()
|
99
|
+
self._writable: set[Fd] = set()
|
99
100
|
|
100
|
-
def register_readable(self, fd:
|
101
|
+
def register_readable(self, fd: Fd) -> None:
|
101
102
|
self._poller.register(fd, self._READ)
|
102
103
|
self._readable.add(fd)
|
103
104
|
|
104
|
-
def register_writable(self, fd:
|
105
|
+
def register_writable(self, fd: Fd) -> None:
|
105
106
|
self._poller.register(fd, self._WRITE)
|
106
107
|
self._writable.add(fd)
|
107
108
|
|
108
|
-
def unregister_readable(self, fd:
|
109
|
+
def unregister_readable(self, fd: Fd) -> None:
|
109
110
|
self._readable.discard(fd)
|
110
111
|
self._poller.unregister(fd)
|
111
112
|
if fd in self._writable:
|
112
113
|
self._poller.register(fd, self._WRITE)
|
113
114
|
|
114
|
-
def unregister_writable(self, fd:
|
115
|
+
def unregister_writable(self, fd: Fd) -> None:
|
115
116
|
self._writable.discard(fd)
|
116
117
|
self._poller.unregister(fd)
|
117
118
|
if fd in self._readable:
|
118
119
|
self._poller.register(fd, self._READ)
|
119
120
|
|
120
|
-
def poll(self, timeout: ta.Optional[float]) -> ta.Tuple[ta.List[
|
121
|
+
def poll(self, timeout: ta.Optional[float]) -> ta.Tuple[ta.List[Fd], ta.List[Fd]]:
|
121
122
|
fds = self._poll_fds(timeout) # type: ignore
|
122
123
|
readable, writable = [], []
|
123
124
|
for fd, eventmask in fds:
|
@@ -129,16 +130,16 @@ class PollPoller(Poller):
|
|
129
130
|
writable.append(fd)
|
130
131
|
return readable, writable
|
131
132
|
|
132
|
-
def _poll_fds(self, timeout: float) -> ta.List[ta.Tuple[
|
133
|
+
def _poll_fds(self, timeout: float) -> ta.List[ta.Tuple[Fd, Fd]]:
|
133
134
|
try:
|
134
|
-
return self._poller.poll(timeout * 1000)
|
135
|
-
except OSError as
|
136
|
-
if
|
135
|
+
return self._poller.poll(timeout * 1000) # type: ignore
|
136
|
+
except OSError as exc:
|
137
|
+
if exc.args[0] == errno.EINTR:
|
137
138
|
log.debug('EINTR encountered in poll')
|
138
139
|
return []
|
139
140
|
raise
|
140
141
|
|
141
|
-
def _ignore_invalid(self, fd:
|
142
|
+
def _ignore_invalid(self, fd: Fd, eventmask: int) -> bool:
|
142
143
|
if eventmask & select.POLLNVAL:
|
143
144
|
# POLLNVAL means `fd` value is invalid, not open. When a process quits it's `fd`s are closed so there is no
|
144
145
|
# more reason to keep this `fd` registered If the process restarts it's `fd`s are registered again.
|
@@ -157,30 +158,30 @@ if sys.platform == 'darwin' or sys.platform.startswith('freebsd'):
|
|
157
158
|
super().__init__()
|
158
159
|
|
159
160
|
self._kqueue: ta.Optional[ta.Any] = select.kqueue()
|
160
|
-
self._readable: set[
|
161
|
-
self._writable: set[
|
161
|
+
self._readable: set[Fd] = set()
|
162
|
+
self._writable: set[Fd] = set()
|
162
163
|
|
163
|
-
def register_readable(self, fd:
|
164
|
+
def register_readable(self, fd: Fd) -> None:
|
164
165
|
self._readable.add(fd)
|
165
166
|
kevent = select.kevent(fd, filter=select.KQ_FILTER_READ, flags=select.KQ_EV_ADD)
|
166
167
|
self._kqueue_control(fd, kevent)
|
167
168
|
|
168
|
-
def register_writable(self, fd:
|
169
|
+
def register_writable(self, fd: Fd) -> None:
|
169
170
|
self._writable.add(fd)
|
170
171
|
kevent = select.kevent(fd, filter=select.KQ_FILTER_WRITE, flags=select.KQ_EV_ADD)
|
171
172
|
self._kqueue_control(fd, kevent)
|
172
173
|
|
173
|
-
def unregister_readable(self, fd:
|
174
|
+
def unregister_readable(self, fd: Fd) -> None:
|
174
175
|
kevent = select.kevent(fd, filter=select.KQ_FILTER_READ, flags=select.KQ_EV_DELETE)
|
175
176
|
self._readable.discard(fd)
|
176
177
|
self._kqueue_control(fd, kevent)
|
177
178
|
|
178
|
-
def unregister_writable(self, fd:
|
179
|
+
def unregister_writable(self, fd: Fd) -> None:
|
179
180
|
kevent = select.kevent(fd, filter=select.KQ_FILTER_WRITE, flags=select.KQ_EV_DELETE)
|
180
181
|
self._writable.discard(fd)
|
181
182
|
self._kqueue_control(fd, kevent)
|
182
183
|
|
183
|
-
def _kqueue_control(self, fd:
|
184
|
+
def _kqueue_control(self, fd: Fd, kevent: 'select.kevent') -> None:
|
184
185
|
try:
|
185
186
|
self._kqueue.control([kevent], 0) # type: ignore
|
186
187
|
except OSError as error:
|
@@ -189,7 +190,7 @@ if sys.platform == 'darwin' or sys.platform.startswith('freebsd'):
|
|
189
190
|
else:
|
190
191
|
raise
|
191
192
|
|
192
|
-
def poll(self, timeout: ta.Optional[float]) -> ta.Tuple[ta.List[
|
193
|
+
def poll(self, timeout: ta.Optional[float]) -> ta.Tuple[ta.List[Fd], ta.List[Fd]]:
|
193
194
|
readable, writable = [], [] # type: ignore
|
194
195
|
|
195
196
|
try:
|
@@ -2,6 +2,7 @@
|
|
2
2
|
import typing as ta
|
3
3
|
|
4
4
|
from .types import Process
|
5
|
+
from .utils.ostypes import Pid
|
5
6
|
|
6
7
|
|
7
8
|
##
|
@@ -14,5 +15,5 @@ class ProcessStateError(RuntimeError):
|
|
14
15
|
##
|
15
16
|
|
16
17
|
|
17
|
-
class PidHistory(ta.Dict[
|
18
|
+
class PidHistory(ta.Dict[Pid, Process]):
|
18
19
|
pass
|