ominfra 0.0.0.dev128__py3-none-any.whl → 0.0.0.dev130__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.
@@ -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