mirror of
https://github.com/coredns/coredns.git
synced 2025-10-27 08:14:18 -04:00
recover from panic log including stacktrace to help finding the origin (#5392)
This commit is contained in:
@@ -28,6 +28,9 @@ type Config struct {
|
||||
// Debug controls the panic/recover mechanism that is enabled by default.
|
||||
Debug bool
|
||||
|
||||
// Stacktrace controls including stacktrace as part of log from recover mechanism, it is disabled by default.
|
||||
Stacktrace bool
|
||||
|
||||
// The transport we implement, normally just "dns" over TCP/UDP, but could be
|
||||
// DNS-over-TLS or DNS-over-gRPC.
|
||||
Transport string
|
||||
|
||||
@@ -154,6 +154,7 @@ func (h *dnsContext) MakeServers() ([]caddy.Server, error) {
|
||||
c.Plugin = c.firstConfigInBlock.Plugin
|
||||
c.ListenHosts = c.firstConfigInBlock.ListenHosts
|
||||
c.Debug = c.firstConfigInBlock.Debug
|
||||
c.Stacktrace = c.firstConfigInBlock.Stacktrace
|
||||
c.TLSConfig = c.firstConfigInBlock.TLSConfig
|
||||
}
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@ import (
|
||||
"fmt"
|
||||
"net"
|
||||
"runtime"
|
||||
"runtime/debug"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
@@ -41,6 +42,7 @@ type Server struct {
|
||||
graceTimeout time.Duration // the maximum duration of a graceful shutdown
|
||||
trace trace.Trace // the trace plugin for the server
|
||||
debug bool // disable recover()
|
||||
stacktrace bool // enable stacktrace in recover error log
|
||||
classChaos bool // allow non-INET class queries
|
||||
}
|
||||
|
||||
@@ -67,6 +69,7 @@ func NewServer(addr string, group []*Config) (*Server, error) {
|
||||
s.debug = true
|
||||
log.D.Set()
|
||||
}
|
||||
s.stacktrace = site.Stacktrace
|
||||
// set the config per zone
|
||||
s.zones[site.Zone] = site
|
||||
|
||||
@@ -213,7 +216,11 @@ func (s *Server) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Msg)
|
||||
// In case the user doesn't enable error plugin, we still
|
||||
// need to make sure that we stay alive up here
|
||||
if rec := recover(); rec != nil {
|
||||
log.Errorf("Recovered from panic in server: %q %v", s.Addr, rec)
|
||||
if s.stacktrace {
|
||||
log.Errorf("Recovered from panic in server: %q %v\n%s", s.Addr, rec, string(debug.Stack()))
|
||||
} else {
|
||||
log.Errorf("Recovered from panic in server: %q %v", s.Addr, rec)
|
||||
}
|
||||
vars.Panic.Inc()
|
||||
errorAndMetricsFunc(s.Addr, w, r, dns.RcodeServerFailure)
|
||||
}
|
||||
|
||||
@@ -26,6 +26,7 @@ func testConfig(transport string, p plugin.Handler) *Config {
|
||||
ListenHosts: []string{"127.0.0.1"},
|
||||
Port: "53",
|
||||
Debug: false,
|
||||
Stacktrace: false,
|
||||
}
|
||||
|
||||
c.AddPlugin(func(next plugin.Handler) plugin.Handler { return p })
|
||||
@@ -76,6 +77,27 @@ func TestDebug(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestStacktrace(t *testing.T) {
|
||||
configNoStacktrace, configStacktrace := testConfig("dns", testPlugin{}), testConfig("dns", testPlugin{})
|
||||
configStacktrace.Stacktrace = true
|
||||
|
||||
s1, err := NewServer("127.0.0.1:53", []*Config{configStacktrace, configStacktrace})
|
||||
if err != nil {
|
||||
t.Errorf("Expected no error for NewServer, got %s", err)
|
||||
}
|
||||
if !s1.stacktrace {
|
||||
t.Errorf("Expected stacktrace mode enabled for server s1")
|
||||
}
|
||||
|
||||
s2, err := NewServer("127.0.0.1:53", []*Config{configNoStacktrace})
|
||||
if err != nil {
|
||||
t.Errorf("Expected no error for NewServer, got %s", err)
|
||||
}
|
||||
if s2.stacktrace {
|
||||
t.Errorf("Expected stacktrace disabled for server s2")
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkCoreServeDNS(b *testing.B) {
|
||||
s, err := NewServer("127.0.0.1:53", []*Config{testConfig("dns", testPlugin{})})
|
||||
if err != nil {
|
||||
|
||||
Reference in New Issue
Block a user