ominfra 0.0.0.dev127__py3-none-any.whl → 0.0.0.dev128__py3-none-any.whl
Sign up to get free protection for your applications and to get access to all the features.
- 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
|