Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(72)

Delta Between Two Patch Sets: src/pkg/net/fd_unix.go

Issue 12476043: code review 12476043: net: use F_DUPFD_CLOEXEC when duping fds (Closed)
Left Patch Set: diff -r ffe930a195f4 https://go.googlecode.com/hg/ Created 11 years, 7 months ago
Right Patch Set: diff -r 58c839988402 https://go.googlecode.com/hg/ Created 11 years, 7 months ago
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
Left: Side by side diff | Download
Right: Side by side diff | Download
« no previous file with change/comment | « no previous file | src/pkg/net/file_unix.go » ('j') | no next file with change/comment »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
LEFTRIGHT
1 // Copyright 2009 The Go Authors. All rights reserved. 1 // Copyright 2009 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style 2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file. 3 // license that can be found in the LICENSE file.
4 4
5 // +build darwin freebsd linux netbsd openbsd 5 // +build darwin freebsd linux netbsd openbsd
6 6
7 package net 7 package net
8 8
9 import ( 9 import (
10 "io" 10 "io"
11 "os" 11 "os"
12 "runtime" 12 "runtime"
13 "sync" 13 "sync"
14 "sync/atomic"
14 "syscall" 15 "syscall"
15 "time" 16 "time"
16 ) 17 )
17 18
18 // Network file descriptor. 19 // Network file descriptor.
19 type netFD struct { 20 type netFD struct {
20 // locking/lifetime of sysfd 21 // locking/lifetime of sysfd
21 sysmu sync.Mutex 22 sysmu sync.Mutex
22 sysref int 23 sysref int
23 24
(...skipping 374 matching lines...) Expand 10 before | Expand all | Expand 10 after
398 399
399 if netfd, err = newFD(s, fd.family, fd.sotype, fd.net); err != nil { 400 if netfd, err = newFD(s, fd.family, fd.sotype, fd.net); err != nil {
400 closesocket(s) 401 closesocket(s)
401 return nil, err 402 return nil, err
402 } 403 }
403 lsa, _ := syscall.Getsockname(netfd.sysfd) 404 lsa, _ := syscall.Getsockname(netfd.sysfd)
404 netfd.setAddr(toAddr(lsa), toAddr(rsa)) 405 netfd.setAddr(toAddr(lsa), toAddr(rsa))
405 return netfd, nil 406 return netfd, nil
406 } 407 }
407 408
408 // dupCloseOnExec is a variable so it can be modified in fd_linux.go. 409 // tryDupCloexec indicates whether F_DUPFD_CLOEXEC should be used.
409 var dupCloseOnExec = dupCloseOnExecUnix 410 // If the kernel doesn't support it, this is set to 0.
410 411 var tryDupCloexec = int32(1)
411 // dupCloseOnExecUnix is the traditional way to dup an fd and set 412
412 // its O_CLOEXEC bit, using two system calls. 413 func dupCloseOnExec(fd int) (newfd int, err error) {
413 func dupCloseOnExecUnix(fd int) (newfd int, err error) { 414 » if atomic.LoadInt32(&tryDupCloexec) == 1 {
415 » » r0, _, e1 := syscall.Syscall(syscall.SYS_FCNTL, uintptr(fd), sys call.F_DUPFD_CLOEXEC, 0)
416 » » switch e1 {
417 » » case 0:
418 » » » return int(r0), nil
419 » » case syscall.EINVAL:
420 » » » // Old kernel. Fall back to the portable way
421 » » » // from now on.
422 » » » atomic.StoreInt32(&tryDupCloexec, 0)
423 » » default:
424 » » » return -1, e1
425 » » }
426 » }
427 » return dupCloseOnExecOld(fd)
428 }
429
430 // dupCloseOnExecUnixOld is the traditional way to dup an fd and
431 // set its O_CLOEXEC bit, using two system calls.
432 func dupCloseOnExecOld(fd int) (newfd int, err error) {
414 syscall.ForkLock.RLock() 433 syscall.ForkLock.RLock()
415 defer syscall.ForkLock.RUnlock() 434 defer syscall.ForkLock.RUnlock()
416 » ns, err := syscall.Dup(fd) 435 » newfd, err = syscall.Dup(fd)
417 if err != nil { 436 if err != nil {
418 » » return 437 » » return -1, err
419 » } 438 » }
420 » syscall.CloseOnExec(ns) 439 » syscall.CloseOnExec(newfd)
421 » return ns, nil 440 » return
422 } 441 }
423 442
424 func (fd *netFD) dup() (f *os.File, err error) { 443 func (fd *netFD) dup() (f *os.File, err error) {
425 ns, err := dupCloseOnExec(fd.sysfd) 444 ns, err := dupCloseOnExec(fd.sysfd)
426 if err != nil { 445 if err != nil {
427 syscall.ForkLock.RUnlock() 446 syscall.ForkLock.RUnlock()
428 return nil, &OpError{"dup", fd.net, fd.laddr, err} 447 return nil, &OpError{"dup", fd.net, fd.laddr, err}
429 } 448 }
430 449
431 // We want blocking mode for the new fd, hence the double negative. 450 // We want blocking mode for the new fd, hence the double negative.
432 // This also puts the old fd into blocking mode, meaning that 451 // This also puts the old fd into blocking mode, meaning that
433 // I/O will block the thread instead of letting us use the epoll server. 452 // I/O will block the thread instead of letting us use the epoll server.
434 // Everything will still work, just with more threads. 453 // Everything will still work, just with more threads.
435 if err = syscall.SetNonblock(ns, false); err != nil { 454 if err = syscall.SetNonblock(ns, false); err != nil {
436 return nil, &OpError{"setnonblock", fd.net, fd.laddr, err} 455 return nil, &OpError{"setnonblock", fd.net, fd.laddr, err}
437 } 456 }
438 457
439 return os.NewFile(uintptr(ns), fd.name()), nil 458 return os.NewFile(uintptr(ns), fd.name()), nil
440 } 459 }
441 460
442 func closesocket(s int) error { 461 func closesocket(s int) error {
443 return syscall.Close(s) 462 return syscall.Close(s)
444 } 463 }
LEFTRIGHT

Powered by Google App Engine
RSS Feeds Recent Issues | This issue
This is Rietveld f62528b