Set blocking mode on hijacked fds for sendfile

This commit is contained in:
Laurence Withers 2019-05-10 13:21:22 +01:00
parent 21a18eced6
commit eac79eb605
1 changed files with 14 additions and 0 deletions

View File

@ -8,6 +8,7 @@ import (
"path/filepath" "path/filepath"
"strconv" "strconv"
"strings" "strings"
"syscall"
"time" "time"
"github.com/lwithers/htpack/packed" "github.com/lwithers/htpack/packed"
@ -194,6 +195,19 @@ func (h *Handler) sendfile(w http.ResponseWriter, data *packed.FileData) {
if err == nil { if err == nil {
err = buf.Flush() 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 { if err != nil {
// error only returned if the underlying connection is broken, // error only returned if the underlying connection is broken,
// so there's no point calling sendfile // so there's no point calling sendfile