ominfra 0.0.0.dev127__py3-none-any.whl → 0.0.0.dev129__py3-none-any.whl
Sign up to get free protection for your applications and to get access to all the features.
- ominfra/deploy/_executor.py +24 -0
- ominfra/pyremote/_runcommands.py +24 -0
- ominfra/scripts/journald2aws.py +24 -0
- ominfra/scripts/supervisor.py +1320 -1225
- ominfra/supervisor/configs.py +34 -11
- ominfra/supervisor/dispatchers.py +7 -6
- ominfra/supervisor/dispatchersimpl.py +29 -22
- ominfra/supervisor/groups.py +1 -1
- ominfra/supervisor/groupsimpl.py +2 -2
- ominfra/supervisor/inject.py +22 -17
- ominfra/supervisor/io.py +82 -0
- ominfra/supervisor/main.py +6 -7
- 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} +42 -54
- ominfra/supervisor/setup.py +1 -1
- ominfra/supervisor/setupimpl.py +4 -3
- ominfra/supervisor/signals.py +56 -50
- ominfra/supervisor/spawning.py +2 -1
- ominfra/supervisor/spawningimpl.py +24 -21
- ominfra/supervisor/supervisor.py +72 -134
- ominfra/supervisor/types.py +45 -34
- 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/signals.py +60 -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.dev129.dist-info}/METADATA +3 -3
- {ominfra-0.0.0.dev127.dist-info → ominfra-0.0.0.dev129.dist-info}/RECORD +39 -33
- ominfra/supervisor/context.py +0 -84
- ominfra/supervisor/datatypes.py +0 -113
- ominfra/supervisor/utils.py +0 -206
- /ominfra/supervisor/{collections.py → utils/collections.py} +0 -0
- {ominfra-0.0.0.dev127.dist-info → ominfra-0.0.0.dev129.dist-info}/LICENSE +0 -0
- {ominfra-0.0.0.dev127.dist-info → ominfra-0.0.0.dev129.dist-info}/WHEEL +0 -0
- {ominfra-0.0.0.dev127.dist-info → ominfra-0.0.0.dev129.dist-info}/entry_points.txt +0 -0
- {ominfra-0.0.0.dev127.dist-info → ominfra-0.0.0.dev129.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
|
@@ -1,11 +1,12 @@
|
|
1
1
|
# ruff: noqa: UP006 UP007
|
2
|
-
from .collections import KeyedCollection
|
3
2
|
from .types import Dispatcher
|
4
|
-
from .types import
|
3
|
+
from .types import ProcessOutputDispatcher
|
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
|
#
|
@@ -23,10 +24,10 @@ class Dispatchers(KeyedCollection[int, Dispatcher]):
|
|
23
24
|
|
24
25
|
def remove_logs(self) -> None:
|
25
26
|
for d in self:
|
26
|
-
if isinstance(d,
|
27
|
+
if isinstance(d, ProcessOutputDispatcher):
|
27
28
|
d.remove_logs()
|
28
29
|
|
29
30
|
def reopen_logs(self) -> None:
|
30
31
|
for d in self:
|
31
|
-
if isinstance(d,
|
32
|
+
if isinstance(d, ProcessOutputDispatcher):
|
32
33
|
d.reopen_logs()
|
@@ -8,29 +8,32 @@ import typing as ta
|
|
8
8
|
from omlish.lite.logs import log
|
9
9
|
|
10
10
|
from .configs import ProcessConfig
|
11
|
+
from .configs import ServerConfig
|
11
12
|
from .events import EventCallbacks
|
12
13
|
from .events import ProcessCommunicationEvent
|
13
14
|
from .events import ProcessLogStderrEvent
|
14
15
|
from .events import ProcessLogStdoutEvent
|
15
|
-
from .types import Dispatcher
|
16
|
-
from .types import InputDispatcher
|
17
|
-
from .types import OutputDispatcher
|
18
16
|
from .types import Process
|
19
|
-
from .
|
20
|
-
from .
|
21
|
-
from .
|
22
|
-
from .utils import
|
23
|
-
from .utils import
|
24
|
-
|
25
|
-
|
26
|
-
|
17
|
+
from .types import ProcessDispatcher
|
18
|
+
from .types import ProcessInputDispatcher
|
19
|
+
from .types import ProcessOutputDispatcher
|
20
|
+
from .utils.diag import compact_traceback
|
21
|
+
from .utils.fds import read_fd
|
22
|
+
from .utils.ostypes import Fd
|
23
|
+
from .utils.strings import as_bytes
|
24
|
+
from .utils.strings import find_prefix_at_end
|
25
|
+
from .utils.strings import strip_escapes
|
26
|
+
|
27
|
+
|
28
|
+
class BaseProcessDispatcherImpl(ProcessDispatcher, abc.ABC):
|
27
29
|
def __init__(
|
28
30
|
self,
|
29
31
|
process: Process,
|
30
32
|
channel: str,
|
31
|
-
fd:
|
33
|
+
fd: Fd,
|
32
34
|
*,
|
33
35
|
event_callbacks: EventCallbacks,
|
36
|
+
server_config: ServerConfig,
|
34
37
|
) -> None:
|
35
38
|
super().__init__()
|
36
39
|
|
@@ -38,6 +41,7 @@ class BaseDispatcherImpl(Dispatcher, abc.ABC):
|
|
38
41
|
self._channel = channel # 'stderr' or 'stdout'
|
39
42
|
self._fd = fd
|
40
43
|
self._event_callbacks = event_callbacks
|
44
|
+
self._server_config = server_config
|
41
45
|
|
42
46
|
self._closed = False # True if close() has been called
|
43
47
|
|
@@ -57,7 +61,7 @@ class BaseDispatcherImpl(Dispatcher, abc.ABC):
|
|
57
61
|
return self._channel
|
58
62
|
|
59
63
|
@property
|
60
|
-
def fd(self) ->
|
64
|
+
def fd(self) -> Fd:
|
61
65
|
return self._fd
|
62
66
|
|
63
67
|
@property
|
@@ -78,7 +82,7 @@ class BaseDispatcherImpl(Dispatcher, abc.ABC):
|
|
78
82
|
self.close()
|
79
83
|
|
80
84
|
|
81
|
-
class
|
85
|
+
class ProcessOutputDispatcherImpl(BaseProcessDispatcherImpl, ProcessOutputDispatcher):
|
82
86
|
"""
|
83
87
|
Dispatcher for one channel (stdout or stderr) of one process. Serves several purposes:
|
84
88
|
|
@@ -91,15 +95,17 @@ class OutputDispatcherImpl(BaseDispatcherImpl, OutputDispatcher):
|
|
91
95
|
self,
|
92
96
|
process: Process,
|
93
97
|
event_type: ta.Type[ProcessCommunicationEvent],
|
94
|
-
fd:
|
98
|
+
fd: Fd,
|
95
99
|
*,
|
96
100
|
event_callbacks: EventCallbacks,
|
101
|
+
server_config: ServerConfig,
|
97
102
|
) -> None:
|
98
103
|
super().__init__(
|
99
104
|
process,
|
100
105
|
event_type.channel,
|
101
106
|
fd,
|
102
107
|
event_callbacks=event_callbacks,
|
108
|
+
server_config=server_config,
|
103
109
|
)
|
104
110
|
|
105
111
|
self._event_type = event_type
|
@@ -123,11 +129,10 @@ class OutputDispatcherImpl(BaseDispatcherImpl, OutputDispatcher):
|
|
123
129
|
|
124
130
|
self._main_log_level = logging.DEBUG
|
125
131
|
|
126
|
-
self._log_to_main_log =
|
132
|
+
self._log_to_main_log = self._server_config.loglevel <= self._main_log_level
|
127
133
|
|
128
|
-
|
129
|
-
self.
|
130
|
-
self._stderr_events_enabled = config.stderr.events_enabled
|
134
|
+
self._stdout_events_enabled = self._process.config.stdout.events_enabled
|
135
|
+
self._stderr_events_enabled = self._process.config.stderr.events_enabled
|
131
136
|
|
132
137
|
_child_log: ta.Optional[logging.Logger] = None # the current logger (normal_log or capture_log)
|
133
138
|
_normal_log: ta.Optional[logging.Logger] = None # the "normal" (non-capture) logger
|
@@ -198,7 +203,7 @@ class OutputDispatcherImpl(BaseDispatcherImpl, OutputDispatcher):
|
|
198
203
|
if not data:
|
199
204
|
return
|
200
205
|
|
201
|
-
if self.
|
206
|
+
if self._server_config.strip_ansi:
|
202
207
|
data = strip_escapes(as_bytes(data))
|
203
208
|
|
204
209
|
if self._child_log:
|
@@ -296,20 +301,22 @@ class OutputDispatcherImpl(BaseDispatcherImpl, OutputDispatcher):
|
|
296
301
|
self.close()
|
297
302
|
|
298
303
|
|
299
|
-
class
|
304
|
+
class ProcessInputDispatcherImpl(BaseProcessDispatcherImpl, ProcessInputDispatcher):
|
300
305
|
def __init__(
|
301
306
|
self,
|
302
307
|
process: Process,
|
303
308
|
channel: str,
|
304
|
-
fd:
|
309
|
+
fd: Fd,
|
305
310
|
*,
|
306
311
|
event_callbacks: EventCallbacks,
|
312
|
+
server_config: ServerConfig,
|
307
313
|
) -> None:
|
308
314
|
super().__init__(
|
309
315
|
process,
|
310
316
|
channel,
|
311
317
|
fd,
|
312
318
|
event_callbacks=event_callbacks,
|
319
|
+
server_config=server_config,
|
313
320
|
)
|
314
321
|
|
315
322
|
self._input_buffer = b''
|
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/groupsimpl.py
CHANGED
@@ -61,7 +61,7 @@ class ProcessGroupImpl(ProcessGroup):
|
|
61
61
|
#
|
62
62
|
|
63
63
|
def get_unstopped_processes(self) -> ta.List[Process]:
|
64
|
-
return [x for x in self if not x.
|
64
|
+
return [x for x in self if not x.state.stopped]
|
65
65
|
|
66
66
|
def stop_all(self) -> None:
|
67
67
|
processes = list(self._by_name.values())
|
@@ -69,7 +69,7 @@ class ProcessGroupImpl(ProcessGroup):
|
|
69
69
|
processes.reverse() # stop in desc priority order
|
70
70
|
|
71
71
|
for proc in processes:
|
72
|
-
state = proc.
|
72
|
+
state = proc.state
|
73
73
|
if state == ProcessState.RUNNING:
|
74
74
|
# RUNNING -> STOPPING
|
75
75
|
proc.stop()
|
ominfra/supervisor/inject.py
CHANGED
@@ -6,34 +6,35 @@ from omlish.lite.inject import InjectorBindings
|
|
6
6
|
from omlish.lite.inject import inj
|
7
7
|
|
8
8
|
from .configs import ServerConfig
|
9
|
-
from .
|
10
|
-
from .dispatchersimpl import
|
11
|
-
from .dispatchersimpl import OutputDispatcherImpl
|
9
|
+
from .dispatchersimpl import ProcessInputDispatcherImpl
|
10
|
+
from .dispatchersimpl import ProcessOutputDispatcherImpl
|
12
11
|
from .events import EventCallbacks
|
13
12
|
from .groups import ProcessGroupManager
|
14
13
|
from .groupsimpl import ProcessFactory
|
15
14
|
from .groupsimpl import ProcessGroupImpl
|
15
|
+
from .io import IoManager
|
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
|
26
|
+
from .signals import SignalHandler
|
27
27
|
from .spawningimpl import InheritedFds
|
28
|
-
from .spawningimpl import
|
29
|
-
from .spawningimpl import
|
28
|
+
from .spawningimpl import ProcessInputDispatcherFactory
|
29
|
+
from .spawningimpl import ProcessOutputDispatcherFactory
|
30
30
|
from .spawningimpl import ProcessSpawningImpl
|
31
31
|
from .supervisor import ProcessGroupFactory
|
32
|
-
from .supervisor import SignalHandler
|
33
32
|
from .supervisor import Supervisor
|
34
|
-
from .
|
33
|
+
from .supervisor import SupervisorStateManagerImpl
|
35
34
|
from .types import ServerEpoch
|
36
|
-
from .
|
35
|
+
from .types import SupervisorStateManager
|
36
|
+
from .utils.signals import SignalReceiver
|
37
|
+
from .utils.users import get_user
|
37
38
|
|
38
39
|
|
39
40
|
def bind_server(
|
@@ -52,17 +53,21 @@ def bind_server(
|
|
52
53
|
|
53
54
|
inj.bind(DaemonizeListener, array=True, to_key=Poller),
|
54
55
|
|
55
|
-
inj.bind(ServerContextImpl, singleton=True),
|
56
|
-
inj.bind(ServerContext, to_key=ServerContextImpl),
|
57
|
-
|
58
56
|
inj.bind(EventCallbacks, singleton=True),
|
59
57
|
|
60
58
|
inj.bind(SignalReceiver, singleton=True),
|
61
59
|
|
60
|
+
inj.bind(IoManager, singleton=True),
|
61
|
+
|
62
62
|
inj.bind(SignalHandler, singleton=True),
|
63
|
+
|
63
64
|
inj.bind(ProcessGroupManager, singleton=True),
|
65
|
+
|
64
66
|
inj.bind(Supervisor, singleton=True),
|
65
67
|
|
68
|
+
inj.bind(SupervisorStateManagerImpl, singleton=True),
|
69
|
+
inj.bind(SupervisorStateManager, to_key=SupervisorStateManagerImpl),
|
70
|
+
|
66
71
|
inj.bind(PidHistory()),
|
67
72
|
|
68
73
|
inj.bind_factory(ProcessGroupImpl, ProcessGroupFactory),
|
@@ -70,8 +75,8 @@ def bind_server(
|
|
70
75
|
|
71
76
|
inj.bind_factory(ProcessSpawningImpl, ProcessSpawningFactory),
|
72
77
|
|
73
|
-
inj.bind_factory(
|
74
|
-
inj.bind_factory(
|
78
|
+
inj.bind_factory(ProcessOutputDispatcherImpl, ProcessOutputDispatcherFactory),
|
79
|
+
inj.bind_factory(ProcessInputDispatcherImpl, ProcessInputDispatcherFactory),
|
75
80
|
]
|
76
81
|
|
77
82
|
#
|
ominfra/supervisor/io.py
ADDED
@@ -0,0 +1,82 @@
|
|
1
|
+
# ruff: noqa: UP006 UP007
|
2
|
+
from omlish.lite.logs import log
|
3
|
+
|
4
|
+
from .dispatchers import Dispatchers
|
5
|
+
from .groups import ProcessGroupManager
|
6
|
+
from .poller import Poller
|
7
|
+
from .types import ExitNow
|
8
|
+
|
9
|
+
|
10
|
+
##
|
11
|
+
|
12
|
+
|
13
|
+
class IoManager:
|
14
|
+
def __init__(
|
15
|
+
self,
|
16
|
+
*,
|
17
|
+
poller: Poller,
|
18
|
+
process_groups: ProcessGroupManager,
|
19
|
+
) -> None:
|
20
|
+
super().__init__()
|
21
|
+
|
22
|
+
self._poller = poller
|
23
|
+
self._process_groups = process_groups
|
24
|
+
|
25
|
+
def get_dispatchers(self) -> Dispatchers:
|
26
|
+
return Dispatchers(
|
27
|
+
d
|
28
|
+
for p in self._process_groups.all_processes()
|
29
|
+
for d in p.get_dispatchers()
|
30
|
+
)
|
31
|
+
|
32
|
+
def poll(self) -> None:
|
33
|
+
dispatchers = self.get_dispatchers()
|
34
|
+
|
35
|
+
for fd, dispatcher in dispatchers.items():
|
36
|
+
if dispatcher.readable():
|
37
|
+
self._poller.register_readable(fd)
|
38
|
+
if dispatcher.writable():
|
39
|
+
self._poller.register_writable(fd)
|
40
|
+
|
41
|
+
timeout = 1 # this cannot be fewer than the smallest TickEvent (5)
|
42
|
+
r, w = self._poller.poll(timeout)
|
43
|
+
|
44
|
+
for fd in r:
|
45
|
+
if fd in dispatchers:
|
46
|
+
try:
|
47
|
+
dispatcher = dispatchers[fd]
|
48
|
+
log.debug('read event caused by %r', dispatcher)
|
49
|
+
dispatcher.handle_read_event()
|
50
|
+
if not dispatcher.readable():
|
51
|
+
self._poller.unregister_readable(fd)
|
52
|
+
except ExitNow:
|
53
|
+
raise
|
54
|
+
except Exception: # noqa
|
55
|
+
dispatchers[fd].handle_error()
|
56
|
+
else:
|
57
|
+
# if the fd is not in combined map, we should unregister it. otherwise, it will be polled every
|
58
|
+
# time, which may cause 100% cpu usage
|
59
|
+
log.debug('unexpected read event from fd %r', fd)
|
60
|
+
try:
|
61
|
+
self._poller.unregister_readable(fd)
|
62
|
+
except Exception: # noqa
|
63
|
+
pass
|
64
|
+
|
65
|
+
for fd in w:
|
66
|
+
if fd in dispatchers:
|
67
|
+
try:
|
68
|
+
dispatcher = dispatchers[fd]
|
69
|
+
log.debug('write event caused by %r', dispatcher)
|
70
|
+
dispatcher.handle_write_event()
|
71
|
+
if not dispatcher.writable():
|
72
|
+
self._poller.unregister_writable(fd)
|
73
|
+
except ExitNow:
|
74
|
+
raise
|
75
|
+
except Exception: # noqa
|
76
|
+
dispatchers[fd].handle_error()
|
77
|
+
else:
|
78
|
+
log.debug('unexpected write event from fd %r', fd)
|
79
|
+
try:
|
80
|
+
self._poller.unregister_writable(fd)
|
81
|
+
except Exception: # noqa
|
82
|
+
pass
|
ominfra/supervisor/main.py
CHANGED
@@ -37,18 +37,18 @@ from omlish.lite.http.coroserver import CoroHttpServer
|
|
37
37
|
from omlish.lite.inject import inj
|
38
38
|
from omlish.lite.journald import journald_log_handler_factory
|
39
39
|
from omlish.lite.logs import configure_standard_logging
|
40
|
+
from omlish.lite.runtime import is_debugger_attached
|
40
41
|
|
41
42
|
from ..configs import read_config_file
|
42
43
|
from .configs import ServerConfig
|
43
44
|
from .configs import prepare_server_config
|
44
|
-
from .context import ServerContextImpl
|
45
|
-
from .context import ServerEpoch
|
46
45
|
from .inject import bind_server
|
47
46
|
from .spawningimpl import InheritedFds
|
48
47
|
from .states import SupervisorState
|
49
48
|
from .supervisor import Supervisor
|
50
|
-
from .
|
51
|
-
from .
|
49
|
+
from .types import ExitNow
|
50
|
+
from .types import ServerEpoch
|
51
|
+
from .utils.fds import get_open_fds
|
52
52
|
|
53
53
|
|
54
54
|
##
|
@@ -79,7 +79,7 @@ def main(
|
|
79
79
|
if not no_logging:
|
80
80
|
configure_standard_logging(
|
81
81
|
'INFO',
|
82
|
-
handler_factory=journald_log_handler_factory if not args.no_journald else None,
|
82
|
+
handler_factory=journald_log_handler_factory if not (args.no_journald or is_debugger_attached()) else None,
|
83
83
|
)
|
84
84
|
|
85
85
|
#
|
@@ -102,7 +102,6 @@ def main(
|
|
102
102
|
inherited_fds=inherited_fds,
|
103
103
|
))
|
104
104
|
|
105
|
-
context = injector[ServerContextImpl]
|
106
105
|
supervisor = injector[Supervisor]
|
107
106
|
|
108
107
|
try:
|
@@ -110,7 +109,7 @@ def main(
|
|
110
109
|
except ExitNow:
|
111
110
|
pass
|
112
111
|
|
113
|
-
if
|
112
|
+
if supervisor.state < SupervisorState.RESTARTING:
|
114
113
|
break
|
115
114
|
|
116
115
|
|
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'],
|