Skip to content

os: add a function to construct *File with non-blocking file descriptor #22939

@crvv

Description

@crvv

Change

Add a new function to construct a *File with a file descriptor, set non blocking and put it into runtime poller. A naive but working diff:

--- a/src/os/file_unix.go
+++ b/src/os/file_unix.go
@@ -74,14 +74,17 @@ func (f *File) Fd() uintptr {
 // NewFile returns a new File with the given file descriptor and
 // name. The returned value will be nil if fd is not a valid file
 // descriptor.
 func NewFile(fd uintptr, name string) *File {
        return newFile(fd, name, kindNewFile)
 }
 
+func NewFileNonBlocking(fd uintptr, name string) *File {
+       return newFile(fd, name, kindOpenFile)
+}

Benefit

With this, I can make use of the runtime poller and have SetDeadline method on custom network interfaces.
An example (on Linux):

package main

import (
	"os"
	"syscall"
	"time"
	"unsafe"
)

const IFF_TUN = 0x0001

func main() {
	f, err := syscall.Open("/dev/net/tun", os.O_RDWR, 0)
	if err != nil { panic(err) }
	fd := uintptr(f)

	var req ifreq
	req.flags = IFF_TUN
	copy(req.name[:], "tun0")
	ioctl(fd, syscall.TUNSETIFF, uintptr(unsafe.Pointer(&req)))

	conn := os.NewFileNonBlocking(fd, "tun0")

	packet := make([]byte, 2000)
	for {
		err := conn.SetDeadline(time.Now().Add(time.Second * 2))
		if err != nil { panic(err) }
		n, err := conn.Read(packet)
		if err != nil {
			println(err.Error())
		} else {
			println("read a packet with length", n)
		}
	}
}

func ioctl(fd uintptr, request uintptr, ifreq uintptr) {
	_, _, errno := syscall.Syscall(syscall.SYS_IOCTL, fd, request, ifreq)
	if errno != 0 { panic(errno) }
}

type ifreq struct {
	name  [16]byte
	flags uint16
}

Related issue

#15021
It looks like the main motivations of #15021 are runtime poller and SetDeadline.
Both of them can be solved by this very simple function.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions