Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
K
k3s
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Jacklull
k3s
Commits
78c02cd0
Commit
78c02cd0
authored
Jul 11, 2016
by
Daniel Smith
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Stop eating panics
parent
2906a35c
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
48 additions
and
27 deletions
+48
-27
executor_test.go
contrib/mesos/pkg/executor/executor_test.go
+2
-1
proc.go
contrib/mesos/pkg/proc/proc.go
+6
-0
handlers.go
pkg/apiserver/handlers.go
+5
-6
worker.go
pkg/kubelet/prober/worker.go
+1
-0
runtime.go
pkg/util/runtime/runtime.go
+21
-9
runtime_test.go
pkg/util/runtime/runtime_test.go
+13
-11
No files found.
contrib/mesos/pkg/executor/executor_test.go
View file @
78c02cd0
...
...
@@ -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
{})
...
...
contrib/mesos/pkg/proc/proc.go
View file @
78c02cd0
...
...
@@ -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
()
}()
...
...
pkg/apiserver/handlers.go
View file @
78c02cd0
...
...
@@ -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
,
...
...
pkg/kubelet/prober/worker.go
View file @
78c02cd0
...
...
@@ -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
)
...
...
pkg/util/runtime/runtime.go
View file @
78c02cd0
...
...
@@ -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
...
...
pkg/util/runtime/runtime_test.go
View file @
78c02cd0
...
...
@@ -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
}()
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment