Merge pull request #83373 from liggitt/automated-cherry-pick-of-#83333-upstream-release-1.14

Automated cherry pick of #83333: Don't leak a go routine on timeout

Kubernetes-commit: b1d90868ad049c8db13d4240f21e13ce3ec550a3
This commit is contained in:
Kubernetes Publisher 2019-10-09 06:55:51 -07:00
commit d62eae5221
1 changed files with 22 additions and 3 deletions

View File

@ -28,6 +28,7 @@ import (
"time" "time"
apierrors "k8s.io/apimachinery/pkg/api/errors" apierrors "k8s.io/apimachinery/pkg/api/errors"
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
"k8s.io/apiserver/pkg/endpoints/metrics" "k8s.io/apiserver/pkg/endpoints/metrics"
apirequest "k8s.io/apiserver/pkg/endpoints/request" apirequest "k8s.io/apiserver/pkg/endpoints/request"
) )
@ -92,7 +93,8 @@ func (t *timeoutHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
return return
} }
errCh := make(chan interface{}) // resultCh is used as both errCh and stopCh
resultCh := make(chan interface{})
tw := newTimeoutWriter(w) tw := newTimeoutWriter(w)
go func() { go func() {
defer func() { defer func() {
@ -103,17 +105,34 @@ func (t *timeoutHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
buf = buf[:runtime.Stack(buf, false)] buf = buf[:runtime.Stack(buf, false)]
err = fmt.Sprintf("%v\n%s", err, buf) err = fmt.Sprintf("%v\n%s", err, buf)
} }
errCh <- err resultCh <- err
}() }()
t.handler.ServeHTTP(tw, r) t.handler.ServeHTTP(tw, r)
}() }()
select { select {
case err := <-errCh: case err := <-resultCh:
if err != nil { if err != nil {
panic(err) panic(err)
} }
return return
case <-after: case <-after:
defer func() {
// resultCh needs to have a reader, since the function doing
// the work needs to send to it. This is defer'd to ensure it runs
// ever if the post timeout work itself panics.
go func() {
res := <-resultCh
if res != nil {
switch t := res.(type) {
case error:
utilruntime.HandleError(t)
default:
utilruntime.HandleError(fmt.Errorf("%v", res))
}
}
}()
}()
postTimeoutFn() postTimeoutFn()
tw.timeout(err) tw.timeout(err)
} }