Commit 437f12c0 authored by Jason Madden's avatar Jason Madden

libuv unrefs handles when they are started just like libev. fixes some test...

libuv unrefs handles when they are started just like libev. fixes some test timeouts notably test__order.

OTOH, test__queue now fails with LoopExit in many cases (before, only
TestQueue.test_peek_empty failed with a timeout). So we must be missing
a counter subtelty.
parent bc65e21c
......@@ -176,6 +176,10 @@ class watcher(object):
raise NotImplementedError()
def _watcher_ffi_start_unref(self):
# While a watcher is active, we don't keep it
# referenced. This allows a timer, for example, to be started,
# and still allow the loop to end if there is nothing
# else to do. see test__order.TestSleep0 for one example.
self._watcher_ffi_unref()
def _watcher_ffi_stop_ref(self):
......
......@@ -688,7 +688,10 @@ class Hub(RawGreenlet):
loop.run()
finally:
loop.error_handler = None # break the refcount cycle
self.parent.throw(LoopExit('This operation would block forever', self))
debug = []
if hasattr(loop, 'debug'):
debug = loop.debug()
self.parent.throw(LoopExit('This operation would block forever', self, debug))
# this function must never return, as it will cause switch() in the parent greenlet
# to return an unexpected value
# It is still possible to kill this greenlet with throw. However, in that case
......
......@@ -6,6 +6,7 @@ from __future__ import absolute_import, print_function
import os
from collections import defaultdict
from collections import namedtuple
import signal
......@@ -112,6 +113,36 @@ class loop(AbstractLoop):
closed_failed = libuv.uv_loop_close(ptr)
assert not closed_failed, closed_failed
def debug(self):
"""
Return all the handles that are open and their ref status.
"""
handle_state = namedtuple("HandleState",
['handle',
'watcher',
'ref',
'active',
'closing'])
handles = []
def walk(handle, _arg):
data = handle.data
if data:
watcher = ffi.from_handle(data)
else:
watcher = None
handles.append(handle_state(handle,
watcher,
libuv.uv_has_ref(handle),
libuv.uv_is_active(handle),
libuv.uv_is_closing(handle)))
libuv.uv_walk(self._ptr,
ffi.callback("void(*)(uv_handle_t*,void*)",
walk),
ffi.NULL)
return handles
def ref(self):
pass
......
......@@ -81,14 +81,6 @@ class watcher(_base.watcher):
def _watcher_ffi_unref(self):
libuv.uv_unref(self._watcher)
def _watcher_ffi_start_unref(self):
# libev manipulates these refs at start and stop for
# some reason; we don't
pass
def _watcher_ffi_stop_ref(self):
pass
def _get_ref(self):
# Convert 1/0 to True/False
return True if libuv.uv_has_ref(self._watcher) else False
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment