@@ -30,6 +30,8 @@ type Manager struct {
3030 setupTimeout time.Duration
3131 closeTimeout time.Duration
3232 lifetime TerminationSignal
33+
34+ exitSignal chan syscall.Signal
3335}
3436
3537func NewManager (options ... managerOption ) * Manager {
@@ -43,6 +45,7 @@ func NewManager(options ...managerOption) *Manager {
4345 setupTimeout : ops .setupTimeout ,
4446 closeTimeout : ops .closeTimeout ,
4547 lifetime : ops .lifetime ,
48+ exitSignal : make (chan syscall.Signal , 1 ),
4649 }
4750}
4851
@@ -63,7 +66,7 @@ func (m *Manager) Run() syscall.Signal {
6366
6467 m .startComponents ()
6568
66- signal := m .lifetime () // Wait for the exit signal
69+ signal := m .waitForSignal () // Wait for the exit signal
6770
6871 err = m .closeComponents ()
6972 if errors .Is (err , errTimeout ) {
@@ -95,27 +98,38 @@ func (m *Manager) setupComponents() error {
9598 return nil
9699}
97100
98- // TODO: startComponents could definitely use some more love
99- // It would be great for a way for start methods to signal the manager that a start errored, this way we can make sure we close back down gracefully..
100- // Maybe something can be done with error groups?
101- //
102- // TODO: We should probably also think in some panic handling... Maybe that goes for Setup and Close aswell
103101func (m * Manager ) startComponents () {
104102 for _ , s := range m .components {
105103 startable , ok := s .Component .(startable )
106104 if ok {
107105 m .logger .Info (fmt .Sprintf ("[UnixCycle] Starting component %q" , s .name ), slog .String ("component_name" , s .name ))
108106 go func () {
107+ defer func () {
108+ if r := recover (); r != nil {
109+ m .logger .Error (fmt .Sprintf ("[UnixCycle] Panic during start for component %q: %v" , s .name , r ), slog .String ("component_name" , s .name ))
110+ m .exitSignal <- syscall .SIGABRT
111+ }
112+ }()
109113 err := startable .Start () // Blocking for go routine
110114 if err != nil {
111- //TODO: We need to signal the manager somehow that a start failed...
112115 m .logger .Error (fmt .Sprintf ("[UnixCycle] Failure during start for component %q: %v" , s .name , err ), slog .String ("component_name" , s .name ))
116+ m .exitSignal <- syscall .SIGABRT
113117 }
114118 }()
115119 }
116120 }
117121}
118122
123+ func (m * Manager ) waitForSignal () syscall.Signal {
124+ go func () {
125+ m .exitSignal <- m .lifetime ()
126+ }()
127+
128+ signal := <- m .exitSignal
129+ m .logger .Info (fmt .Sprintf ("[UnixCycle] Received signal: %v" , signal ), slog .String ("signal" , signal .String ()))
130+ return signal
131+ }
132+
119133func (m * Manager ) closeComponents () error {
120134 for _ , s := range slices .Backward (m .components ) {
121135 closable , ok := s .Component .(closable )
0 commit comments