fix: make sure to log panic in handlers (#13611)

This commit is contained in:
Klaus Post 2021-11-08 09:28:13 -08:00 committed by GitHub
parent 02bef7560f
commit d9800c8135
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -21,6 +21,7 @@ import (
"net" "net"
"net/http" "net/http"
"path" "path"
"runtime/debug"
"strings" "strings"
"sync/atomic" "sync/atomic"
"time" "time"
@ -28,7 +29,7 @@ import (
"github.com/minio/minio-go/v7/pkg/set" "github.com/minio/minio-go/v7/pkg/set"
xnet "github.com/minio/pkg/net" xnet "github.com/minio/pkg/net"
humanize "github.com/dustin/go-humanize" "github.com/dustin/go-humanize"
"github.com/minio/minio/internal/config/dns" "github.com/minio/minio/internal/config/dns"
"github.com/minio/minio/internal/crypto" "github.com/minio/minio/internal/crypto"
xhttp "github.com/minio/minio/internal/http" xhttp "github.com/minio/minio/internal/http"
@ -451,18 +452,24 @@ func addCustomHeaders(h http.Handler) http.Handler {
}) })
} }
// criticalErrorHandler handles critical server failures caused by // criticalErrorHandler handles panics and fatal errors by
// `panic(logger.ErrCritical)` as done by `logger.CriticalIf`. // `panic(logger.ErrCritical)` as done by `logger.CriticalIf`.
// //
// It should be always the first / highest HTTP handler. // It should be always the first / highest HTTP handler.
func setCriticalErrorHandler(h http.Handler) http.Handler { func setCriticalErrorHandler(h http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
defer func() { defer func() {
if err := recover(); err == logger.ErrCritical { // handle if rec := recover(); rec == logger.ErrCritical { // handle
stack := debug.Stack()
logger.Error("critical: \"%s %s\": %v\n%s", r.Method, r.URL, rec, string(stack))
writeErrorResponse(r.Context(), w, errorCodes.ToAPIErr(ErrInternalError), r.URL)
return
} else if rec != nil {
stack := debug.Stack()
logger.Error("panic: \"%s %s\": %v\n%s", r.Method, r.URL, rec, string(stack))
// Try to write an error response, upstream may not have written header.
writeErrorResponse(r.Context(), w, errorCodes.ToAPIErr(ErrInternalError), r.URL) writeErrorResponse(r.Context(), w, errorCodes.ToAPIErr(ErrInternalError), r.URL)
return return
} else if err != nil {
panic(err) // forward other panic calls
} }
}() }()
h.ServeHTTP(w, r) h.ServeHTTP(w, r)