labstack / echo-contrib

Echo community contribution
https://echo.labstack.com
MIT License
175 stars 92 forks source link

write tcp broken pipe #118

Closed bengarrett closed 2 months ago

bengarrett commented 3 months ago

Issue Description

Hi, thanks for the great work with Echo, it's much appreciated! I seem to be suffering an random issue with the session middleware that causes an occasional critical error.

Unfortunately I can not recreate it but the error pops up on browser page loads. It may have something to do with server/client connection pools? https://dev.to/mstryoda/golang-what-is-broken-pipe-error-tcp-http-connections-and-pools-4699

1st occurrence

error: write tcp 127.0.0.1:1323->127.0.0.1:36788: write: broken pipe

2nd occurrence

error: write tcp 127.0.0.1:1323->127.0.0.1:39474: write: broken pipe

Error trace

github.com/MyApp/server/handler/app.InternalErr
    /home/ben/github/myapp/handler/app/error.go:166

github.com/MyApp/server/handler/app.Dirs.Artifact
    /home/ben/github/myapp/handler/app/dirs.go:192

github.com/MyApp/server/handler.Configuration.website.func3
    /home/ben/github/myapp/handler/router.go:208

github.com/labstack/echo/v4.(*Echo).add.func1
    /home/ben/go/pkg/mod/github.com/labstack/echo/v4@v4.12.0/echo.go:587

github.com/MyApp/server/handler.Configuration.nonce.Middleware.MiddlewareWithConfig.func1.1
    /home/ben/go/pkg/mod/github.com/labstack/echo-contrib@v0.17.1/session/session.go:73

github.com/MyApp/server/handler.Configuration.Controller.RemoveTrailingSlashWithConfig.func2.1
    /home/ben/go/pkg/mod/github.com/labstack/echo/v4@v4.12.0/middleware/slash.go:117
github.com/labstack/echo/v4/middleware.RequestLoggerConfig.ToMiddleware.func1.1
    /home/ben/go/pkg/mod/github.com/labstack/echo/v4@v4.12.0/middleware/request_logger.go:286
github.com/MyApp/server/handler.Configuration.Controller.Secure.SecureWithConfig.func4.1
    /home/ben/go/pkg/mod/github.com/labstack/echo/v4@v4.12.0/middleware/secure.go:141
github.com/labstack/echo/v4.(*Echo).ServeHTTP.func1
    /home/ben/go/pkg/mod/github.com/labstack/echo/v4@v4.12.0/echo.go:668
github.com/MyApp/server/handler.Configuration.Controller.NonWWWRedirect.NonWWWRedirectWithConfig.redirect.func6.1
    /home/ben/go/pkg/mod/github.com/labstack/echo/v4@v4.12.0/middleware/redirect.go:152
github.com/labstack/echo/v4/middleware.RewriteWithConfig.func1.1
    /home/ben/go/pkg/mod/github.com/labstack/echo/v4@v4.12.0/middleware/rewrite.go:77
github.com/labstack/echo/v4.(*Echo).ServeHTTP
    /home/ben/go/pkg/mod/github.com/labstack/echo/v4@v4.12.0/echo.go:674
net/http.serverHandler.ServeHTTP
    /usr/local/go/src/net/http/server.go:3142
net/http.(*conn).serve
    /usr/local/go/src/net/http/server.go:2044

Checklist

Working code to debug

/home/ben/github/myapp/handler/app/error.go:166

func InternalErr(c echo.Context, uri string, err error) error {
    const code = http.StatusInternalServerError
    logger := zaplog.Debug()
    if err != nil {
        logger.Error(err) # line 166
    }

/home/ben/github/myapp/handler/app/dirs.go:192

func (dir Dirs) Artifact(c echo.Context, logger *zap.SugaredLogger, readonly bool) error { 
...
    err = c.Render(http.StatusOK, name, data)
    if err != nil {
        return InternalErr(c, name, err) # line 192
    }

/home/ben/github/myapp/handler/router.go:208

    s.GET("/f/:id", func(cx echo.Context) error {
        dir.URI = cx.Param("id")
        return dir.Artifact(cx, logger, false) # line 208
    })

Version/commit

echo/v4@v4.12.0

echo-contrib@v0.17.1

aldas commented 3 months ago

This probably happens when your browser makes a request, it is still being served by the server and browser decides to abort the request by closing the connection. at that point server is at some function/method that tries to write into that connection (probably c.Render(http.StatusOK, name, data)) without knowing yet that the connection has been closed and gets that error.

bengarrett commented 3 months ago

Thanks, I guess it's best to handle the specific error.

Next time it happens I'll check the browser console log, network connections to see if it has cancelled any part of the request.

bengarrett commented 2 months ago

I managed to isolate and recreate this issue. It specifically happens when using a live reloader like Air and spamming the refresh tab button.

For anyone who searches this, handing the error using errors.Is(err, syscall.EPIPE) solved it for me.

func InternalErr(c echo.Context, uri string, err error) error {
        if errors.Is(err, syscall.EPIPE) {
        fmt.Fprintf(io.Discard, err)
        return nil
    }
    const code = http.StatusInternalServerError
    logger := zaplog.Debug()
    if err != nil {
        logger.Error(err) # line 166
    }