Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

syscall: syscall.Read and syscall.Write do not return deadline errors with syscall.RawConn #53445

Closed
jackc opened this issue Jun 18, 2022 · 1 comment

Comments

@jackc
Copy link

jackc commented Jun 18, 2022

What version of Go are you using (go version)?

$ go version
go version go1.18.3 darwin/amd64

Does this issue reproduce with the latest release?

Yes.

What operating system and processor architecture are you using (go env)?

go env Output
$ go env
GO111MODULE=""
GOARCH="amd64"
GOBIN=""
GOCACHE="/Users/jack/Library/Caches/go-build"
GOENV="/Users/jack/Library/Application Support/go/env"
GOEXE=""
GOEXPERIMENT=""
GOFLAGS=""
GOHOSTARCH="amd64"
GOHOSTOS="darwin"
GOINSECURE=""
GOMODCACHE="/Users/jack/go/pkg/mod"
GONOPROXY=""
GONOSUMDB=""
GOOS="darwin"
GOPATH="/Users/jack/go"
GOPRIVATE=""
GOPROXY="https://proxy.golang.org,direct"
GOROOT="/usr/local/go"
GOSUMDB="sum.golang.org"
GOTMPDIR=""
GOTOOLDIR="/usr/local/go/pkg/tool/darwin_amd64"
GOVCS=""
GOVERSION="go1.18.3"
GCCGO="gccgo"
GOAMD64="v1"
AR="ar"
CC="clang"
CXX="clang++"
CGO_ENABLED="1"
GOMOD="/Users/jack/dev/go-rawconn-deadline/go.mod"
GOWORK=""
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
PKG_CONFIG="pkg-config"
GOGCCFLAGS="-fPIC -arch x86_64 -m64 -pthread -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -fdebug-prefix-map=/var/folders/49/sq09r9hs3mlgyzk8r18zswfw0000gn/T/go-build1229573827=/tmp/go-build -gno-record-gcc-switches -fno-common"

What did you do?

Establish a TCP connection and set a deadline for now. Call syscall.RawConn Read or Write.

What did you expect to see?

0 bytes read / written and some sort of error.

What did you see instead?

0 bytes read / written and no error.

The deadline works, but there is no indication to the calling code that the deadline has passed. This makes the deadline difficult to handle as loop until an error occurs will hang. It's also not clear if there are any other reasons that a 0 bytes and no error could occur.

package main

import (
	"fmt"
	"log"
	"net"
	"syscall"
	"time"
)

func main() {
	client, server, err := makeTCPConns()
	if err != nil {
		log.Fatal(err)
	}
	defer client.Close()
	defer server.Close()

	err = client.SetDeadline(time.Now())
	if err != nil {
		log.Fatal(err)
	}

	scClient, err := client.(syscall.Conn).SyscallConn()
	if err != nil {
		log.Fatal(err)
	}

	var n int
	scClient.Read(func(fd uintptr) (done bool) {
		n, err = syscall.Read(int(fd), make([]byte, 64))
		return true
	})
	fmt.Println(n, err) // => 0 <nil>

	scClient.Write(func(fd uintptr) (done bool) {
		n, err = syscall.Write(int(fd), make([]byte, 64))
		return true
	})
	fmt.Println(n, err) // => 0 <nil>

}

func makeTCPConns() (client, server net.Conn, err error) {
	ln, err := net.Listen("tcp", "127.0.0.1:0")
	if err != nil {
		return nil, nil, err
	}
	defer ln.Close()

	type acceptResultT struct {
		conn net.Conn
		err  error
	}
	acceptChan := make(chan acceptResultT)

	go func() {
		conn, err := ln.Accept()
		acceptChan <- acceptResultT{conn: conn, err: err}
	}()

	client, err = net.Dial("tcp", ln.Addr().String())
	if err != nil {
		return nil, nil, err
	}

	acceptResult := <-acceptChan
	err = acceptResult.err
	if err != nil {
		return nil, nil, err
	}

	server = acceptResult.conn

	return client, server, nil
}
@jackc
Copy link
Author

jackc commented Jun 18, 2022

My mistake. The deadline error is returned from the RawConn.Read() and RawConn.Write() not the syscall.Read() and syscall.Write().

@jackc jackc closed this as completed Jun 18, 2022
@golang golang locked and limited conversation to collaborators Jun 18, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

2 participants