posix.py 1.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869
  1. #
  2. # Copyright 2011 Facebook
  3. #
  4. # Licensed under the Apache License, Version 2.0 (the "License"); you may
  5. # not use this file except in compliance with the License. You may obtain
  6. # a copy of the License at
  7. #
  8. # http://www.apache.org/licenses/LICENSE-2.0
  9. #
  10. # Unless required by applicable law or agreed to in writing, software
  11. # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
  12. # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
  13. # License for the specific language governing permissions and limitations
  14. # under the License.
  15. """Posix implementations of platform-specific functionality."""
  16. from __future__ import absolute_import, division, print_function
  17. import fcntl
  18. import os
  19. from tornado.platform import common, interface
  20. def set_close_exec(fd):
  21. flags = fcntl.fcntl(fd, fcntl.F_GETFD)
  22. fcntl.fcntl(fd, fcntl.F_SETFD, flags | fcntl.FD_CLOEXEC)
  23. def _set_nonblocking(fd):
  24. flags = fcntl.fcntl(fd, fcntl.F_GETFL)
  25. fcntl.fcntl(fd, fcntl.F_SETFL, flags | os.O_NONBLOCK)
  26. class Waker(interface.Waker):
  27. def __init__(self):
  28. r, w = os.pipe()
  29. _set_nonblocking(r)
  30. _set_nonblocking(w)
  31. set_close_exec(r)
  32. set_close_exec(w)
  33. self.reader = os.fdopen(r, "rb", 0)
  34. self.writer = os.fdopen(w, "wb", 0)
  35. def fileno(self):
  36. return self.reader.fileno()
  37. def write_fileno(self):
  38. return self.writer.fileno()
  39. def wake(self):
  40. try:
  41. self.writer.write(b"x")
  42. except (IOError, ValueError):
  43. pass
  44. def consume(self):
  45. try:
  46. while True:
  47. result = self.reader.read()
  48. if not result:
  49. break
  50. except IOError:
  51. pass
  52. def close(self):
  53. self.reader.close()
  54. common.try_close(self.writer)