LEFT | RIGHT |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 } |
LEFT | RIGHT |