From 80916dc43d2b7bda72aa92469a96945c95afdc7e Mon Sep 17 00:00:00 2001 From: Justin Israel Date: Tue, 27 Feb 2018 14:04:40 +1300 Subject: [PATCH] Fix panic stack trace being printed during recovery of broken pipe (#1089) --- recovery.go | 34 +++++++++++++++++++++++++++++----- 1 file changed, 29 insertions(+), 5 deletions(-) diff --git a/recovery.go b/recovery.go index 89b39fec..bdcea40a 100644 --- a/recovery.go +++ b/recovery.go @@ -10,8 +10,11 @@ import ( "io" "io/ioutil" "log" + "net" "net/http/httputil" + "os" "runtime" + "syscall" ) var ( @@ -35,12 +38,33 @@ func RecoveryWithWriter(out io.Writer) HandlerFunc { return func(c *Context) { defer func() { if err := recover(); err != nil { - if logger != nil { - stack := stack(3) - httprequest, _ := httputil.DumpRequest(c.Request, false) - logger.Printf("[Recovery] panic recovered:\n%s\n%s\n%s%s", string(httprequest), err, stack, reset) + // Check for a broken connection, as it is not really a + // condition that warrants a panic stack trace. + var brokenPipe bool + if ne, ok := err.(*net.OpError); ok { + if se, ok := ne.Err.(*os.SyscallError); ok { + if se.Err == syscall.EPIPE || se.Err == syscall.ECONNRESET { + brokenPipe = true + } + } + } + if logger != nil { + httprequest, _ := httputil.DumpRequest(c.Request, false) + if brokenPipe { + logger.Printf("%s\n%s%s", err, string(httprequest), reset) + } else { + logger.Printf("[Recovery] panic recovered:\n%s\n%s\n%s%s", + string(httprequest), err, stack(3), reset) + } + } + + // If the connection is dead, we can't write a status to it. + if brokenPipe { + c.Error(err.(error)) + c.Abort() + } else { + c.AbortWithStatus(500) } - c.AbortWithStatus(500) } }() c.Next()