From eac79eb60569612eddc3fae3b39c08032dce9c24 Mon Sep 17 00:00:00 2001 From: Laurence Withers Date: Fri, 10 May 2019 13:21:22 +0100 Subject: [PATCH] Set blocking mode on hijacked fds for sendfile --- handler.go | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/handler.go b/handler.go index 13dfb78..9411793 100644 --- a/handler.go +++ b/handler.go @@ -8,6 +8,7 @@ import ( "path/filepath" "strconv" "strings" + "syscall" "time" "github.com/lwithers/htpack/packed" @@ -194,6 +195,19 @@ func (h *Handler) sendfile(w http.ResponseWriter, data *packed.FileData) { if err == nil { err = buf.Flush() } + if err == nil { + // Since we're bypassing Read / Write, there is no integration + // with Go's epoll-driven event handling for this file + // descriptor. We'll therefore get EAGAIN behaviour rather + // than blocking for Sendfile(). Work around this by setting + // the file descriptor to blocking mode; since this function + // now guarantees (via defer tcp.Close()) that the connection + // will be closed and not be passed back to Go's own event + // loop, this is safe to do. + rawsock.Control(func(outfd uintptr) { + err = syscall.SetNonblock(int(outfd), false) + }) + } if err != nil { // error only returned if the underlying connection is broken, // so there's no point calling sendfile