Skip to content

Commit 71bf356

Browse files
committed
🍵 service: gracefully stop previously started services on error
While here, improve relevant log messages.
1 parent 7ad7226 commit 71bf356

File tree

8 files changed

+41
-29
lines changed

8 files changed

+41
-29
lines changed

api/api.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -459,5 +459,9 @@ func (s *Server) Start(ctx context.Context) error {
459459
//
460460
// Stop implements [shadowsocks.Service.Stop].
461461
func (s *Server) Stop() error {
462-
return s.server.Close()
462+
if err := s.server.Close(); err != nil {
463+
return err
464+
}
465+
s.logger.Info("Stopped API server")
466+
return nil
463467
}

cmd/shadowsocks-go/main.go

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -99,13 +99,8 @@ func main() {
9999
cancel()
100100
}()
101101

102-
if err = m.Start(ctx); err != nil {
103-
logger.Fatal("Failed to start services",
104-
zap.String("confPath", confPath),
105-
zap.Error(err),
106-
)
102+
if !m.Run(ctx) {
103+
m.Close()
104+
os.Exit(1)
107105
}
108-
109-
<-ctx.Done()
110-
m.Stop()
111106
}

service/reload_unix.go

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,15 +14,11 @@ import (
1414
)
1515

1616
type reloadNotifier struct {
17-
sigCh chan os.Signal
1817
fns []func()
18+
sigCh chan os.Signal
1919
}
2020

21-
func newReloadNotifier(logger *zap.Logger, credmgr *cred.Manager, tlsCertStore *tlscerts.Store) reloadNotifier {
22-
rn := reloadNotifier{
23-
sigCh: make(chan os.Signal, 1),
24-
}
25-
21+
func newReloadNotifier(logger *zap.Logger, credmgr *cred.Manager, tlsCertStore *tlscerts.Store) (rn reloadNotifier) {
2622
if cmsCount, cmsSeq := credmgr.Servers(); cmsCount > 0 {
2723
cms := slices.AppendSeq(make([]*cred.ManagedServer, 0, cmsCount), cmsSeq)
2824
rn.fns = append(rn.fns, func() {
@@ -57,6 +53,7 @@ func (rn *reloadNotifier) start() {
5753
if len(rn.fns) == 0 {
5854
return
5955
}
56+
rn.sigCh = make(chan os.Signal, 1)
6057
signal.Notify(rn.sigCh, syscall.SIGUSR1)
6158
go func() {
6259
for range rn.sigCh {

service/service.go

Lines changed: 26 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -288,34 +288,46 @@ type Manager struct {
288288
logger *zap.Logger
289289
}
290290

291-
// Start starts all configured services.
292-
func (m *Manager) Start(ctx context.Context) error {
291+
// Run starts all services. If any service fails to start, it stops all running services
292+
// and returns false. On success, it blocks until the context is canceled, and then stops
293+
// all services. It returns true if no errors were encountered.
294+
func (m *Manager) Run(ctx context.Context) bool {
295+
ctx, cancel := context.WithCancel(ctx)
296+
defer cancel()
297+
293298
m.notifyReload.start()
299+
300+
ok := true
301+
runningSvcs := make([]shadowsocks.Service, 0, len(m.services))
302+
294303
for _, s := range m.services {
295304
if err := s.Start(ctx); err != nil {
296-
kv := s.ZapField()
297-
return fmt.Errorf("failed to start %s=%q: %w", kv.Key, kv.String, err)
305+
m.logger.Error("Failed to start service", s.ZapField(), zap.Error(err))
306+
ok = false
307+
break
298308
}
309+
runningSvcs = append(runningSvcs, s)
299310
}
300-
return nil
301-
}
302311

303-
// Stop stops all running services.
304-
func (m *Manager) Stop() {
305-
for _, s := range m.services {
306-
kv := s.ZapField()
312+
if ok {
313+
<-ctx.Done()
314+
} else {
315+
cancel()
316+
}
317+
318+
for _, s := range runningSvcs {
307319
if err := s.Stop(); err != nil {
308-
m.logger.Warn("Failed to stop service", kv, zap.Error(err))
309-
continue
320+
m.logger.Error("Failed to stop service", s.ZapField(), zap.Error(err))
310321
}
311-
m.logger.Info("Stopped service", kv)
312322
}
323+
313324
m.notifyReload.stop()
325+
return ok
314326
}
315327

316328
// Close closes the manager.
317329
func (m *Manager) Close() {
318330
if err := m.router.Close(); err != nil {
319-
m.logger.Warn("Failed to close router", zap.Error(err))
331+
m.logger.Error("Failed to close router", zap.Error(err))
320332
}
321333
}

service/tcp.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -306,5 +306,6 @@ func (s *TCPRelay) Stop() error {
306306
}
307307
}
308308

309+
s.logger.Info("Stopped TCP relay service", zap.String("server", s.serverName))
309310
return nil
310311
}

service/udp_nat.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -652,5 +652,6 @@ func (s *UDPNATRelay) Stop() error {
652652
}
653653
}
654654

655+
s.logger.Info("Stopped UDP NAT relay service", zap.String("server", s.serverName))
655656
return nil
656657
}

service/udp_session.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -741,5 +741,6 @@ func (s *UDPSessionRelay) Stop() error {
741741
}
742742
}
743743

744+
s.logger.Info("Stopped UDP session relay service", zap.String("server", s.serverName))
744745
return nil
745746
}

service/udp_transparent_linux.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -808,5 +808,6 @@ func (s *UDPTransparentRelay) Stop() error {
808808
}
809809
}
810810

811+
s.logger.Info("Stopped UDP transparent relay service", zap.String("server", s.serverName))
811812
return nil
812813
}

0 commit comments

Comments
 (0)