ominfra 0.0.0.dev127__py3-none-any.whl → 0.0.0.dev129__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/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'],
|