Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.
 
 
 
 

234 рядки
6.4 KiB

  1. @cython.no_gc_clear
  2. cdef class UVPoll(UVHandle):
  3. cdef _init(self, Loop loop, int fd):
  4. cdef int err
  5. self._start_init(loop)
  6. self._handle = <uv.uv_handle_t*>PyMem_RawMalloc(sizeof(uv.uv_poll_t))
  7. if self._handle is NULL:
  8. self._abort_init()
  9. raise MemoryError()
  10. err = uv.uv_poll_init(self._loop.uvloop,
  11. <uv.uv_poll_t *>self._handle, fd)
  12. if err < 0:
  13. self._abort_init()
  14. raise convert_error(err)
  15. self._finish_init()
  16. self.fd = fd
  17. self.reading_handle = None
  18. self.writing_handle = None
  19. @staticmethod
  20. cdef UVPoll new(Loop loop, int fd):
  21. cdef UVPoll handle
  22. handle = UVPoll.__new__(UVPoll)
  23. handle._init(loop, fd)
  24. return handle
  25. cdef int is_active(self) noexcept:
  26. return (self.reading_handle is not None or
  27. self.writing_handle is not None)
  28. cdef inline _poll_start(self, int flags):
  29. cdef int err
  30. self._ensure_alive()
  31. err = uv.uv_poll_start(
  32. <uv.uv_poll_t*>self._handle,
  33. flags,
  34. __on_uvpoll_event)
  35. if err < 0:
  36. exc = convert_error(err)
  37. self._fatal_error(exc, True)
  38. return
  39. cdef inline _poll_stop(self):
  40. cdef int err
  41. if not self._is_alive():
  42. return
  43. err = uv.uv_poll_stop(<uv.uv_poll_t*>self._handle)
  44. if err < 0:
  45. exc = convert_error(err)
  46. self._fatal_error(exc, True)
  47. return
  48. cdef:
  49. int backend_id
  50. system.epoll_event dummy_event
  51. if system.PLATFORM_IS_LINUX:
  52. # libuv doesn't remove the FD from epoll immediately
  53. # after uv_poll_stop or uv_poll_close, causing hard
  54. # to debug issue with dup-ed file descriptors causing
  55. # CPU burn in epoll/epoll_ctl:
  56. # https://github.com/MagicStack/uvloop/issues/61
  57. #
  58. # It's safe though to manually call epoll_ctl here,
  59. # after calling uv_poll_stop.
  60. backend_id = uv.uv_backend_fd(self._loop.uvloop)
  61. if backend_id != -1:
  62. memset(&dummy_event, 0, sizeof(dummy_event))
  63. system.epoll_ctl(
  64. backend_id,
  65. system.EPOLL_CTL_DEL,
  66. self.fd,
  67. &dummy_event) # ignore errors
  68. cdef is_reading(self):
  69. return self._is_alive() and self.reading_handle is not None
  70. cdef is_writing(self):
  71. return self._is_alive() and self.writing_handle is not None
  72. cdef start_reading(self, Handle callback):
  73. cdef:
  74. int mask = 0
  75. if self.reading_handle is None:
  76. # not reading right now, setup the handle
  77. mask = uv.UV_READABLE
  78. if self.writing_handle is not None:
  79. # are we writing right now?
  80. mask |= uv.UV_WRITABLE
  81. self._poll_start(mask)
  82. else:
  83. self.reading_handle._cancel()
  84. self.reading_handle = callback
  85. cdef start_writing(self, Handle callback):
  86. cdef:
  87. int mask = 0
  88. if self.writing_handle is None:
  89. # not writing right now, setup the handle
  90. mask = uv.UV_WRITABLE
  91. if self.reading_handle is not None:
  92. # are we reading right now?
  93. mask |= uv.UV_READABLE
  94. self._poll_start(mask)
  95. else:
  96. self.writing_handle._cancel()
  97. self.writing_handle = callback
  98. cdef stop_reading(self):
  99. if self.reading_handle is None:
  100. return False
  101. self.reading_handle._cancel()
  102. self.reading_handle = None
  103. if self.writing_handle is None:
  104. self.stop()
  105. else:
  106. self._poll_start(uv.UV_WRITABLE)
  107. return True
  108. cdef stop_writing(self):
  109. if self.writing_handle is None:
  110. return False
  111. self.writing_handle._cancel()
  112. self.writing_handle = None
  113. if self.reading_handle is None:
  114. self.stop()
  115. else:
  116. self._poll_start(uv.UV_READABLE)
  117. return True
  118. cdef stop(self):
  119. if self.reading_handle is not None:
  120. self.reading_handle._cancel()
  121. self.reading_handle = None
  122. if self.writing_handle is not None:
  123. self.writing_handle._cancel()
  124. self.writing_handle = None
  125. self._poll_stop()
  126. cdef _close(self):
  127. if self.is_active():
  128. self.stop()
  129. UVHandle._close(<UVHandle>self)
  130. cdef _fatal_error(self, exc, throw, reason=None):
  131. try:
  132. if self.reading_handle is not None:
  133. try:
  134. self.reading_handle._run()
  135. except BaseException as ex:
  136. self._loop._handle_exception(ex)
  137. self.reading_handle = None
  138. if self.writing_handle is not None:
  139. try:
  140. self.writing_handle._run()
  141. except BaseException as ex:
  142. self._loop._handle_exception(ex)
  143. self.writing_handle = None
  144. finally:
  145. self._close()
  146. cdef void __on_uvpoll_event(
  147. uv.uv_poll_t* handle,
  148. int status,
  149. int events,
  150. ) noexcept with gil:
  151. if __ensure_handle_data(<uv.uv_handle_t*>handle, "UVPoll callback") == 0:
  152. return
  153. cdef:
  154. UVPoll poll = <UVPoll> handle.data
  155. if status < 0:
  156. exc = convert_error(status)
  157. poll._fatal_error(exc, False)
  158. return
  159. if ((events & (uv.UV_READABLE | uv.UV_DISCONNECT)) and
  160. poll.reading_handle is not None):
  161. try:
  162. if UVLOOP_DEBUG:
  163. poll._loop._poll_read_events_total += 1
  164. poll.reading_handle._run()
  165. except BaseException as ex:
  166. if UVLOOP_DEBUG:
  167. poll._loop._poll_read_cb_errors_total += 1
  168. poll._error(ex, False)
  169. # continue code execution
  170. if ((events & (uv.UV_WRITABLE | uv.UV_DISCONNECT)) and
  171. poll.writing_handle is not None):
  172. try:
  173. if UVLOOP_DEBUG:
  174. poll._loop._poll_write_events_total += 1
  175. poll.writing_handle._run()
  176. except BaseException as ex:
  177. if UVLOOP_DEBUG:
  178. poll._loop._poll_write_cb_errors_total += 1
  179. poll._error(ex, False)