]> Cypherpunks.ru repositories - gostls13.git/commitdiff
os: document and emphasize a potential misuse of File.Fd
authorChangkun Ou <hi@changkun.us>
Thu, 24 Sep 2020 06:57:00 +0000 (08:57 +0200)
committerRob Pike <r@golang.org>
Sun, 27 Sep 2020 02:23:55 +0000 (02:23 +0000)
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>

src/os/file_plan9.go
src/os/file_unix.go
src/os/file_windows.go
src/runtime/mfinal.go

index 043500744b11eb6942750ef29448d74404530f6a..5e0ad6820843f46e2484bff5440d8567ebde5aae 100644 (file)
@@ -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))
index dc7d868a32bed7ed672d4b0b7e55c65b46a9bd9a..c4dd4fc6a959ed00bad754ffe0ce11a4794c51ba 100644 (file)
@@ -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))
index cc695fd94c746a51d100c7771a39282bed20e840..f744a35023132c2f84e5b4774823bf674220ea43 100644 (file)
@@ -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)
index d6c85a8b939288506efc50958bd9814187c8d638..cd6196dcabd1f3032031c93759e2dd21de2c85a4 100644 (file)
@@ -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