From 067b286a2e96b6e3f2d908043fd4b13db4dd6559 Mon Sep 17 00:00:00 2001 From: Louis Thibault Date: Tue, 15 Feb 2022 18:29:38 -0500 Subject: [PATCH] Bugfix: handle non-string panic values. Fixes: https://github.com/thejerf/suture/issues/59 --- v4/events.go | 5 +++++ v4/messages.go | 6 +++--- v4/supervisor.go | 13 ++++++++++--- 3 files changed, 18 insertions(+), 6 deletions(-) diff --git a/v4/events.go b/v4/events.go index 0aa36aa..4d4ed33 100644 --- a/v4/events.go +++ b/v4/events.go @@ -19,6 +19,11 @@ type ( EventType int EventHook func(Event) + + // SprintFunc formats an arbitrary Go value into a string. + // It is used by the supervisor to format the value of a call + // to recover(). + SprintFunc func(interface{}) string ) const ( diff --git a/v4/messages.go b/v4/messages.go index 054d392..380fd6e 100644 --- a/v4/messages.go +++ b/v4/messages.go @@ -29,13 +29,13 @@ type syncSupervisor struct { func (ss syncSupervisor) isSupervisorMessage() {} -func (s *Supervisor) fail(id serviceID, panicMsg string, stacktrace []byte) { - s.control <- serviceFailed{id, panicMsg, stacktrace} +func (s *Supervisor) fail(id serviceID, panicVal interface{}, stacktrace []byte) { + s.control <- serviceFailed{id, panicVal, stacktrace} } type serviceFailed struct { id serviceID - panicMsg string + panicVal interface{} stacktrace []byte } diff --git a/v4/supervisor.go b/v4/supervisor.go index 781c347..db2f3b1 100644 --- a/v4/supervisor.go +++ b/v4/supervisor.go @@ -358,7 +358,7 @@ func (s *Supervisor) Serve(ctx context.Context) error { case m := <-s.control: switch msg := m.(type) { case serviceFailed: - s.handleFailedService(ctx, msg.id, msg.panicMsg, msg.stacktrace, true) + s.handleFailedService(ctx, msg.id, msg.panicVal, msg.stacktrace, true) case serviceEnded: _, monitored := s.services[msg.id] if monitored { @@ -507,7 +507,7 @@ func (s *Supervisor) handleFailedService(ctx context.Context, id serviceID, err CurrentFailures: s.failures, FailureThreshold: s.spec.FailureThreshold, Restarting: curState == normal, - PanicMsg: err.(string), + PanicMsg: s.spec.Sprint(err), Stacktrace: string(stacktrace), }) } else { @@ -543,7 +543,7 @@ func (s *Supervisor) runService(ctx context.Context, service Service, id service buf := make([]byte, 65535) written := runtime.Stack(buf, false) buf = buf[:written] - s.fail(id, r.(string), buf) + s.fail(id, r, buf) } }() } @@ -848,6 +848,7 @@ var ErrSupervisorNotStarted = errors.New("supervisor not started yet") // supervisor. See the New function for full documentation. type Spec struct { EventHook EventHook + Sprint SprintFunc FailureDecay float64 FailureThreshold float64 FailureBackoff time.Duration @@ -880,4 +881,10 @@ func (s *Spec) configureDefaults(supervisorName string) { log.Print(e) } } + + if s.Sprint == nil { + s.Sprint = func(v interface{}) string { + return fmt.Sprintf("%v", v) + } + } }