os: further document limitations around naked file descriptors

NewFile requires the file descriptor to be either closed
through the returned File instance, or to stay valid at least
until the finalizer runs during garbage collection.

These requirements are easily violated when file descriptors
are closed via unix.Close, or when the *File returned by
NewFile is garbage collected while the underlying file descriptor is
still in use.

This commit adds further documentation for NewFile and Fd, making it
explicit that using naked file descriptors is subject to constraints
due to garbage collection of File objects.

Fixes #43863

Change-Id: I49ea1f0054eb2d2a72b616450c8e83476f4d07fb
GitHub-Last-Rev: 180d0130ae
GitHub-Pull-Request: golang/go#43867
Reviewed-on: https://go-review.googlesource.com/c/go/+/286032
Trust: Ian Lance Taylor <iant@golang.org>
Reviewed-by: Rob Pike <r@golang.org>
This commit is contained in:
Victor Michel 2021-01-24 05:53:36 +00:00 committed by Ian Lance Taylor
parent cf263e9f77
commit 1d5e14632e

View file

@ -66,6 +66,10 @@ type file struct {
// making it invalid; see runtime.SetFinalizer for more information on when
// a finalizer might be run. On Unix systems this will cause the SetDeadline
// methods to stop working.
// Because file descriptors can be reused, the returned file descriptor may
// only be closed through the Close method of f, or by its finalizer during
// garbage collection. Otherwise, during garbage collection the finalizer
// may close an unrelated file descriptor with the same (reused) number.
//
// As an alternative, see the f.SyscallConn method.
func (f *File) Fd() uintptr {
@ -90,6 +94,10 @@ func (f *File) Fd() uintptr {
// descriptor. On Unix systems, if the file descriptor is in
// non-blocking mode, NewFile will attempt to return a pollable File
// (one for which the SetDeadline methods work).
//
// After passing it to NewFile, fd may become invalid under the same
// conditions described in the comments of the Fd method, and the same
// constraints apply.
func NewFile(fd uintptr, name string) *File {
kind := kindNewFile
if nb, err := unix.IsNonblock(int(fd)); err == nil && nb {