ominfra 0.0.0.dev128__py3-none-any.whl → 0.0.0.dev130__py3-none-any.whl

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,13 +1,14 @@
1
1
  # ruff: noqa: UP006 UP007
2
- from .types import Dispatcher
3
- from .types import OutputDispatcher
2
+ from omlish.lite.fdio.handlers import FdIoHandler
3
+
4
+ from .types import ProcessOutputDispatcher
4
5
  from .utils.collections import KeyedCollection
5
6
  from .utils.ostypes import Fd
6
7
 
7
8
 
8
- class Dispatchers(KeyedCollection[Fd, Dispatcher]):
9
- def _key(self, v: Dispatcher) -> Fd:
10
- return v.fd
9
+ class Dispatchers(KeyedCollection[Fd, FdIoHandler]):
10
+ def _key(self, v: FdIoHandler) -> Fd:
11
+ return Fd(v.fd())
11
12
 
12
13
  #
13
14
 
@@ -16,18 +17,18 @@ class Dispatchers(KeyedCollection[Fd, Dispatcher]):
16
17
  # note that we *must* call readable() for every dispatcher, as it may have side effects for a given
17
18
  # dispatcher (eg. call handle_listener_state_change for event listener processes)
18
19
  if d.readable():
19
- d.handle_read_event()
20
+ d.on_readable()
20
21
  if d.writable():
21
- d.handle_write_event()
22
+ d.on_writable()
22
23
 
23
24
  #
24
25
 
25
26
  def remove_logs(self) -> None:
26
27
  for d in self:
27
- if isinstance(d, OutputDispatcher):
28
+ if isinstance(d, ProcessOutputDispatcher):
28
29
  d.remove_logs()
29
30
 
30
31
  def reopen_logs(self) -> None:
31
32
  for d in self:
32
- if isinstance(d, OutputDispatcher):
33
+ if isinstance(d, ProcessOutputDispatcher):
33
34
  d.reopen_logs()
@@ -8,14 +8,15 @@ 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
17
+ from .types import ProcessDispatcher
18
+ from .types import ProcessInputDispatcher
19
+ from .types import ProcessOutputDispatcher
19
20
  from .utils.diag import compact_traceback
20
21
  from .utils.fds import read_fd
21
22
  from .utils.ostypes import Fd
@@ -24,7 +25,7 @@ from .utils.strings import find_prefix_at_end
24
25
  from .utils.strings import strip_escapes
25
26
 
26
27
 
27
- class BaseDispatcherImpl(Dispatcher, abc.ABC):
28
+ class BaseProcessDispatcherImpl(ProcessDispatcher, abc.ABC):
28
29
  def __init__(
29
30
  self,
30
31
  process: Process,
@@ -32,6 +33,7 @@ class BaseDispatcherImpl(Dispatcher, abc.ABC):
32
33
  fd: Fd,
33
34
  *,
34
35
  event_callbacks: EventCallbacks,
36
+ server_config: ServerConfig,
35
37
  ) -> None:
36
38
  super().__init__()
37
39
 
@@ -39,6 +41,7 @@ class BaseDispatcherImpl(Dispatcher, abc.ABC):
39
41
  self._channel = channel # 'stderr' or 'stdout'
40
42
  self._fd = fd
41
43
  self._event_callbacks = event_callbacks
44
+ self._server_config = server_config
42
45
 
43
46
  self._closed = False # True if close() has been called
44
47
 
@@ -57,7 +60,6 @@ class BaseDispatcherImpl(Dispatcher, abc.ABC):
57
60
  def channel(self) -> str:
58
61
  return self._channel
59
62
 
60
- @property
61
63
  def fd(self) -> Fd:
62
64
  return self._fd
63
65
 
@@ -72,14 +74,14 @@ class BaseDispatcherImpl(Dispatcher, abc.ABC):
72
74
  log.debug('fd %s closed, stopped monitoring %s', self._fd, self)
73
75
  self._closed = True
74
76
 
75
- def handle_error(self) -> None:
77
+ def on_error(self, exc: ta.Optional[BaseException] = None) -> None:
76
78
  nil, t, v, tbinfo = compact_traceback()
77
79
 
78
80
  log.critical('uncaptured python exception, closing channel %s (%s:%s %s)', repr(self), t, v, tbinfo)
