blockon_linux.go 1.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344
  1. //go:build linux && !android
  2. // +build linux,!android
  3. package tio
  4. import (
  5. "os"
  6. "golang.org/x/sys/unix"
  7. )
  8. // blockOn parks the calling goroutine until fd is ready or shutdownFd signals teardown.
  9. // (events is POLLIN for reads, POLLOUT for writes)
  10. // It builds the pollfd array on the stack every call, so concurrent callers on the same Queue never share Revents storage.
  11. //
  12. // Returns os.ErrClosed when shutdown was signaled (POLLIN on shutdownFd)
  13. // or either fd reported a problem condition (POLLHUP|POLLNVAL|POLLERR).
  14. func blockOn(fd, shutdownFd int32, events int16) error {
  15. const problemFlags = unix.POLLHUP | unix.POLLNVAL | unix.POLLERR
  16. pfds := [2]unix.PollFd{
  17. {Fd: fd, Events: events},
  18. {Fd: shutdownFd, Events: unix.POLLIN},
  19. }
  20. var err error
  21. for {
  22. _, err = unix.Poll(pfds[:], -1)
  23. if err != unix.EINTR {
  24. break
  25. }
  26. }
  27. tunEvents := pfds[0].Revents
  28. shutdownEvents := pfds[1].Revents
  29. // Check err before trusting the potentially bogus bits we just got.
  30. if err != nil {
  31. return err
  32. }
  33. if shutdownEvents&(unix.POLLIN|problemFlags) != 0 {
  34. return os.ErrClosed
  35. }
  36. if tunEvents&problemFlags != 0 {
  37. return os.ErrClosed
  38. }
  39. return nil
  40. }