zrepl/internal/util/socketpair/socketpair.go
2024-10-18 19:21:17 +02:00

40 lines
988 B
Go

package socketpair
import (
"net"
"os"
"golang.org/x/sys/unix"
)
func SocketPair() (a, b *net.UnixConn, err error) {
// don't use net.Pipe, as it doesn't implement things like lingering, which our code relies on
sockpair, err := unix.Socketpair(unix.AF_UNIX, unix.SOCK_STREAM, 0)
if err != nil {
return nil, nil, err
}
toConn := func(fd int) (*net.UnixConn, error) {
f := os.NewFile(uintptr(fd), "fileconn")
if f == nil {
panic(fd)
}
c, err := net.FileConn(f)
f.Close() // net.FileConn uses dup under the hood
if err != nil {
return nil, err
}
// strictly, the following type assertion is an implementation detail
// however, will be caught by test TestSocketPairWorks
fileConnIsUnixConn := c.(*net.UnixConn)
return fileConnIsUnixConn, nil
}
if a, err = toConn(sockpair[0]); err != nil { // shadowing
return nil, nil, err
}
if b, err = toConn(sockpair[1]); err != nil { // shadowing
a.Close()
return nil, nil, err
}
return a, b, nil
}