79
81
  self.close()
80
82
 
81
83
 
82
- class OutputDispatcherImpl(BaseDispatcherImpl, OutputDispatcher):
84
+ class ProcessOutputDispatcherImpl(BaseProcessDispatcherImpl, ProcessOutputDispatcher):
83
85
  """
84
86
  Dispatcher for one channel (stdout or stderr) of one process. Serves several purposes:
85
87
 
@@ -95,12 +97,14 @@ class OutputDispatcherImpl(BaseDispatcherImpl, OutputDispatcher):
95
97
  fd: Fd,
96
98
  *,
97
99
  event_callbacks: EventCallbacks,
100
+ server_config: ServerConfig,
98
101
  ) -> None:
99
102
  super().__init__(
100
103
  process,
101
104
  event_type.channel,
102
105
  fd,
103
106
  event_callbacks=event_callbacks,
107
+ server_config=server_config,
104
108
  )
105
109
 
106
110
  self._event_type = event_type
@@ -124,11 +128,10 @@ class OutputDispatcherImpl(BaseDispatcherImpl, OutputDispatcher):
124
128
 
125
129
  self._main_log_level = logging.DEBUG
126
130
 
127
- self._log_to_main_log = process.context.config.loglevel <= self._main_log_level
131
+ self._log_to_main_log = self._server_config.loglevel <= self._main_log_level
128
132
 
129
- config = self._process.config
130
- self._stdout_events_enabled = config.stdout.events_enabled
131
- self._stderr_events_enabled = config.stderr.events_enabled
133
+ self._stdout_events_enabled = self._process.config.stdout.events_enabled
134
+ self._stderr_events_enabled = self._process.config.stderr.events_enabled
132
135
 
133
136
  _child_log: ta.Optional[logging.Logger] = None # the current logger (normal_log or capture_log)
134
137
  _normal_log: ta.Optional[logging.Logger] = None # the "normal" (non-capture) logger
@@ -199,7 +202,7 @@ class OutputDispatcherImpl(BaseDispatcherImpl, OutputDispatcher):
199
202
  if not data:
200
203
  return
201
204
 
202
- if self._process.context.config.strip_ansi:
205
+ if self._server_config.strip_ansi:
203
206
  data = strip_escapes(as_bytes(data))
204
207
 
205
208
  if self._child_log:
@@ -287,7 +290,7 @@ class OutputDispatcherImpl(BaseDispatcherImpl, OutputDispatcher):
287
290
  return False
288
291
  return True
289
292
 
290
- def handle_read_event(self) -> None:
293
+ def on_readable(self) -> None:
291
294
  data = read_fd(self._fd)
292
295
  self._output_buffer += data
293
296
  self.record_output()
@@ -297,7 +300,7 @@ class OutputDispatcherImpl(BaseDispatcherImpl, OutputDispatcher):
297
300
  self.close()
298
301
 
299
302
 
300
- class InputDispatcherImpl(BaseDispatcherImpl, InputDispatcher):
303
+ class ProcessInputDispatcherImpl(BaseProcessDispatcherImpl, ProcessInputDispatcher):
301
304
  def __init__(
302
305
  self,
303
306
  process: Process,
@@ -305,12 +308,14 @@ class InputDispatcherImpl(BaseDispatcherImpl, InputDispatcher):
305
308
  fd: Fd,
306
309
  *,
307
310
  event_callbacks: EventCallbacks,
311
+ server_config: ServerConfig,
308
312
  ) -> None:
309
313
  super().__init__(
310
314
  process,
311
315
  channel,
312
316
  fd,
313
317
  event_callbacks=event_callbacks,
318
+ server_config=server_config,
314
319
  )
315
320
 
316
321
  self._input_buffer = b''
@@ -323,15 +328,12 @@ class InputDispatcherImpl(BaseDispatcherImpl, InputDispatcher):
323
328
  return True
324
329
  return False
325
330
 
326
- def readable(self) -> bool:
327
- return False
328
-
329
331
  def flush(self) -> None:
330
332
  # other code depends on this raising EPIPE if the pipe is closed
331
333
  sent = os.write(self._fd, as_bytes(self._input_buffer))
332
334
  self._input_buffer = self._input_buffer[sent:]
333
335
 
334
- def handle_write_event(self) -> None:
336
+ def on_writable(self) -> None:
335
337
  if self._input_buffer:
336
338
  try:
337
339
  self.flush()
@@ -2,15 +2,20 @@
2
2
  import typing as ta
3
3
 
4
4
  from .configs import ProcessGroupConfig
5
+ from .dispatchers import Dispatchers
5
6
  from .events import EventCallbacks
6
7
  from .events import ProcessGroupAddedEvent
7
8
  from .events import ProcessGroupRemovedEvent
9
+ from .types import HasDispatchers
8
10
  from .types import Process
9
11
  from .types import ProcessGroup
10
12
  from .utils.collections import KeyedCollectionAccessors
11
13
 
12
14
 
13
- class ProcessGroupManager(KeyedCollectionAccessors[str, ProcessGroup]):
15
+ class ProcessGroupManager(
16
+ KeyedCollectionAccessors[str, ProcessGroup],
17
+ HasDispatchers,
18
+ ):
14
19
  def __init__(
15
20
  self,
16
21
  *,
@@ -34,6 +39,16 @@ class ProcessGroupManager(KeyedCollectionAccessors[str, ProcessGroup]):
34
39
 
35
40
  #
36
41
 
42
+ def get_dispatchers(self) -> Dispatchers:
43
+ return Dispatchers(
44
+ d
45
+ for g in self
46
+ for p in g
47
+ for d in p.get_dispatchers()
48
+ )
49
+
50
+ #
51
+
37
52
  def add(self, group: ProcessGroup) -> None:
38
53
  if (name := group.name) in self._by_name:
39
54
  raise KeyError(f'Process group already exists: {name}')
@@ -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.get_state().stopped]
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.get_state()
72
+ state = proc.state
73
73
  if state == ProcessState.RUNNING:
74
74
  # RUNNING -> STOPPING
75
75
  proc.stop()
@@ -0,0 +1,130 @@
1
+ # ruff: noqa: U006 UP007
2
+ import json
3
+ import socket
4
+ import typing as ta
5
+
6
+ from omlish.lite.check import check_not_none
7
+ from omlish.lite.fdio.corohttp import CoroHttpServerConnectionFdIoHandler
8
+ from omlish.lite.fdio.handlers import SocketFdIoHandler
9
+ from omlish.lite.http.handlers import HttpHandler
10
+ from omlish.lite.http.handlers import HttpHandlerRequest
11
+ from omlish.lite.http.handlers import HttpHandlerResponse
12
+ from omlish.lite.json import JSON_PRETTY_KWARGS
13
+ from omlish.lite.socket import SocketAddress
14
+
15
+ from .dispatchers import Dispatchers
16
+ from .groups import ProcessGroupManager
17
+ from .types import HasDispatchers
18
+
19
+
20
+ ##
21
+
22
+
23
+ class SocketServerFdIoHandler(SocketFdIoHandler):
24
+ def __init__(
25
+ self,
26
+ addr: SocketAddress,
27
+ on_connect: ta.Callable[[socket.socket, SocketAddress], None],
28
+ ) -> None:
29
+ sock = socket.create_server(addr)
30
+ sock.setblocking(False)
31
+
32
+ super().__init__(addr, sock)
33
+
34
+ self._on_connect = on_connect
35
+
36
+ sock.listen(1)
37
+
38
+ def readable(self) -> bool:
39
+ return True
40
+
41
+ def on_readable(self) -> None:
42
+ cli_sock, cli_addr = check_not_none(self._sock).accept()
43
+ cli_sock.setblocking(False)
44
+
45
+ self._on_connect(cli_sock, cli_addr)
46
+
47
+
48
+ ##
49
+
50
+
51
+ class HttpServer(HasDispatchers):
52
+ class Address(ta.NamedTuple):
53
+ a: SocketAddress
54
+
55
+ class Handler(ta.NamedTuple):
56
+ h: HttpHandler
57
+
58
+ def __init__(
59
+ self,
60
+ handler: Handler,
61
+ addr: Address = Address(('localhost', 8000)),
62
+ ) -> None:
63
+ super().__init__()
64
+
65
+ self._handler = handler.h
66
+ self._addr = addr.a
67
+
68
+ self._server = SocketServerFdIoHandler(self._addr, self._on_connect)
69
+
70
+ self._conns: ta.List[CoroHttpServerConnectionFdIoHandler] = []
71
+
72
+ def get_dispatchers(self) -> Dispatchers:
73
+ l = []
74
+ for c in self._conns:
75
+ if not c.closed:
76
+ l.append(c)
77
+ self._conns = l
78
+ return Dispatchers([
79
+ self._server,
80
+ *l,
81
+ ])
82
+
83
+ def _on_connect(self, sock: socket.socket, addr: SocketAddress) -> None:
84
+ conn = CoroHttpServerConnectionFdIoHandler(
85
+ addr,
86
+ sock,
87
+ self._handler,
88
+ )
89
+
90
+ self._conns.append(conn)
91
+
92
+
93
+ ##
94
+
95
+
96
+ class SupervisorHttpHandler:
97
+ def __init__(
98
+ self,
99
+ *,
100
+ groups: ProcessGroupManager,
101
+ ) -> None:
102
+ super().__init__()
103
+
104
+ self._groups = groups
105
+
106
+ def handle(self, req: HttpHandlerRequest) -> HttpHandlerResponse:
107
+ dct = {
108
+ 'method': req.method,
109
+ 'path': req.path,
110
+ 'data': len(req.data or b''),
111
+ 'groups': {
112
+ g.name: {
113
+ 'processes': {
114
+ p.name: {
115
+ 'pid': p.pid,
116
+ }
117
+ for p in g
118
+ },
119
+ }
120
+ for g in self._groups
121
+ },
122
+ }
123
+
124
+ return HttpHandlerResponse(
125
+ 200,
126
+ data=json.dumps(dct, **JSON_PRETTY_KWARGS).encode('utf-8') + b'\n',
127
+ headers={
128
+ 'Content-Type': 'application/json',
129
+ },
130
+ )
@@ -1,20 +1,26 @@
1
1
  # ruff: noqa: UP006 UP007
2
+ import dataclasses as dc
2
3
  import typing as ta
3
4
 
5
+ from omlish.lite.fdio.kqueue import KqueueFdIoPoller # noqa
6
+ from omlish.lite.fdio.pollers import FdIoPoller
7
+ from omlish.lite.fdio.pollers import PollFdIoPoller # noqa
8
+ from omlish.lite.fdio.pollers import SelectFdIoPoller
4
9
  from omlish.lite.inject import InjectorBindingOrBindings
5
10
  from omlish.lite.inject import InjectorBindings
6
11
  from omlish.lite.inject import inj
7
12
 
8
13
  from .configs import ServerConfig
9
- from .context import ServerContextImpl
10
- from .dispatchersimpl import InputDispatcherImpl
11
- from .dispatchersimpl import OutputDispatcherImpl
14
+ from .dispatchersimpl import ProcessInputDispatcherImpl
15
+ from .dispatchersimpl import ProcessOutputDispatcherImpl
12
16
  from .events import EventCallbacks
13
17
  from .groups import ProcessGroupManager
14
18
  from .groupsimpl import ProcessFactory
15
19
  from .groupsimpl import ProcessGroupImpl
16
- from .poller import Poller
17
- from .poller import get_poller_impl
20
+ from .http import HttpServer
21
+ from .http import SupervisorHttpHandler
22
+ from .io import HasDispatchersList
23
+ from .io import IoManager
18
24
  from .process import PidHistory
19
25
  from .processimpl import ProcessImpl
20
26
  from .processimpl import ProcessSpawningFactory
@@ -23,19 +29,32 @@ from .setup import DaemonizeListeners
23
29
  from .setup import SupervisorUser
24
30
  from .setupimpl import SupervisorSetup
25
31
  from .setupimpl import SupervisorSetupImpl
32
+ from .signals import SignalHandler
26
33
  from .spawningimpl import InheritedFds
27
- from .spawningimpl import InputDispatcherFactory
28
- from .spawningimpl import OutputDispatcherFactory
34
+ from .spawningimpl import ProcessInputDispatcherFactory
35
+ from .spawningimpl import ProcessOutputDispatcherFactory
29
36
  from .spawningimpl import ProcessSpawningImpl
30
37
  from .supervisor import ProcessGroupFactory
31
- from .supervisor import SignalHandler
32
38
  from .supervisor import Supervisor
33
- from .types import ServerContext
39
+ from .supervisor import SupervisorStateManagerImpl
40
+ from .types import HasDispatchers
34
41
  from .types import ServerEpoch
42
+ from .types import SupervisorStateManager
35
43
  from .utils.signals import SignalReceiver
36
44
  from .utils.users import get_user
37
45
 
38
46
 
47
+ @dc.dataclass(frozen=True)
48
+ class _FdIoPollerDaemonizeListener(DaemonizeListener):
49
+ _poller: FdIoPoller
50
+
51
+ def before_daemonize(self) -> None:
52
+ self._poller.close()
53
+
54
+ def after_daemonize(self) -> None:
55
+ self._poller.reopen()
56
+
57
+
39
58
  def bind_server(
40
59
  config: ServerConfig,
41
60
  *,
@@ -45,24 +64,30 @@ def bind_server(
45
64
  lst: ta.List[InjectorBindingOrBindings] = [
46
65
  inj.bind(config),
47
66
 
67
+ inj.bind_array(DaemonizeListener),
48
68
  inj.bind_array_type(DaemonizeListener, DaemonizeListeners),
49
69
 
50
70
  inj.bind(SupervisorSetupImpl, singleton=True),
51
71
  inj.bind(SupervisorSetup, to_key=SupervisorSetupImpl),
52
72
 
53
- inj.bind(DaemonizeListener, array=True, to_key=Poller),
54
-
55
- inj.bind(ServerContextImpl, singleton=True),
56
- inj.bind(ServerContext, to_key=ServerContextImpl),
57
-
58
73
  inj.bind(EventCallbacks, singleton=True),
59
74
 
60
75
  inj.bind(SignalReceiver, singleton=True),
61
76
 
77
+ inj.bind(IoManager, singleton=True),
78
+ inj.bind_array(HasDispatchers),
79
+ inj.bind_array_type(HasDispatchers, HasDispatchersList),
80
+
62
81
  inj.bind(SignalHandler, singleton=True),
82
+
63
83
  inj.bind(ProcessGroupManager, singleton=True),
84
+ inj.bind(HasDispatchers, array=True, to_key=ProcessGroupManager),
85
+
64
86
  inj.bind(Supervisor, singleton=True),
65
87
 
88
+ inj.bind(SupervisorStateManagerImpl, singleton=True),
89
+ inj.bind(SupervisorStateManager, to_key=SupervisorStateManagerImpl),
90
+
66
91
  inj.bind(PidHistory()),
67
92
 
68
93
  inj.bind_factory(ProcessGroupImpl, ProcessGroupFactory),
@@ -70,8 +95,8 @@ def bind_server(
70
95
 
71
96
  inj.bind_factory(ProcessSpawningImpl, ProcessSpawningFactory),
72
97
 
73
- inj.bind_factory(OutputDispatcherImpl, OutputDispatcherFactory),
74
- inj.bind_factory(InputDispatcherImpl, InputDispatcherFactory),
98
+ inj.bind_factory(ProcessOutputDispatcherImpl, ProcessOutputDispatcherFactory),
99
+ inj.bind_factory(ProcessInputDispatcherImpl, ProcessInputDispatcherFactory),
75
100
  ]
76
101
 
77
102
  #
@@ -89,7 +114,26 @@ def bind_server(
89
114
 
90
115
  #
91
116
 
92
- lst.append(inj.bind(get_poller_impl(), key=Poller, singleton=True))
117
+ poller_impl = next(filter(None, [
118
+ KqueueFdIoPoller,
119
+ PollFdIoPoller,
120
+ SelectFdIoPoller,
121
+ ]))
122
+ lst.append(inj.bind(poller_impl, key=FdIoPoller, singleton=True))
123
+ inj.bind(_FdIoPollerDaemonizeListener, array=True, singleton=True)
124
+
125
+ #
126
+
127
+ def _provide_http_handler(s: SupervisorHttpHandler) -> HttpServer.Handler:
128
+ return HttpServer.Handler(s.handle)
129
+
130
+ lst.extend([
131
+ inj.bind(HttpServer, singleton=True, eager=True),
132
+ inj.bind(HasDispatchers, array=True, to_key=HttpServer),
133
+
134
+ inj.bind(SupervisorHttpHandler, singleton=True),
135
+ inj.bind(_provide_http_handler),
136
+ ])
93
137
 
94
138
  #
95
139
 
@@ -0,0 +1,97 @@
1
+ # ruff: noqa: UP006 UP007
2
+ import typing as ta
3
+
4
+ from omlish.lite.fdio.pollers import FdIoPoller
5
+ from omlish.lite.logs import log
6
+
7
+ from .dispatchers import Dispatchers
8
+ from .types import ExitNow
9
+ from .types import HasDispatchers
10
+ from .utils.ostypes import Fd
11
+
12
+
13
+ ##
14
+
15
+
16
+ HasDispatchersList = ta.NewType('HasDispatchersList', ta.Sequence[HasDispatchers])
17
+
18
+
19
+ class IoManager(HasDispatchers):
20
+ def __init__(
21
+ self,
22
+ *,
23
+ poller: FdIoPoller,
24
+ has_dispatchers_list: HasDispatchersList,
25
+ ) -> None:
26
+ super().__init__()
27
+
28
+ self._poller = poller
29
+ self._has_dispatchers_list = has_dispatchers_list
30
+
31
+ def get_dispatchers(self) -> Dispatchers:
32
+ return Dispatchers(
33
+ d
34
+ for hd in self._has_dispatchers_list
35
+ for d in hd.get_dispatchers()
36
+ )
37
+
38
+ def poll(self) -> None:
39
+ dispatchers = self.get_dispatchers()
40
+
41
+ self._poller.update(
42
+ {fd for fd, d in dispatchers.items() if d.readable()},
43
+ {fd for fd, d in dispatchers.items() if d.writable()},
44
+ )
45
+
46
+ timeout = 1 # this cannot be fewer than the smallest TickEvent (5)
47
+ log.info(f'Polling: {timeout=}') # noqa
48
+ polled = self._poller.poll(timeout)
49
+ log.info(f'Polled: {polled=}') # noqa
50
+ if polled.msg is not None:
51
+ log.error(polled.msg)
52
+ if polled.exc is not None:
53
+ log.error('Poll exception: %r', polled.exc)
54
+
55
+ for r in polled.r:
56
+ fd = Fd(r)
57
+ if fd in dispatchers:
58
+ dispatcher = dispatchers[fd]
59
+ try:
60
+ log.debug('read event caused by %r', dispatcher)
61
+ dispatcher.on_readable()
62
+ if not dispatcher.readable():
63
+ self._poller.unregister_readable(fd)
64
+ except ExitNow:
65
+ raise
66
+ except Exception as exc: # noqa
67
+ log.exception('Error in dispatcher: %r', dispatcher)
68
+ dispatcher.on_error(exc)
69
+ else:
70
+ # if the fd is not in combined map, we should unregister it. otherwise, it will be polled every
71
+ # time, which may cause 100% cpu usage
72
+ log.debug('unexpected read event from fd %r', fd)
73
+ try:
74
+ self._poller.unregister_readable(fd)
75
+ except Exception: # noqa
76
+ pass
77
+
78
+ for w in polled.w:
79
+ fd = Fd(w)
80
+ if fd in dispatchers:
81
+ dispatcher = dispatchers[fd]
82
+ try:
83
+ log.debug('write event caused by %r', dispatcher)
84
+ dispatcher.on_writable()
85
+ if not dispatcher.writable():
86
+ self._poller.unregister_writable(fd)
87
+ except ExitNow:
88
+ raise
89
+ except Exception as exc: # noqa
90
+ log.exception('Error in dispatcher: %r', dispatcher)
91
+ dispatcher.on_error(exc)
92
+ else:
93
+ log.debug('unexpected write event from fd %r', fd)
94
+ try:
95
+ self._poller.unregister_writable(fd)
96
+ except Exception: # noqa
97
+ pass
@@ -37,17 +37,17 @@ 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
- from .supervisor import ExitNow
50
48
  from .supervisor import Supervisor
49
+ from .types import ExitNow
50
+ from .types import ServerEpoch
51
51
  from .utils.fds import get_open_fds
52
52
 
53
53
 
@@ -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 context.state < SupervisorState.RESTARTING:
112
+ if supervisor.state < SupervisorState.RESTARTING:
114
113
  break
115
114
 
116
115