socketpair: directly export *net.UnixConn (and add test for that behavior)

This commit is contained in:
Christian Schwarz 2018-12-30 20:22:54 +01:00
parent 76a6c623f3
commit d281fb00e3
2 changed files with 27 additions and 19 deletions

View File

@ -1,42 +1,32 @@
package socketpair
import (
"golang.org/x/sys/unix"
"net"
"os"
"golang.org/x/sys/unix"
)
type fileConn struct {
net.Conn // net.FileConn
f *os.File
}
func (c fileConn) Close() error {
if err := c.Conn.Close(); err != nil {
return err
}
if err := c.f.Close(); err != nil {
return err
}
return nil
}
func SocketPair() (a, b net.Conn, err error) {
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.Conn, error) {
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 {
f.Close()
return nil, err
}
return fileConn{Conn: c, f: f}, nil
// 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

View File

@ -0,0 +1,18 @@
package socketpair
import (
"testing"
"github.com/stretchr/testify/assert"
)
// This is test is mostly to verify that the assumption about
// net.FileConn returning *net.UnixConn for AF_UNIX FDs works.
func TestSocketPairWorks(t *testing.T) {
assert.NotPanics(t, func() {
a, b, err := SocketPair()
assert.NoError(t, err)
a.Close()
b.Close()
})
}