blockon_linux.go 1.1 KB

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