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

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

Issue 6813046: code review 6813046: net: use WriteNB on non-blocking sockets (Closed)
Left Patch Set: diff -r 8df088298a0c https://code.google.com/p/go Created 11 years, 5 months ago
Right Patch Set: diff -r 9a3e56fe880c https://code.google.com/p/go Created 11 years, 2 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 | no next file » | 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 "errors"
11 "io" 10 "io"
12 "os" 11 "os"
13 "runtime" 12 "runtime"
14 "sync" 13 "sync"
15 "syscall" 14 "syscall"
16 "time" 15 "time"
17 ) 16 )
18 17
19 // Network file descriptor. 18 // Network file descriptor.
20 type netFD struct { 19 type netFD struct {
(...skipping 10 matching lines...) Expand all
31 family int 30 family int
32 sotype int 31 sotype int
33 isConnected bool 32 isConnected bool
34 sysfile *os.File 33 sysfile *os.File
35 cr chan error 34 cr chan error
36 cw chan error 35 cw chan error
37 net string 36 net string
38 laddr Addr 37 laddr Addr
39 raddr Addr 38 raddr Addr
40 39
41 » // owned by client 40 » // serialize access to Read and Write methods
42 » rdeadline int64 41 » rio, wio sync.Mutex
43 » rio sync.Mutex 42
44 » wdeadline int64 43 » // read and write deadlines
45 » wio sync.Mutex 44 » rdeadline, wdeadline deadline
46 45
47 // owned by fd wait server 46 // owned by fd wait server
48 ncr, ncw int 47 ncr, ncw int
49 48
50 // wait server 49 // wait server
51 pollServer *pollServer 50 pollServer *pollServer
52 } 51 }
53 52
54 // A pollServer helps FDs determine when to retry a non-blocking 53 // A pollServer helps FDs determine when to retry a non-blocking
55 // read or write after they get EAGAIN. When an FD needs to wait, 54 // read or write after they get EAGAIN. When an FD needs to wait,
(...skipping 20 matching lines...) Expand all
76 if intfd < 0 || fd.closing { 75 if intfd < 0 || fd.closing {
77 // fd closed underfoot 76 // fd closed underfoot
78 s.Unlock() 77 s.Unlock()
79 return errClosing 78 return errClosing
80 } 79 }
81 80
82 var t int64 81 var t int64
83 key := intfd << 1 82 key := intfd << 1
84 if mode == 'r' { 83 if mode == 'r' {
85 fd.ncr++ 84 fd.ncr++
86 » » t = fd.rdeadline 85 » » t = fd.rdeadline.value()
87 } else { 86 } else {
88 fd.ncw++ 87 fd.ncw++
89 key++ 88 key++
90 » » t = fd.wdeadline 89 » » t = fd.wdeadline.value()
91 } 90 }
92 s.pending[key] = fd 91 s.pending[key] = fd
93 doWakeup := false 92 doWakeup := false
94 if t > 0 && (s.deadline == 0 || t < s.deadline) { 93 if t > 0 && (s.deadline == 0 || t < s.deadline) {
95 s.deadline = t 94 s.deadline = t
96 doWakeup = true 95 doWakeup = true
97 } 96 }
98 97
99 wake, err := s.poll.AddFD(intfd, mode, false) 98 wake, err := s.poll.AddFD(intfd, mode, false)
100 s.Unlock() 99 s.Unlock()
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
147 fd.cr <- err 146 fd.cr <- err
148 } 147 }
149 } else { 148 } else {
150 for fd.ncw > 0 { 149 for fd.ncw > 0 {
151 fd.ncw-- 150 fd.ncw--
152 fd.cw <- err 151 fd.cw <- err
153 } 152 }
154 } 153 }
155 } 154 }
156 155
157 func (s *pollServer) Now() int64 {
158 return time.Now().UnixNano()
159 }
160
161 func (s *pollServer) CheckDeadlines() { 156 func (s *pollServer) CheckDeadlines() {
162 » now := s.Now() 157 » now := time.Now().UnixNano()
163 // TODO(rsc): This will need to be handled more efficiently, 158 // TODO(rsc): This will need to be handled more efficiently,
164 // probably with a heap indexed by wakeup time. 159 // probably with a heap indexed by wakeup time.
165 160
166 » var next_deadline int64 161 » var nextDeadline int64
167 for key, fd := range s.pending { 162 for key, fd := range s.pending {
168 var t int64 163 var t int64
169 var mode int 164 var mode int
170 if key&1 == 0 { 165 if key&1 == 0 {
171 mode = 'r' 166 mode = 'r'
172 } else { 167 } else {
173 mode = 'w' 168 mode = 'w'
174 } 169 }
175 if mode == 'r' { 170 if mode == 'r' {
176 » » » t = fd.rdeadline 171 » » » t = fd.rdeadline.value()
177 } else { 172 } else {
178 » » » t = fd.wdeadline 173 » » » t = fd.wdeadline.value()
179 } 174 }
180 if t > 0 { 175 if t > 0 {
181 if t <= now { 176 if t <= now {
182 delete(s.pending, key) 177 delete(s.pending, key)
183 if mode == 'r' { 178 if mode == 'r' {
184 s.poll.DelFD(fd.sysfd, mode) 179 s.poll.DelFD(fd.sysfd, mode)
185 fd.rdeadline = -1
186 } else { 180 } else {
187 s.poll.DelFD(fd.sysfd, mode) 181 s.poll.DelFD(fd.sysfd, mode)
188 fd.wdeadline = -1
189 } 182 }
190 » » » » s.WakeFD(fd, mode, nil) 183 » » » » s.WakeFD(fd, mode, errTimeout)
191 » » » } else if next_deadline == 0 || t < next_deadline { 184 » » » } else if nextDeadline == 0 || t < nextDeadline {
192 » » » » next_deadline = t 185 » » » » nextDeadline = t
193 » » » } 186 » » » }
194 » » } 187 » » }
195 » } 188 » }
196 » s.deadline = next_deadline 189 » s.deadline = nextDeadline
197 } 190 }
198 191
199 func (s *pollServer) Run() { 192 func (s *pollServer) Run() {
200 var scratch [100]byte 193 var scratch [100]byte
201 s.Lock() 194 s.Lock()
202 defer s.Unlock() 195 defer s.Unlock()
203 for { 196 for {
204 » » var t = s.deadline 197 » » var timeout int64 // nsec to wait for or 0 for none
205 » » if t > 0 { 198 » » if s.deadline > 0 {
206 » » » t = t - s.Now() 199 » » » timeout = s.deadline - time.Now().UnixNano()
207 » » » if t <= 0 { 200 » » » if timeout <= 0 {
208 s.CheckDeadlines() 201 s.CheckDeadlines()
209 continue 202 continue
210 } 203 }
211 } 204 }
212 » » fd, mode, err := s.poll.WaitFD(s, t) 205 » » fd, mode, err := s.poll.WaitFD(s, timeout)
213 if err != nil { 206 if err != nil {
214 print("pollServer WaitFD: ", err.Error(), "\n") 207 print("pollServer WaitFD: ", err.Error(), "\n")
215 return 208 return
216 } 209 }
217 if fd < 0 { 210 if fd < 0 {
218 // Timeout happened. 211 // Timeout happened.
219 s.CheckDeadlines() 212 s.CheckDeadlines()
220 continue 213 continue
221 } 214 }
222 if fd == int(s.pr.Fd()) { 215 if fd == int(s.pr.Fd()) {
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
254 return err 247 return err
255 } 248 }
256 249
257 // Network FD methods. 250 // Network FD methods.
258 // Spread network FDs over several pollServers. 251 // Spread network FDs over several pollServers.
259 252
260 var pollMaxN int 253 var pollMaxN int
261 var pollservers []*pollServer 254 var pollservers []*pollServer
262 var startServersOnce []func() 255 var startServersOnce []func()
263 256
264 func init() { 257 var canCancelIO = true // used for testing current package
258
259 func sysInit() {
265 pollMaxN = runtime.NumCPU() 260 pollMaxN = runtime.NumCPU()
266 if pollMaxN > 8 { 261 if pollMaxN > 8 {
267 pollMaxN = 8 // No improvement then. 262 pollMaxN = 8 // No improvement then.
268 } 263 }
269 pollservers = make([]*pollServer, pollMaxN) 264 pollservers = make([]*pollServer, pollMaxN)
270 startServersOnce = make([]func(), pollMaxN) 265 startServersOnce = make([]func(), pollMaxN)
271 for i := 0; i < pollMaxN; i++ { 266 for i := 0; i < pollMaxN; i++ {
272 k := i 267 k := i
273 once := new(sync.Once) 268 once := new(sync.Once)
274 startServersOnce[i] = func() { once.Do(func() { startServer(k) } ) } 269 startServersOnce[i] = func() { once.Do(func() { startServer(k) } ) }
(...skipping 11 matching lines...) Expand all
286 func server(fd int) *pollServer { 281 func server(fd int) *pollServer {
287 pollN := runtime.GOMAXPROCS(0) 282 pollN := runtime.GOMAXPROCS(0)
288 if pollN > pollMaxN { 283 if pollN > pollMaxN {
289 pollN = pollMaxN 284 pollN = pollMaxN
290 } 285 }
291 k := fd % pollN 286 k := fd % pollN
292 startServersOnce[k]() 287 startServersOnce[k]()
293 return pollservers[k] 288 return pollservers[k]
294 } 289 }
295 290
291 func dialTimeout(net, addr string, timeout time.Duration) (Conn, error) {
292 deadline := time.Now().Add(timeout)
293 _, addri, err := resolveNetAddr("dial", net, addr, deadline)
294 if err != nil {
295 return nil, err
296 }
297 return dialAddr(net, addr, addri, deadline)
298 }
299
296 func newFD(fd, family, sotype int, net string) (*netFD, error) { 300 func newFD(fd, family, sotype int, net string) (*netFD, error) {
297 if err := syscall.SetNonblock(fd, true); err != nil { 301 if err := syscall.SetNonblock(fd, true); err != nil {
298 return nil, err 302 return nil, err
299 } 303 }
300 netfd := &netFD{ 304 netfd := &netFD{
301 sysfd: fd, 305 sysfd: fd,
302 family: family, 306 family: family,
303 sotype: sotype, 307 sotype: sotype,
304 net: net, 308 net: net,
305 } 309 }
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
337 if err != nil { 341 if err != nil {
338 return os.NewSyscallError("getsockopt", err) 342 return os.NewSyscallError("getsockopt", err)
339 } 343 }
340 if e != 0 { 344 if e != 0 {
341 err = syscall.Errno(e) 345 err = syscall.Errno(e)
342 } 346 }
343 } 347 }
344 return err 348 return err
345 } 349 }
346 350
347 var errClosing = errors.New("use of closed network connection")
348
349 // Add a reference to this fd. 351 // Add a reference to this fd.
350 // If closing==true, pollserver must be locked; mark the fd as closing. 352 // If closing==true, pollserver must be locked; mark the fd as closing.
351 // Returns an error if the fd cannot be used. 353 // Returns an error if the fd cannot be used.
352 func (fd *netFD) incref(closing bool) error { 354 func (fd *netFD) incref(closing bool) error {
353 if fd == nil {
354 return errClosing
355 }
356 fd.sysmu.Lock() 355 fd.sysmu.Lock()
357 if fd.closing { 356 if fd.closing {
358 fd.sysmu.Unlock() 357 fd.sysmu.Unlock()
359 return errClosing 358 return errClosing
360 } 359 }
361 fd.sysref++ 360 fd.sysref++
362 if closing { 361 if closing {
363 fd.closing = true 362 fd.closing = true
364 } 363 }
365 fd.sysmu.Unlock() 364 fd.sysmu.Unlock()
366 return nil 365 return nil
367 } 366 }
368 367
369 // Remove a reference to this FD and close if we've been asked to do so (and 368 // Remove a reference to this FD and close if we've been asked to do so (and
370 // there are no references left. 369 // there are no references left.
371 func (fd *netFD) decref() { 370 func (fd *netFD) decref() {
372 if fd == nil {
373 return
374 }
375 fd.sysmu.Lock() 371 fd.sysmu.Lock()
376 fd.sysref-- 372 fd.sysref--
377 if fd.closing && fd.sysref == 0 && fd.sysfile != nil { 373 if fd.closing && fd.sysref == 0 && fd.sysfile != nil {
378 fd.sysfile.Close() 374 fd.sysfile.Close()
379 fd.sysfile = nil 375 fd.sysfile = nil
380 fd.sysfd = -1 376 fd.sysfd = -1
381 } 377 }
382 fd.sysmu.Unlock() 378 fd.sysmu.Unlock()
383 } 379 }
384 380
385 func (fd *netFD) Close() error { 381 func (fd *netFD) Close() error {
386 fd.pollServer.Lock() // needed for both fd.incref(true) and pollserver.E vict 382 fd.pollServer.Lock() // needed for both fd.incref(true) and pollserver.E vict
387 defer fd.pollServer.Unlock()
388 if err := fd.incref(true); err != nil { 383 if err := fd.incref(true); err != nil {
384 fd.pollServer.Unlock()
389 return err 385 return err
390 } 386 }
391 // Unblock any I/O. Once it all unblocks and returns, 387 // Unblock any I/O. Once it all unblocks and returns,
392 // so that it cannot be referring to fd.sysfd anymore, 388 // so that it cannot be referring to fd.sysfd anymore,
393 // the final decref will close fd.sysfd. This should happen 389 // the final decref will close fd.sysfd. This should happen
394 // fairly quickly, since all the I/O is non-blocking, and any 390 // fairly quickly, since all the I/O is non-blocking, and any
395 // attempts to block in the pollserver will return errClosing. 391 // attempts to block in the pollserver will return errClosing.
396 fd.pollServer.Evict(fd) 392 fd.pollServer.Evict(fd)
393 fd.pollServer.Unlock()
397 fd.decref() 394 fd.decref()
398 return nil 395 return nil
399 } 396 }
400 397
401 func (fd *netFD) shutdown(how int) error { 398 func (fd *netFD) shutdown(how int) error {
402 if err := fd.incref(false); err != nil { 399 if err := fd.incref(false); err != nil {
403 return err 400 return err
404 } 401 }
405 defer fd.decref() 402 defer fd.decref()
406 err := syscall.Shutdown(fd.sysfd, how) 403 err := syscall.Shutdown(fd.sysfd, how)
(...skipping 12 matching lines...) Expand all
419 } 416 }
420 417
421 func (fd *netFD) Read(p []byte) (n int, err error) { 418 func (fd *netFD) Read(p []byte) (n int, err error) {
422 fd.rio.Lock() 419 fd.rio.Lock()
423 defer fd.rio.Unlock() 420 defer fd.rio.Unlock()
424 if err := fd.incref(false); err != nil { 421 if err := fd.incref(false); err != nil {
425 return 0, err 422 return 0, err
426 } 423 }
427 defer fd.decref() 424 defer fd.decref()
428 for { 425 for {
426 if fd.rdeadline.expired() {
427 err = errTimeout
428 break
429 }
429 n, err = syscall.Read(int(fd.sysfd), p) 430 n, err = syscall.Read(int(fd.sysfd), p)
430 » » if err == syscall.EAGAIN { 431 » » if err != nil {
431 » » » err = errTimeout 432 » » » n = 0
432 » » » if fd.rdeadline >= 0 { 433 » » » if err == syscall.EAGAIN {
433 if err = fd.pollServer.WaitRead(fd); err == nil { 434 if err = fd.pollServer.WaitRead(fd); err == nil {
434 continue 435 continue
435 } 436 }
436 } 437 }
437 } 438 }
438 » » if err != nil { 439 » » err = chkReadErr(n, err, fd)
439 » » » n = 0
440 » » } else if n == 0 && err == nil && fd.sotype != syscall.SOCK_DGRA M {
441 » » » err = io.EOF
442 » » }
443 break 440 break
444 } 441 }
445 if err != nil && err != io.EOF { 442 if err != nil && err != io.EOF {
446 err = &OpError{"read", fd.net, fd.raddr, err} 443 err = &OpError{"read", fd.net, fd.raddr, err}
447 } 444 }
448 return 445 return
449 } 446 }
450 447
451 func (fd *netFD) ReadFrom(p []byte) (n int, sa syscall.Sockaddr, err error) { 448 func (fd *netFD) ReadFrom(p []byte) (n int, sa syscall.Sockaddr, err error) {
452 fd.rio.Lock() 449 fd.rio.Lock()
453 defer fd.rio.Unlock() 450 defer fd.rio.Unlock()
454 if err := fd.incref(false); err != nil { 451 if err := fd.incref(false); err != nil {
455 return 0, nil, err 452 return 0, nil, err
456 } 453 }
457 defer fd.decref() 454 defer fd.decref()
458 for { 455 for {
456 if fd.rdeadline.expired() {
457 err = errTimeout
458 break
459 }
459 n, sa, err = syscall.Recvfrom(fd.sysfd, p, 0) 460 n, sa, err = syscall.Recvfrom(fd.sysfd, p, 0)
460 » » if err == syscall.EAGAIN { 461 » » if err != nil {
461 » » » err = errTimeout 462 » » » n = 0
462 » » » if fd.rdeadline >= 0 { 463 » » » if err == syscall.EAGAIN {
463 if err = fd.pollServer.WaitRead(fd); err == nil { 464 if err = fd.pollServer.WaitRead(fd); err == nil {
464 continue 465 continue
465 } 466 }
466 } 467 }
467 } 468 }
468 » » if err != nil { 469 » » err = chkReadErr(n, err, fd)
469 » » » n = 0
470 » » }
471 break 470 break
472 } 471 }
473 if err != nil && err != io.EOF { 472 if err != nil && err != io.EOF {
474 err = &OpError{"read", fd.net, fd.laddr, err} 473 err = &OpError{"read", fd.net, fd.laddr, err}
475 } 474 }
476 return 475 return
477 } 476 }
478 477
479 func (fd *netFD) ReadMsg(p []byte, oob []byte) (n, oobn, flags int, sa syscall.S ockaddr, err error) { 478 func (fd *netFD) ReadMsg(p []byte, oob []byte) (n, oobn, flags int, sa syscall.S ockaddr, err error) {
480 fd.rio.Lock() 479 fd.rio.Lock()
481 defer fd.rio.Unlock() 480 defer fd.rio.Unlock()
482 if err := fd.incref(false); err != nil { 481 if err := fd.incref(false); err != nil {
483 return 0, 0, 0, nil, err 482 return 0, 0, 0, nil, err
484 } 483 }
485 defer fd.decref() 484 defer fd.decref()
486 for { 485 for {
486 if fd.rdeadline.expired() {
487 err = errTimeout
488 break
489 }
487 n, oobn, flags, sa, err = syscall.Recvmsg(fd.sysfd, p, oob, 0) 490 n, oobn, flags, sa, err = syscall.Recvmsg(fd.sysfd, p, oob, 0)
488 » » if err == syscall.EAGAIN { 491 » » if err != nil {
489 » » » err = errTimeout 492 » » » // TODO(dfc) should n and oobn be set to 0
490 » » » if fd.rdeadline >= 0 { 493 » » » if err == syscall.EAGAIN {
491 if err = fd.pollServer.WaitRead(fd); err == nil { 494 if err = fd.pollServer.WaitRead(fd); err == nil {
492 continue 495 continue
493 } 496 }
494 } 497 }
495 } 498 }
496 » » if err == nil && n == 0 { 499 » » err = chkReadErr(n, err, fd)
497 » » » err = io.EOF
498 » » }
499 break 500 break
500 } 501 }
501 if err != nil && err != io.EOF { 502 if err != nil && err != io.EOF {
502 err = &OpError{"read", fd.net, fd.laddr, err} 503 err = &OpError{"read", fd.net, fd.laddr, err}
503 return
504 } 504 }
505 return 505 return
506 } 506 }
507 507
508 func (fd *netFD) Write(p []byte) (int, error) { 508 func chkReadErr(n int, err error, fd *netFD) error {
509 » if n == 0 && err == nil && fd.sotype != syscall.SOCK_DGRAM && fd.sotype != syscall.SOCK_RAW {
510 » » return io.EOF
511 » }
512 » return err
513 }
514
515 func (fd *netFD) Write(p []byte) (nn int, err error) {
509 fd.wio.Lock() 516 fd.wio.Lock()
510 defer fd.wio.Unlock() 517 defer fd.wio.Unlock()
511 if err := fd.incref(false); err != nil { 518 if err := fd.incref(false); err != nil {
512 return 0, err 519 return 0, err
513 } 520 }
514 defer fd.decref() 521 defer fd.decref()
515 » if fd.sysfile == nil { 522 » for {
516 » » return 0, syscall.EINVAL 523 » » if fd.wdeadline.expired() {
517 » } 524 » » » err = errTimeout
518 525 » » » break
519 » var err error 526 » » }
520 » nn := 0
521 » for {
522 var n int 527 var n int
523 n, err = syscall.WriteNB(int(fd.sysfd), p[nn:]) 528 n, err = syscall.WriteNB(int(fd.sysfd), p[nn:])
524 if n > 0 { 529 if n > 0 {
525 nn += n 530 nn += n
526 } 531 }
527 if nn == len(p) { 532 if nn == len(p) {
528 break 533 break
529 } 534 }
530 if err == syscall.EAGAIN { 535 if err == syscall.EAGAIN {
531 » » » err = errTimeout 536 » » » if err = fd.pollServer.WaitWrite(fd); err == nil {
532 » » » if fd.wdeadline >= 0 { 537 » » » » continue
533 » » » » if err = fd.pollServer.WaitWrite(fd); err == nil {
534 » » » » » continue
535 » » » » }
536 } 538 }
537 } 539 }
538 if err != nil { 540 if err != nil {
539 n = 0 541 n = 0
540 break 542 break
541 } 543 }
542 if n == 0 { 544 if n == 0 {
543 err = io.ErrUnexpectedEOF 545 err = io.ErrUnexpectedEOF
544 break 546 break
545 } 547 }
546 } 548 }
547 if err != nil { 549 if err != nil {
548 err = &OpError{"write", fd.net, fd.raddr, err} 550 err = &OpError{"write", fd.net, fd.raddr, err}
549 } 551 }
550 return nn, err 552 return nn, err
551 } 553 }
552 554
553 func (fd *netFD) WriteTo(p []byte, sa syscall.Sockaddr) (n int, err error) { 555 func (fd *netFD) WriteTo(p []byte, sa syscall.Sockaddr) (n int, err error) {
554 fd.wio.Lock() 556 fd.wio.Lock()
555 defer fd.wio.Unlock() 557 defer fd.wio.Unlock()
556 if err := fd.incref(false); err != nil { 558 if err := fd.incref(false); err != nil {
557 return 0, err 559 return 0, err
558 } 560 }
559 defer fd.decref() 561 defer fd.decref()
560 for { 562 for {
563 if fd.wdeadline.expired() {
564 err = errTimeout
565 break
566 }
561 err = syscall.Sendto(fd.sysfd, p, 0, sa) 567 err = syscall.Sendto(fd.sysfd, p, 0, sa)
562 if err == syscall.EAGAIN { 568 if err == syscall.EAGAIN {
563 » » » err = errTimeout 569 » » » if err = fd.pollServer.WaitWrite(fd); err == nil {
564 » » » if fd.wdeadline >= 0 { 570 » » » » continue
565 » » » » if err = fd.pollServer.WaitWrite(fd); err == nil {
566 » » » » » continue
567 » » » » }
568 } 571 }
569 } 572 }
570 break 573 break
571 } 574 }
572 if err == nil { 575 if err == nil {
573 n = len(p) 576 n = len(p)
574 } else { 577 } else {
575 err = &OpError{"write", fd.net, fd.raddr, err} 578 err = &OpError{"write", fd.net, fd.raddr, err}
576 } 579 }
577 return 580 return
578 } 581 }
579 582
580 func (fd *netFD) WriteMsg(p []byte, oob []byte, sa syscall.Sockaddr) (n int, oob n int, err error) { 583 func (fd *netFD) WriteMsg(p []byte, oob []byte, sa syscall.Sockaddr) (n int, oob n int, err error) {
581 fd.wio.Lock() 584 fd.wio.Lock()
582 defer fd.wio.Unlock() 585 defer fd.wio.Unlock()
583 if err := fd.incref(false); err != nil { 586 if err := fd.incref(false); err != nil {
584 return 0, 0, err 587 return 0, 0, err
585 } 588 }
586 defer fd.decref() 589 defer fd.decref()
587 for { 590 for {
591 if fd.wdeadline.expired() {
592 err = errTimeout
593 break
594 }
588 err = syscall.Sendmsg(fd.sysfd, p, oob, sa, 0) 595 err = syscall.Sendmsg(fd.sysfd, p, oob, sa, 0)
589 if err == syscall.EAGAIN { 596 if err == syscall.EAGAIN {
590 » » » err = errTimeout 597 » » » if err = fd.pollServer.WaitWrite(fd); err == nil {
591 » » » if fd.wdeadline >= 0 { 598 » » » » continue
592 » » » » if err = fd.pollServer.WaitWrite(fd); err == nil {
593 » » » » » continue
594 » » » » }
595 } 599 }
596 } 600 }
597 break 601 break
598 } 602 }
599 if err == nil { 603 if err == nil {
600 n = len(p) 604 n = len(p)
601 oobn = len(oob) 605 oobn = len(oob)
602 } else { 606 } else {
603 err = &OpError{"write", fd.net, fd.raddr, err} 607 err = &OpError{"write", fd.net, fd.raddr, err}
604 } 608 }
(...skipping 10 matching lines...) Expand all
615 // It is okay to hold the lock across syscall.Accept 619 // It is okay to hold the lock across syscall.Accept
616 // because we have put fd.sysfd into non-blocking mode. 620 // because we have put fd.sysfd into non-blocking mode.
617 var s int 621 var s int
618 var rsa syscall.Sockaddr 622 var rsa syscall.Sockaddr
619 for { 623 for {
620 syscall.ForkLock.RLock() 624 syscall.ForkLock.RLock()
621 s, rsa, err = syscall.Accept(fd.sysfd) 625 s, rsa, err = syscall.Accept(fd.sysfd)
622 if err != nil { 626 if err != nil {
623 syscall.ForkLock.RUnlock() 627 syscall.ForkLock.RUnlock()
624 if err == syscall.EAGAIN { 628 if err == syscall.EAGAIN {
625 » » » » err = errTimeout 629 » » » » if err = fd.pollServer.WaitRead(fd); err == nil {
626 » » » » if fd.rdeadline >= 0 { 630 » » » » » continue
627 » » » » » if err = fd.pollServer.WaitRead(fd); err == nil {
628 » » » » » » continue
629 » » » » » }
630 } 631 }
631 } else if err == syscall.ECONNABORTED { 632 } else if err == syscall.ECONNABORTED {
632 // This means that a socket on the listen queue was closed 633 // This means that a socket on the listen queue was closed
633 // before we Accept()ed it; it's a silly error, so try again. 634 // before we Accept()ed it; it's a silly error, so try again.
634 continue 635 continue
635 } 636 }
636 return nil, &OpError{"accept", fd.net, fd.laddr, err} 637 return nil, &OpError{"accept", fd.net, fd.laddr, err}
637 } 638 }
638 break 639 break
639 } 640 }
(...skipping 23 matching lines...) Expand all
663 if err = syscall.SetNonblock(ns, false); err != nil { 664 if err = syscall.SetNonblock(ns, false); err != nil {
664 return nil, &OpError{"setnonblock", fd.net, fd.laddr, err} 665 return nil, &OpError{"setnonblock", fd.net, fd.laddr, err}
665 } 666 }
666 667
667 return os.NewFile(uintptr(ns), fd.name()), nil 668 return os.NewFile(uintptr(ns), fd.name()), nil
668 } 669 }
669 670
670 func closesocket(s int) error { 671 func closesocket(s int) error {
671 return syscall.Close(s) 672 return syscall.Close(s)
672 } 673 }
LEFTRIGHT
« no previous file | no next file » | Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Toggle Comments ('s')

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