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

net: FileConn() and Dial() only return public net.Conn implementations #27391

Open
dfinkel opened this issue Aug 30, 2018 · 3 comments
Open

net: FileConn() and Dial() only return public net.Conn implementations #27391

dfinkel opened this issue Aug 30, 2018 · 3 comments
Labels
Documentation NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one.
Milestone

Comments

@dfinkel
Copy link
Contributor

dfinkel commented Aug 30, 2018

In Go 1.11 and 1.10, the documentation does not say anything about which implementations of net.Conn are actually returned by net.Dial() (and friends) and net.FileConn().

The current implementations of net.Dial() and net.FileConn() only return public implementations of net.Conn (or an error). Taking advantage of this by type-asserting to the actual implementation returned by these functions/methods is extremely useful. As such, it would be nice to have this behavior documented so users can rely on it.

I'll send out a CL to extend the documentation and a test or two shortly.

@gopherbot
Copy link

Change https://golang.org/cl/132437 mentions this issue: net: extend documentation for net.FileConn()

@ianlancetaylor ianlancetaylor added the NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one. label Aug 31, 2018
@ianlancetaylor ianlancetaylor added this to the Unplanned milestone Aug 31, 2018
@ianlancetaylor
Copy link
Contributor

For what kind of code does this matter?

@dfinkel
Copy link
Contributor Author

dfinkel commented Aug 31, 2018

This is particularly with unix sockets where one might want access to the non-generic Conn methods. (e.g. (*UnixConn).SetWriteBuffer()1 which isn't in the Conn interface)

My specific use-case is that I'm constructing a unix socket with syscall.SocketPair()2 to communicate data with a subprocess that's being spawned with os.Exec, and it's much nicer if my function for creating the socket can return the correct net.Conn implementation.

In this case, I'd like the documentation reflect that this will never return the "failed to type-assert back to a UnixConn" error below (with some error-checking elided for simplicity):

func SocketPair() (*os.File, *net.UnixConn, error)
	fds, _ := syscall.Socketpair(syscall.AF_UNIX, syscall.SOCK_STREAM, 0)

	// Convert these into os.files.
	var files [2]*os.File
	for i, fd := range fds {
		files[i] = os.NewFile(uintptr(fd), fmt.Sprintf("anonymous-socket-%d", i))
	}

	conn, _ := net.FileConn(files[1])

	unixConn, ok := conn.(*net.UnixConn)
	if !ok {
		for _, file := range files {
			file.Close()
		}
		return nil, nil, fmt.Errorf("failed to type-assert back to a UnixConn. conn type: %T", conn)
	}

	// Since FileConn dup'd the files[1] FD, we need to close that FD.
	// Since we never wrote to this FD closing should always succeed.
	if err := files[1].Close(); err != nil {
		// We don't want to leak an FD for every process.
		log.Panicf("Failed to close a unix FD: %s", err)
	}
	return files[0], unixConn, nil

The use-case for Dial() is less clear to me due to the presence of DialUnix(), DialTCP, etc, but it seems odd to document that the less-used FileConn won't use a random private type when Dial() doesn't document similar behavior.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Documentation NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one.
Projects
None yet
Development

No branches or pull requests

4 participants