@@ -22,6 +22,7 @@ func fixLongPath(path string) string {
22
22
// can overwrite this data, which could cause the finalizer
23
23
// to close the wrong file descriptor.
24
24
type file struct {
25
+ fdmu poll.FDMutex
25
26
fd int
26
27
name string
27
28
dirinfo * dirInfo // nil unless directory being read
@@ -142,24 +143,35 @@ func openFileNolog(name string, flag int, perm FileMode) (*File, error) {
142
143
// be canceled and return immediately with an ErrClosed error.
143
144
// Close will return an error if it has already been called.
144
145
func (f * File ) Close () error {
145
- if err := f . checkValid ( "close" ); err ! = nil {
146
- return err
146
+ if f = = nil {
147
+ return ErrInvalid
147
148
}
148
149
return f .file .close ()
149
150
}
150
151
151
152
func (file * file ) close () error {
152
- if file == nil || file . fd == badFd {
153
- return ErrInvalid
153
+ if ! file . fdmu . IncrefAndClose () {
154
+ return & PathError { Op : "close" , Path : file . name , Err : ErrClosed }
154
155
}
156
+
157
+ // At this point we should cancel any pending I/O.
158
+ // How do we do that on Plan 9?
159
+
160
+ err := file .decref ()
161
+
162
+ // no need for a finalizer anymore
163
+ runtime .SetFinalizer (file , nil )
164
+ return err
165
+ }
166
+
167
+ // destroy actually closes the descriptor. This is called when
168
+ // there are no remaining references, by the decref, readUnlock,
169
+ // and writeUnlock methods.
170
+ func (file * file ) destroy () error {
155
171
var err error
156
172
if e := syscall .Close (file .fd ); e != nil {
157
173
err = & PathError {Op : "close" , Path : file .name , Err : e }
158
174
}
159
- file .fd = badFd // so it can't be closed again
160
-
161
- // no need for a finalizer anymore
162
- runtime .SetFinalizer (file , nil )
163
175
return err
164
176
}
165
177
@@ -193,6 +205,12 @@ func (f *File) Truncate(size int64) error {
193
205
if err != nil {
194
206
return & PathError {Op : "truncate" , Path : f .name , Err : err }
195
207
}
208
+
209
+ if err := f .incref ("truncate" ); err != nil {
210
+ return err
211
+ }
212
+ defer f .decref ()
213
+
196
214
if err = syscall .Fwstat (f .fd , buf [:n ]); err != nil {
197
215
return & PathError {Op : "truncate" , Path : f .name , Err : err }
198
216
}
@@ -219,6 +237,12 @@ func (f *File) chmod(mode FileMode) error {
219
237
if err != nil {
220
238
return & PathError {Op : "chmod" , Path : f .name , Err : err }
221
239
}
240
+
241
+ if err := f .incref ("chmod" ); err != nil {
242
+ return err
243
+ }
244
+ defer f .decref ()
245
+
222
246
if err = syscall .Fwstat (f .fd , buf [:n ]); err != nil {
223
247
return & PathError {Op : "chmod" , Path : f .name , Err : err }
224
248
}
@@ -240,6 +264,12 @@ func (f *File) Sync() error {
240
264
if err != nil {
241
265
return & PathError {Op : "sync" , Path : f .name , Err : err }
242
266
}
267
+
268
+ if err := f .incref ("sync" ); err != nil {
269
+ return err
270
+ }
271
+ defer f .decref ()
272
+
243
273
if err = syscall .Fwstat (f .fd , buf [:n ]); err != nil {
244
274
return & PathError {Op : "sync" , Path : f .name , Err : err }
245
275
}
@@ -249,6 +279,10 @@ func (f *File) Sync() error {
249
279
// read reads up to len(b) bytes from the File.
250
280
// It returns the number of bytes read and an error, if any.
251
281
func (f * File ) read (b []byte ) (n int , err error ) {
282
+ if err := f .readLock (); err != nil {
283
+ return 0 , err
284
+ }
285
+ defer f .readUnlock ()
252
286
n , e := fixCount (syscall .Read (f .fd , b ))
253
287
if n == 0 && len (b ) > 0 && e == nil {
254
288
return 0 , io .EOF
@@ -260,6 +294,10 @@ func (f *File) read(b []byte) (n int, err error) {
260
294
// It returns the number of bytes read and the error, if any.
261
295
// EOF is signaled by a zero count with err set to nil.
262
296
func (f * File ) pread (b []byte , off int64 ) (n int , err error ) {
297
+ if err := f .readLock (); err != nil {
298
+ return 0 , err
299
+ }
300
+ defer f .readUnlock ()
263
301
n , e := fixCount (syscall .Pread (f .fd , b , off ))
264
302
if n == 0 && len (b ) > 0 && e == nil {
265
303
return 0 , io .EOF
@@ -272,6 +310,10 @@ func (f *File) pread(b []byte, off int64) (n int, err error) {
272
310
// Since Plan 9 preserves message boundaries, never allow
273
311
// a zero-byte write.
274
312
func (f * File ) write (b []byte ) (n int , err error ) {
313
+ if err := f .writeLock (); err != nil {
314
+ return 0 , err
315
+ }
316
+ defer f .writeUnlock ()
275
317
if len (b ) == 0 {
276
318
return 0 , nil
277
319
}
@@ -283,6 +325,10 @@ func (f *File) write(b []byte) (n int, err error) {
283
325
// Since Plan 9 preserves message boundaries, never allow
284
326
// a zero-byte write.
285
327
func (f * File ) pwrite (b []byte , off int64 ) (n int , err error ) {
328
+ if err := f .writeLock (); err != nil {
329
+ return 0 , err
330
+ }
331
+ defer f .writeUnlock ()
286
332
if len (b ) == 0 {
287
333
return 0 , nil
288
334
}
@@ -294,6 +340,10 @@ func (f *File) pwrite(b []byte, off int64) (n int, err error) {
294
340
// relative to the current offset, and 2 means relative to the end.
295
341
// It returns the new offset and an error, if any.
296
342
func (f * File ) seek (offset int64 , whence int ) (ret int64 , err error ) {
343
+ if err := f .incref ("" ); err != nil {
344
+ return 0 , err
345
+ }
346
+ defer f .decref ()
297
347
if f .dirinfo != nil {
298
348
// Free cached dirinfo, so we allocate a new one if we
299
349
// access this file as a directory again. See #35767 and #37161.
@@ -493,9 +543,10 @@ func tempDir() string {
493
543
// which must be a directory.
494
544
// If there is an error, it will be of type *PathError.
495
545
func (f * File ) Chdir () error {
496
- if err := f .checkValid ("chdir" ); err != nil {
546
+ if err := f .incref ("chdir" ); err != nil {
497
547
return err
498
548
}
549
+ defer f .decref ()
499
550
if e := syscall .Fchdir (f .fd ); e != nil {
500
551
return & PathError {Op : "chdir" , Path : f .name , Err : e }
501
552
}
@@ -526,16 +577,17 @@ func (f *File) setWriteDeadline(time.Time) error {
526
577
return poll .ErrNoDeadline
527
578
}
528
579
529
- // checkValid checks whether f is valid for use.
530
- // If not, it returns an appropriate error, perhaps incorporating the operation name op.
580
+ // checkValid checks whether f is valid for use, but does not prepare
581
+ // to actually use it. If f is not ready checkValid returns an appropriate
582
+ // error, perhaps incorporating the operation name op.
531
583
func (f * File ) checkValid (op string ) error {
532
584
if f == nil {
533
585
return ErrInvalid
534
586
}
535
- if f . fd == badFd {
536
- return & PathError { Op : op , Path : f . name , Err : ErrClosed }
587
+ if err := f . incref ( op ); err != nil {
588
+ return err
537
589
}
538
- return nil
590
+ return f . decref ()
539
591
}
540
592
541
593
type rawConn struct {}
0 commit comments