mirror of
https://github.com/golang/go
synced 2024-11-23 00:30:07 -07:00
os: document and emphasize a potential misuse of File.Fd
This CL revises the document of File.Fd that explicitly points its user to runtime.SetFinalizer where contains the information that a file descriptor could be closed in a finalizer and therefore causes a failure in syscall.Write if runtime.KeepAlive is not invoked. The CL also suggests an alternative of File.Fd towards File.SyscallConn. Fixes #41505 Change-Id: I6816f0157add48b649bf1fb793cf19dcea6894b5 Reviewed-on: https://go-review.googlesource.com/c/go/+/256899 Reviewed-by: Rob Pike <r@golang.org> Trust: Ian Lance Taylor <iant@golang.org>
This commit is contained in:
parent
6f02578f9c
commit
7bb6fed9b5
@ -29,8 +29,13 @@ type file struct {
|
||||
}
|
||||
|
||||
// Fd returns the integer Plan 9 file descriptor referencing the open file.
|
||||
// The file descriptor is valid only until f.Close is called or f is garbage collected.
|
||||
// On Unix systems this will cause the SetDeadline methods to stop working.
|
||||
// If f is closed, the file descriptor becomes invalid.
|
||||
// If f is garbage collected, a finalizer may close the file descriptor,
|
||||
// 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.
|
||||
//
|
||||
// As an alternative, see the f.SyscallCon method.
|
||||
func (f *File) Fd() uintptr {
|
||||
if f == nil {
|
||||
return ^(uintptr(0))
|
||||
|
@ -62,8 +62,13 @@ type file struct {
|
||||
}
|
||||
|
||||
// Fd returns the integer Unix file descriptor referencing the open file.
|
||||
// The file descriptor is valid only until f.Close is called or f is garbage collected.
|
||||
// On Unix systems this will cause the SetDeadline methods to stop working.
|
||||
// If f is closed, the file descriptor becomes invalid.
|
||||
// If f is garbage collected, a finalizer may close the file descriptor,
|
||||
// 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.
|
||||
//
|
||||
// As an alternative, see the f.SyscallCon method.
|
||||
func (f *File) Fd() uintptr {
|
||||
if f == nil {
|
||||
return ^(uintptr(0))
|
||||
|
@ -26,8 +26,11 @@ type file struct {
|
||||
}
|
||||
|
||||
// Fd returns the Windows handle referencing the open file.
|
||||
// The handle is valid only until f.Close is called or f is garbage collected.
|
||||
// On Unix systems this will cause the SetDeadline methods to stop working.
|
||||
// If f is closed, the file descriptor becomes invalid.
|
||||
// If f is garbage collected, a finalizer may close the file descriptor,
|
||||
// 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.
|
||||
func (file *File) Fd() uintptr {
|
||||
if file == nil {
|
||||
return uintptr(syscall.InvalidHandle)
|
||||
|
@ -293,15 +293,15 @@ func runfinq() {
|
||||
// pass the object to a call of the KeepAlive function to mark the
|
||||
// last point in the function where the object must be reachable.
|
||||
//
|
||||
// For example, if p points to a struct that contains a file descriptor d,
|
||||
// and p has a finalizer that closes that file descriptor, and if the last
|
||||
// use of p in a function is a call to syscall.Write(p.d, buf, size), then
|
||||
// p may be unreachable as soon as the program enters syscall.Write. The
|
||||
// finalizer may run at that moment, closing p.d, causing syscall.Write
|
||||
// to fail because it is writing to a closed file descriptor (or, worse,
|
||||
// to an entirely different file descriptor opened by a different goroutine).
|
||||
// To avoid this problem, call runtime.KeepAlive(p) after the call to
|
||||
// syscall.Write.
|
||||
// For example, if p points to a struct, such as os.File, that contains
|
||||
// a file descriptor d, and p has a finalizer that closes that file
|
||||
// descriptor, and if the last use of p in a function is a call to
|
||||
// syscall.Write(p.d, buf, size), then p may be unreachable as soon as
|
||||
// the program enters syscall.Write. The finalizer may run at that moment,
|
||||
// closing p.d, causing syscall.Write to fail because it is writing to
|
||||
// a closed file descriptor (or, worse, to an entirely different
|
||||
// file descriptor opened by a different goroutine). To avoid this problem,
|
||||
// call runtime.KeepAlive(p) after the call to syscall.Write.
|
||||
//
|
||||
// A single goroutine runs all finalizers for a program, sequentially.
|
||||
// If a finalizer must run for a long time, it should do so by starting
|
||||
|
Loading…
Reference in New Issue
Block a user