app/vmauth: properly handle http.ErrAbortHandler panic

This panic can be raised by the reverseProxy on aborted request to the backend.
So handle it (e.g. suppress) at reverseProxy.ServeHTTP call.

Do not suppress the panic at lib/httpserver generic HTTP handler,
since it may result in an inconsistent state left after the panicking handler.

Updates https://github.com/VictoriaMetrics/VictoriaMetrics/issues/1353
This commit is contained in:
Aliaksandr Valialkin 2021-06-11 12:50:22 +03:00
parent ce10bdc82a
commit 0672cfffa2
2 changed files with 16 additions and 4 deletions

View file

@ -81,10 +81,24 @@ func requestHandler(w http.ResponseWriter, r *http.Request) bool {
return true return true
} }
r.Header.Set("vm-target-url", targetURL.String()) r.Header.Set("vm-target-url", targetURL.String())
reverseProxy.ServeHTTP(w, r) proxyRequest(w, r)
return true return true
} }
func proxyRequest(w http.ResponseWriter, r *http.Request) {
defer func() {
err := recover()
if err == nil || err == http.ErrAbortHandler {
// Suppress http.ErrAbortHandler panic.
// See https://github.com/VictoriaMetrics/VictoriaMetrics/issues/1353
return
}
// Forward other panics to the caller.
panic(err)
}()
reverseProxy.ServeHTTP(w, r)
}
var configReloadRequests = metrics.NewCounter(`vmagent_http_requests_total{path="/-/reload"}`) var configReloadRequests = metrics.NewCounter(`vmagent_http_requests_total{path="/-/reload"}`)
var reverseProxy = &httputil.ReverseProxy{ var reverseProxy = &httputil.ReverseProxy{

View file

@ -212,9 +212,7 @@ func handlerWrapper(s *server, w http.ResponseWriter, r *http.Request, rh Reques
// The following recover() code works around this by explicitly stopping the process after logging the panic. // The following recover() code works around this by explicitly stopping the process after logging the panic.
// See https://github.com/golang/go/issues/16542#issuecomment-246549902 for details. // See https://github.com/golang/go/issues/16542#issuecomment-246549902 for details.
defer func() { defer func() {
// need to check for abortHandler if err := recover(); err != nil {
// https://github.com/VictoriaMetrics/VictoriaMetrics/issues/1353
if err := recover(); err != nil && err != http.ErrAbortHandler {
buf := make([]byte, 1<<20) buf := make([]byte, 1<<20)
n := runtime.Stack(buf, false) n := runtime.Stack(buf, false)
fmt.Fprintf(os.Stderr, "panic: %v\n\n%s", err, buf[:n]) fmt.Fprintf(os.Stderr, "panic: %v\n\n%s", err, buf[:n])