mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-23 19:56:01 +00:00
Merge pull request #28800 from lavalamp/reallypanic
Automatic merge from submit-queue Stop eating panics Fixes #28365
This commit is contained in:
commit
aebc35a9e8
@ -381,7 +381,8 @@ func TestExecutorInitializeStaticPodsSource(t *testing.T) {
|
||||
// its state. When a Kamikaze message is received, the executor should
|
||||
// attempt suicide.
|
||||
func TestExecutorFrameworkMessage(t *testing.T) {
|
||||
// create and start executor
|
||||
// TODO(jdef): Fix the unexpected call in the mocking system.
|
||||
t.Skip("This test started failing when panic catching was disabled.")
|
||||
var (
|
||||
mockDriver = &MockExecutorDriver{}
|
||||
kubeletFinished = make(chan struct{})
|
||||
|
@ -84,6 +84,12 @@ func stateRun(ps *processState, a *scheduledAction) stateFn {
|
||||
close(a.errCh) // signal that action was scheduled
|
||||
func() {
|
||||
// we don't trust clients of this package
|
||||
defer func() {
|
||||
if x := recover(); x != nil {
|
||||
// HandleCrash has already logged this, so
|
||||
// nothing to do.
|
||||
}
|
||||
}()
|
||||
defer runtime.HandleCrash()
|
||||
a.action()
|
||||
}()
|
||||
|
@ -35,6 +35,7 @@ import (
|
||||
"k8s.io/kubernetes/pkg/auth/user"
|
||||
"k8s.io/kubernetes/pkg/httplog"
|
||||
"k8s.io/kubernetes/pkg/serviceaccount"
|
||||
"k8s.io/kubernetes/pkg/util/runtime"
|
||||
"k8s.io/kubernetes/pkg/util/sets"
|
||||
)
|
||||
|
||||
@ -137,12 +138,10 @@ func tooManyRequests(req *http.Request, w http.ResponseWriter) {
|
||||
// RecoverPanics wraps an http Handler to recover and log panics.
|
||||
func RecoverPanics(handler http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
|
||||
defer func() {
|
||||
if x := recover(); x != nil {
|
||||
http.Error(w, "apis panic. Look in log for details.", http.StatusInternalServerError)
|
||||
glog.Errorf("APIServer panic'd on %v %v: %v\n%s\n", req.Method, req.RequestURI, x, debug.Stack())
|
||||
}
|
||||
}()
|
||||
defer runtime.HandleCrash(func(err interface{}) {
|
||||
http.Error(w, "This request caused apisever to panic. Look in log for details.", http.StatusInternalServerError)
|
||||
glog.Errorf("APIServer panic'd on %v %v: %v\n%s\n", req.Method, req.RequestURI, err, debug.Stack())
|
||||
})
|
||||
defer httplog.NewLogged(req, &w).StacktraceWhen(
|
||||
httplog.StatusIsNot(
|
||||
http.StatusOK,
|
||||
|
@ -138,6 +138,7 @@ func (w *worker) stop() {
|
||||
// doProbe probes the container once and records the result.
|
||||
// Returns whether the worker should continue.
|
||||
func (w *worker) doProbe() (keepGoing bool) {
|
||||
defer func() { recover() }() // Actually eat panics (HandleCrash takes care of logging)
|
||||
defer runtime.HandleCrash(func(_ interface{}) { keepGoing = true })
|
||||
|
||||
status, ok := w.probeManager.statusManager.GetPodStatus(w.pod.UID)
|
||||
|
@ -22,19 +22,27 @@ import (
|
||||
"runtime"
|
||||
)
|
||||
|
||||
// For testing, bypass HandleCrash.
|
||||
var ReallyCrash bool
|
||||
var (
|
||||
// ReallyCrash controls the behavior of HandleCrash and now defaults
|
||||
// true. It's still exposed so components can optionally set to false
|
||||
// to restore prior behavior.
|
||||
ReallyCrash = true
|
||||
)
|
||||
|
||||
// PanicHandlers is a list of functions which will be invoked when a panic happens.
|
||||
var PanicHandlers = []func(interface{}){logPanic}
|
||||
|
||||
//TODO search the public functions
|
||||
// HandleCrash simply catches a crash and logs an error. Meant to be called via defer.
|
||||
// Additional context-specific handlers can be provided, and will be called in case of panic
|
||||
// HandleCrash simply catches a crash and logs an error. Meant to be called via
|
||||
// defer. Additional context-specific handlers can be provided, and will be
|
||||
// called in case of panic. HandleCrash actually crashes, after calling the
|
||||
// handlers and logging the panic message.
|
||||
//
|
||||
// TODO: remove this function. We are switching to a world where it's safe for
|
||||
// apiserver to panic, since it will be restarted by kubelet. At the beginning
|
||||
// of the Kubernetes project, nothing was going to restart apiserver and so
|
||||
// catching panics was important. But it's actually much simpler for montoring
|
||||
// software if we just exit when an unexpected panic happens.
|
||||
func HandleCrash(additionalHandlers ...func(interface{})) {
|
||||
if ReallyCrash {
|
||||
return
|
||||
}
|
||||
if r := recover(); r != nil {
|
||||
for _, fn := range PanicHandlers {
|
||||
fn(r)
|
||||
@ -42,6 +50,10 @@ func HandleCrash(additionalHandlers ...func(interface{})) {
|
||||
for _, fn := range additionalHandlers {
|
||||
fn(r)
|
||||
}
|
||||
if ReallyCrash {
|
||||
// Actually proceed to panic.
|
||||
panic(r)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -55,7 +67,7 @@ func logPanic(r interface{}) {
|
||||
}
|
||||
callers = callers + fmt.Sprintf("%v:%v\n", file, line)
|
||||
}
|
||||
glog.Errorf("Recovered from panic: %#v (%v)\n%v", r, r, callers)
|
||||
glog.Errorf("Observed a panic: %#v (%v)\n%v", r, r, callers)
|
||||
}
|
||||
|
||||
// ErrorHandlers is a list of functions which will be invoked when an unreturnable
|
||||
|
@ -22,19 +22,15 @@ import (
|
||||
)
|
||||
|
||||
func TestHandleCrash(t *testing.T) {
|
||||
count := 0
|
||||
expect := 10
|
||||
for i := 0; i < expect; i = i + 1 {
|
||||
defer HandleCrash()
|
||||
if i%2 == 0 {
|
||||
panic("Test Panic")
|
||||
defer func() {
|
||||
if x := recover(); x == nil {
|
||||
t.Errorf("Expected a panic to recover from")
|
||||
}
|
||||
count = count + 1
|
||||
}
|
||||
if count != expect {
|
||||
t.Errorf("Expected %d iterations, found %d", expect, count)
|
||||
}
|
||||
}()
|
||||
defer HandleCrash()
|
||||
panic("Test Panic")
|
||||
}
|
||||
|
||||
func TestCustomHandleCrash(t *testing.T) {
|
||||
old := PanicHandlers
|
||||
defer func() { PanicHandlers = old }()
|
||||
@ -45,6 +41,11 @@ func TestCustomHandleCrash(t *testing.T) {
|
||||
},
|
||||
}
|
||||
func() {
|
||||
defer func() {
|
||||
if x := recover(); x == nil {
|
||||
t.Errorf("Expected a panic to recover from")
|
||||
}
|
||||
}()
|
||||
defer HandleCrash()
|
||||
panic("test")
|
||||
}()
|
||||
@ -52,6 +53,7 @@ func TestCustomHandleCrash(t *testing.T) {
|
||||
t.Errorf("did not receive custom handler")
|
||||
}
|
||||
}
|
||||
|
||||
func TestCustomHandleError(t *testing.T) {
|
||||
old := ErrorHandlers
|
||||
defer func() { ErrorHandlers = old }()
|
||||
|
Loading…
Reference in New Issue
Block a user