TUN-5837: Log panic recovery in http2 logic with debug level log

This commit is contained in:
Nuno Diegues 2022-03-04 09:31:40 +00:00
parent d17a61c15b
commit 7220c2c214
3 changed files with 16 additions and 9 deletions

View File

@ -100,7 +100,7 @@ func (c *HTTP2Connection) ServeHTTP(w http.ResponseWriter, r *http.Request) {
connType := determineHTTP2Type(r) connType := determineHTTP2Type(r)
handleMissingRequestParts(connType, r) handleMissingRequestParts(connType, r)
respWriter, err := NewHTTP2RespWriter(r, w, connType) respWriter, err := NewHTTP2RespWriter(r, w, connType, c.log)
if err != nil { if err != nil {
c.observer.log.Error().Msg(err.Error()) c.observer.log.Error().Msg(err.Error())
return return
@ -163,14 +163,16 @@ type http2RespWriter struct {
w http.ResponseWriter w http.ResponseWriter
flusher http.Flusher flusher http.Flusher
shouldFlush bool shouldFlush bool
log *zerolog.Logger
} }
func NewHTTP2RespWriter(r *http.Request, w http.ResponseWriter, connType Type) (*http2RespWriter, error) { func NewHTTP2RespWriter(r *http.Request, w http.ResponseWriter, connType Type, log *zerolog.Logger) (*http2RespWriter, error) {
flusher, isFlusher := w.(http.Flusher) flusher, isFlusher := w.(http.Flusher)
if !isFlusher { if !isFlusher {
respWriter := &http2RespWriter{ respWriter := &http2RespWriter{
r: r.Body, r: r.Body,
w: w, w: w,
log: log,
} }
respWriter.WriteErrorResponse() respWriter.WriteErrorResponse()
return nil, fmt.Errorf("%T doesn't implement http.Flusher", w) return nil, fmt.Errorf("%T doesn't implement http.Flusher", w)
@ -181,6 +183,7 @@ func NewHTTP2RespWriter(r *http.Request, w http.ResponseWriter, connType Type) (
w: w, w: w,
flusher: flusher, flusher: flusher,
shouldFlush: connType.shouldFlush(), shouldFlush: connType.shouldFlush(),
log: log,
}, nil }, nil
} }
@ -239,7 +242,7 @@ func (rp *http2RespWriter) Write(p []byte) (n int, err error) {
// Implementer of OriginClient should make sure it doesn't write to the connection after Proxy returns // Implementer of OriginClient should make sure it doesn't write to the connection after Proxy returns
// Register a recover routine just in case. // Register a recover routine just in case.
if r := recover(); r != nil { if r := recover(); r != nil {
println(fmt.Sprintf("Recover from http2 response writer panic, error %s", debug.Stack())) rp.log.Debug().Msgf("Recover from http2 response writer panic, error %s", debug.Stack())
} }
}() }()
n, err = rp.w.Write(p) n, err = rp.w.Write(p)

View File

@ -332,7 +332,8 @@ func proxyHTTP(t *testing.T, originProxy connection.OriginProxy, hostname string
require.NoError(t, err) require.NoError(t, err)
w := httptest.NewRecorder() w := httptest.NewRecorder()
respWriter, err := connection.NewHTTP2RespWriter(req, w, connection.TypeHTTP) log := zerolog.Nop()
respWriter, err := connection.NewHTTP2RespWriter(req, w, connection.TypeHTTP, &log)
require.NoError(t, err) require.NoError(t, err)
err = originProxy.ProxyHTTP(respWriter, req, false) err = originProxy.ProxyHTTP(respWriter, req, false)
@ -358,7 +359,8 @@ func proxyTCP(t *testing.T, originProxy connection.OriginProxy, originAddr strin
req, err := http.NewRequest(http.MethodGet, fmt.Sprintf("http://%s", originAddr), reqBody) req, err := http.NewRequest(http.MethodGet, fmt.Sprintf("http://%s", originAddr), reqBody)
require.NoError(t, err) require.NoError(t, err)
respWriter, err := connection.NewHTTP2RespWriter(req, w, connection.TypeTCP) log := zerolog.Nop()
respWriter, err := connection.NewHTTP2RespWriter(req, w, connection.TypeTCP, &log)
require.NoError(t, err) require.NoError(t, err)
tcpReq := &connection.TCPRequest{ tcpReq := &connection.TCPRequest{
@ -578,7 +580,8 @@ func TestPersistentConnection(t *testing.T) {
// ProxyHTTP will add Connection, Upgrade and Sec-Websocket-Version headers // ProxyHTTP will add Connection, Upgrade and Sec-Websocket-Version headers
req.Header.Add("Sec-WebSocket-Key", "dGhlIHNhbXBsZSBub25jZQ==") req.Header.Add("Sec-WebSocket-Key", "dGhlIHNhbXBsZSBub25jZQ==")
respWriter, err := connection.NewHTTP2RespWriter(req, wsRespReadWriter, connection.TypeWebsocket) log := zerolog.Nop()
respWriter, err := connection.NewHTTP2RespWriter(req, wsRespReadWriter, connection.TypeWebsocket, &log)
require.NoError(t, err) require.NoError(t, err)
err = originProxy.ProxyHTTP(respWriter, req, true) err = originProxy.ProxyHTTP(respWriter, req, true)

View File

@ -8,6 +8,7 @@ import (
"fmt" "fmt"
"io" "io"
"net/http" "net/http"
"runtime/debug"
"sync/atomic" "sync/atomic"
"time" "time"
@ -77,7 +78,7 @@ func unidirectionalStream(dst io.Writer, src io.Reader, dir string, status *bidi
// exited. In such case, we stop a possible panic from propagating upstream. // exited. In such case, we stop a possible panic from propagating upstream.
if r := recover(); r != nil { if r := recover(); r != nil {
// We handle such unexpected errors only when we detect that one side of the streaming is done. // We handle such unexpected errors only when we detect that one side of the streaming is done.
log.Debug().Msgf("Handled gracefully error %v in Streaming for %s", r, dir) log.Debug().Msgf("Gracefully handled error %v in Streaming for %s, error %s", r, dir, debug.Stack())
} }
} }
}() }()