def __init__(self, seconds=None, exception=None): self.seconds = seconds self.exception = exception if seconds is not None: self.timer = get_hub().loop.timer(seconds) else: self.timer = get_hub().loop.timer(0.0)
def _test(self, timeout): try: get_hub().switch() raise AssertionError("Must raise Timeout") except gevent.Timeout, ex: if ex is not timeout: raise
def _read_loop(self): while True: try: frame = None with Timeout(INACTIVITY_TIMEOUT, False): frame = self._reader.read_frame() if frame is None: raise ConnectionTimeoutError() process = self._process_frame_by_type.get(frame.__class__) if process is None: raise InvalidFrameError('received an unsupported frame') process(self, frame) except: e = sys.exc_info()[1] if not isinstance(e, socket_error): log.error('Connection readloop failed', exc_info=True) self._close_with_error(e) break # Nothing else will be read, clean up self._ping_reqs = [] while self._ping_waiters: _, waiters = self._ping_waiters.popitem() for waiter in waiters: get_hub().loop.run_callback(waiter.throw, self._failure) # TODO: settings stuff while self._streams: _, stream = self._streams.popitem() stream._close_with_error(self._failure)
def _test(self, timeout): try: get_hub().switch() self.fail('Must raise Timeout') except gevent.Timeout as ex: if ex is not timeout: raise return ex
def _test(self, timeout): try: get_hub().switch() raise AssertionError('Must raise Timeout') except gevent.Timeout: ex = sys.exc_info()[1] if ex is not timeout: raise
def test(self): try: sock = socket.socket() get_hub().loop.timer(0, sock.close) sock.connect(('python.org', 81)) except Exception: gevent.sleep(0) else: assert False, 'expected an error here'
def signal(signalnum, handler): """ Exactly the same as :func:`signal.signal` except where :const:`signal.SIGCHLD` is concerned. .. note:: A :const:`signal.SIGCHLD` handler installed with this function will only be triggered for children that are forked using :func:`gevent.os.fork` (:func:`gevent.os.fork_and_watch`); children forked before monkey patching, or otherwise by the raw :func:`os.fork`, will not trigger the handler installed by this function. (It's unlikely that a SIGCHLD handler installed with the builtin :func:`signal.signal` would be triggered either; libev typically overwrites such a handler at the C level. At the very least, it's full of race conditions.) .. note:: Use of ``SIG_IGN`` and ``SIG_DFL`` may also have race conditions with libev child watchers and the :mod:`gevent.subprocess` module. .. versionchanged:: 1.2a1 If ``SIG_IGN`` or ``SIG_DFL`` are used to ignore ``SIGCHLD``, a future use of ``gevent.subprocess`` and libev child watchers will once again work. However, on Python 2, use of ``os.popen`` will fail. .. versionchanged:: 1.1rc2 Allow using ``SIG_IGN`` and ``SIG_DFL`` to reset and ignore ``SIGCHLD``. However, this allows the possibility of a race condition if ``gevent.subprocess`` had already been used. """ if signalnum != _signal.SIGCHLD: return _signal_signal(signalnum, handler) # TODO: raise value error if not called from the main # greenlet, just like threads if handler != _signal.SIG_IGN and handler != _signal.SIG_DFL and not callable(handler): # exact same error message raised by the stdlib raise TypeError("signal handler must be signal.SIG_IGN, signal.SIG_DFL, or a callable object") old_handler = getsignal(signalnum) global _child_handler _child_handler = handler if handler in (_signal.SIG_IGN, _signal.SIG_DFL): # Allow resetting/ignoring this signal at the process level. # Note that this conflicts with gevent.subprocess and other users # of child watchers, until the next time gevent.subprocess/loop.install_sigchld() # is called. from gevent.hub import get_hub # Are we always safe to import here? _signal_signal(signalnum, handler) get_hub().loop.reset_sigchld() return old_handler
def _check_context_manager_expires(self, timeout, raises=True): try: with timeout: get_hub().switch() except gevent.Timeout as ex: if ex is not timeout: raise return ex if raises: self.fail("Must raise Timeout")
def acquire(self, blocking=True): if not blocking and self.locked(): return False if self.counter <= 0: self._waiters.add(getcurrent()) try: while self.counter <= 0: get_hub().switch() finally: self._waiters.discard(getcurrent()) self.counter -= 1 return True
def _process_ping_frame(self, frame): if frame.flags & FLAG_PING_ACK: waiters = self._ping_waiters.get(frame.value) if len(waiters) > 1: waiter = waiters.pop(0) elif waiters: del self._ping_waiters[frame.value] waiter = waiters[0] else: waiter = None if waiter is not None: get_hub().loop.run_callback(waiter.switch) else: self._ping_acks.append(frame.value) self._write_ready.set()
def wait(self, timeout=None): """Block until the instance is ready. If this instance already holds a value / an exception, return immediatelly. Otherwise, block until another thread calls :meth:`set` or :meth:`set_exception` or until the optional timeout occurs. When the *timeout* argument is present and not ``None``, it should be a floating point number specifying a timeout for the operation in seconds (or fractions thereof). Return :attr:`value`. """ if self._exception is not _NONE: return self.value else: switch = getcurrent().switch self.rawlink(switch) try: timer = Timeout.start_new(timeout) try: result = get_hub().switch() assert result is self, 'Invalid switch into AsyncResult.wait(): %r' % (result, ) finally: timer.cancel() except Timeout, exc: self.unlink(switch) if exc is not timer: raise except:
def __init__(self, args, bufsize=-1, stdin=None, stdout=None, stderr=None, shell=False, universal_newlines=False, **kwargs): """Create new Popen instance.""" assert not universal_newlines, "universal_newlines must be False" hub = get_hub() self.pid = None self.returncode = None self.universal_newlines = universal_newlines self.result = AsyncResult() self.stdin = None self.stdout = None self.stderr = None self._transport = None if shell: hub.wait_async(hub.loop.subprocess_shell( lambda: _DelegateProtocol(self), *args, stdin=stdin, stdout=stdout, stderr=stderr, bufsize=bufsize, **kwargs)) else: hub.wait_async(hub.loop.subprocess_exec( lambda: _DelegateProtocol(self), *args, stdin=stdin, stdout=stdout, stderr=stderr, bufsize=bufsize, **kwargs))
def _do_wait(self, timeout): """ Wait for up to *timeout* seconds to expire. If timeout elapses, return the exception. Otherwise, return None. Raises timeout if a different timer expires. """ switch = getcurrent().switch self.rawlink(switch) try: # As a tiny efficiency optimization, avoid allocating a timer # if not needed. timer = Timeout.start_new(timeout) if timeout is not None else None try: try: result = get_hub().switch() assert result is self, 'Invalid switch into Semaphore.wait/acquire(): %r' % (result, ) except Timeout as ex: if ex is not timer: raise return ex finally: if timer is not None: timer.cancel() finally: self.unlink(switch)
def __init__(self, value=1): if value < 0: raise ValueError("semaphore initial value must be >= 0") self._links = [] self.counter = value self.hub = get_hub() self._notifier = self.hub.loop.callback()
def wait(io, timeout=None, timeout_exc=_NONE): """ Block the current greenlet until *io* is ready. If *timeout* is non-negative, then *timeout_exc* is raised after *timeout* second has passed. By default *timeout_exc* is ``socket.timeout('timed out')``. If :func:`cancel_wait` is called on *io* by another greenlet, raise an exception in this blocking greenlet (``socket.error(EBADF, 'File descriptor was closed in another greenlet')`` by default). :param io: A libev watcher, most commonly an IO watcher obtained from :meth:`gevent.core.loop.io` :keyword timeout_exc: The exception to raise if the timeout expires. By default, a :class:`socket.timeout` exception is raised. If you pass a value for this keyword, it is interpreted as for :class:`gevent.timeout.Timeout`. """ if io.callback is not None: raise ConcurrentObjectUseError('This socket is already used by another greenlet: %r' % (io.callback, )) if timeout is not None: timeout_exc = timeout_exc if timeout_exc is not _NONE else _timeout_error('timed out') timeout = Timeout.start_new(timeout, timeout_exc) try: return get_hub().wait(io) finally: if timeout is not None: timeout.cancel()
def fork_and_watch(callback=None, loop=None, ref=False, fork=fork): """ Fork a child process and start a child watcher for it in the parent process. This call cooperates with the :func:`gevent.os.waitpid` to enable cooperatively waiting for children to finish. When monkey-patching, these functions are patched in as :func:`os.fork` and :func:`os.waitpid`, respectively. In the child process, this function calls :func:`gevent.hub.reinit` before returning. .. warning:: Forking a process that uses greenlets does not eliminate all non-running greenlets. Any that were scheduled in the hub of the forking thread in the parent remain scheduled in the child; compare this to how normal threads operate. (This behaviour may change is a subsequent major release.) :keyword callback: If given, a callable that will be called with the child watcher when the child finishes. :keyword loop: The loop to start the watcher in. Defaults to the loop of the current hub. :keyword fork: The fork function. Defaults to the one defined in this module (which automatically calls :func:`gevent.hub.reinit`). Pass the builtin :func:`os.fork` function if you do not need to initialize gevent in the child process. .. versionadded: 1.1a3 """ pid = fork() if pid: # parent loop = loop or get_hub().loop watcher = loop.child(pid) _watched_children[pid] = watcher watcher.start(_on_child, watcher, callback) return pid
def apply(*args, **kwargs): sql = args[1:2] moving_average = query_speed.get(sql, None) if moving_average is FAST_ENOUGH: t0 = timefunc() # this query is usually fast so run it directly result = method(*args, **kwargs) duration = timefunc() - t0 if duration >= too_slow: query_speed[sql] = init_moving_average(duration) else: t0 = timefunc() # this query is usually slow so run it in another thread result = get_hub().threadpool.apply(method, args, kwargs) duration = timefunc() - t0 if moving_average is not None: avg = update_average(duration, moving_average) if avg < too_slow: query_speed[sql] = FAST_ENOUGH else: # first time we've seen this query if duration > too_slow: query_speed[sql] = init_moving_average(duration) else: query_speed[sql] = FAST_ENOUGH return result
def wait(self, timeout=None): """Block until the internal flag is true. If the internal flag is true on entry, return immediately. Otherwise, block until another thread calls :meth:`set` to set the flag to true, or until the optional timeout occurs. When the *timeout* argument is present and not ``None``, it should be a floating point number specifying a timeout for the operation in seconds (or fractions thereof). Return the value of the internal flag (``True`` or ``False``). """ if self._flag: return self._flag else: switch = getcurrent().switch self.rawlink(switch) try: timer = Timeout.start_new(timeout) try: try: result = get_hub().switch() assert result is self, 'Invalid switch into Event.wait(): %r' % (result, ) except Timeout, ex: if ex is not timer: raise finally: timer.cancel() finally: self.unlink(switch) return self._flag
def get(self, block=True, timeout=None): """Return the stored value or raise the exception. If this instance already holds a value / an exception, return / raise it immediatelly. Otherwise, block until another greenlet calls :meth:`set` or :meth:`set_exception` or until the optional timeout occurs. When the *timeout* argument is present and not ``None``, it should be a floating point number specifying a timeout for the operation in seconds (or fractions thereof). """ if self._exception is not _NONE: if self._exception is None: return self.value raise self._exception elif block: switch = getcurrent().switch self.rawlink(switch) try: timer = Timeout.start_new(timeout) try: result = get_hub().switch() assert result is self, 'Invalid switch into AsyncResult.get(): %r' % (result, ) finally: timer.cancel() except: self.unlink(switch) raise if self._exception is None: return self.value raise self._exception else: raise Timeout
def wait_readwrite(fileno, timeout=-1, timeout_exc=_socket.timeout('timed out')): evt = core.readwrite_event(fileno, _wait_helper, timeout, (getcurrent(), timeout_exc)) try: switch_result = get_hub().switch() assert evt is switch_result, 'Invalid switch into wait_readwrite(): %r' % (switch_result, ) finally: evt.cancel()
def nb_write(fd, buf): """ Write some number of bytes from buffer *buf* to file descriptor *fd*. Return the number of bytes written, which may be less than the length of *buf*. The file descriptor must be in non-blocking mode. """ hub = None event = None try: while 1: try: result = _write(fd, buf) return result except OSError as e: if e.errno not in ignored_errors: raise if not PY3: sys.exc_clear() if hub is None: hub = get_hub() event = hub.loop.io(fd, 2) hub.wait(event) finally: if event is not None: event.close() event = None hub = None
def fork_and_watch(callback=None, loop=None, ref=False, fork=fork_gevent): """ Fork a child process and start a child watcher for it in the parent process. This call cooperates with :func:`waitpid` to enable cooperatively waiting for children to finish. When monkey-patching, these functions are patched in as :func:`os.fork` and :func:`os.waitpid`, respectively. In the child process, this function calls :func:`gevent.hub.reinit` before returning. Availability: POSIX. :keyword callback: If given, a callable that will be called with the child watcher when the child finishes. :keyword loop: The loop to start the watcher in. Defaults to the loop of the current hub. :keyword fork: The fork function. Defaults to :func:`the one defined in this module <gevent.os.fork_gevent>` (which automatically calls :func:`gevent.hub.reinit`). Pass the builtin :func:`os.fork` function if you do not need to initialize gevent in the child process. .. versionadded:: 1.1b1 .. seealso:: :func:`gevent.monkey.get_original` To access the builtin :func:`os.fork`. """ pid = fork() if pid: # parent loop = loop or get_hub().loop watcher = loop.child(pid, ref=ref) _watched_children[pid] = watcher watcher.start(_on_child, watcher, callback) return pid
def tp_write(fd, buf): """Write bytes from buffer *buf* to file descriptor *fd*. Return the number of bytes written. Writing is done using the threadpool. """ return get_hub().threadpool.apply(_write, (fd, buf))
def wait(self, timeout): evt = get_hub().loop.timer(timeout) evt.start(self.waiter.switch) try: return self.waiter.get() finally: evt.stop()
def __init__(self, run=None, *args, **kwargs): """ Greenlet constructor. :param args: The arguments passed to the ``run`` function. :param kwargs: The keyword arguments passed to the ``run`` function. :keyword run: The callable object to run. If not given, this object's `_run` method will be invoked (typically defined by subclasses). .. versionchanged:: 1.1a3 The ``run`` argument to the constructor is now verified to be a callable object. Previously, passing a non-callable object would fail after the greenlet was spawned. """ hub = get_hub() greenlet.__init__(self, parent=hub) if run is not None: self._run = run # If they didn't pass a callable at all, then they must # already have one. Note that subclassing to override the run() method # itself has never been documented or supported. if not callable(self._run): raise TypeError("The run argument or self._run must be callable") if args: self.args = args if kwargs: self._kwargs = kwargs
def nb_read(fd, n): """ Read up to *n* bytes from file descriptor *fd*. Return a byte string containing the bytes read, which may be shorter than *n*. If end-of-file is reached, an empty string is returned. The descriptor must be in non-blocking mode. """ hub = None event = None try: while 1: try: result = _read(fd, n) return result except OSError as e: if e.errno not in ignored_errors: raise if not PY3: sys.exc_clear() if hub is None: hub = get_hub() event = hub.loop.io(fd, 1) hub.wait(event) finally: if event is not None: event.close() event = None hub = None
def select(rlist, wlist, xlist, timeout=None): """An implementation of :meth:`select.select` that blocks only the current greenlet. Note: *xlist* is ignored. """ watchers = [] loop = get_hub().loop io = loop.io MAXPRI = loop.MAXPRI result = SelectResult() try: try: for readfd in rlist: watcher = io(get_fileno(readfd), 1) watcher.priority = MAXPRI watcher.start(result.add_read, readfd) watchers.append(watcher) for writefd in wlist: watcher = io(get_fileno(writefd), 2) watcher.priority = MAXPRI watcher.start(result.add_write, writefd) watchers.append(watcher) except IOError: ex = sys.exc_info()[1] raise error(*ex.args) result.event.wait(timeout=timeout) return result.read, result.write, [] finally: for watcher in watchers: watcher.stop()
def __init__(self, fobj, *args, **kwargs): """ :param fobj: The underlying file-like object to wrap, or an integer fileno that will be pass to :func:`os.fdopen` along with everything in *args*. :keyword bool lock: If True (the default) then all operations will be performed one-by-one. Note that this does not guarantee that, if using this file object from multiple threads/greenlets, operations will be performed in any particular order, only that no two operations will be attempted at the same time. You can also pass your own :class:`gevent.lock.Semaphore` to synchronize file operations with an external resource. :keyword bool close: If True (the default) then when this object is closed, the underlying object is closed as well. """ self._close = kwargs.pop('close', True) self.threadpool = kwargs.pop('threadpool', None) self.lock = kwargs.pop('lock', True) if kwargs: raise TypeError('Unexpected arguments: %r' % kwargs.keys()) if self.lock is True: self.lock = Semaphore() elif not self.lock: self.lock = DummySemaphore() if not hasattr(self.lock, '__enter__'): raise TypeError('Expected a Semaphore or boolean, got %r' % type(self.lock)) if isinstance(fobj, integer_types): if not self._close: # we cannot do this, since fdopen object will close the descriptor raise TypeError('FileObjectThread does not support close=False') fobj = os.fdopen(fobj, *args) self.io = fobj if self.threadpool is None: self.threadpool = get_hub().threadpool
def _apply_immediately(self): # If we're being called from a different thread than the one that # created us, e.g., because a worker task is trying to use apply() # recursively, we have no choice but to run the task immediately; # if we try to AsyncResult.get() in the worker thread, it's likely to have # nothing to switch to and lead to a LoopExit. return get_hub() is not self.hub
def __init__(self, maxsize=None, items=None): if maxsize is not None and maxsize <= 0: self.maxsize = None if maxsize == 0: import warnings warnings.warn('Queue(0) now equivalent to Queue(None); if you want a channel, use Channel', DeprecationWarning, stacklevel=2) else: self.maxsize = maxsize # Explicitly maintain order for getters and putters that block # so that callers can consistently rely on getting things out # in the apparent order they went in. This was once required by # imap_unordered. Previously these were set() objects, and the # items put in the set have default hash() and eq() methods; # under CPython, since new objects tend to have increasing # hash values, this tended to roughly maintain order anyway, # but that's not true under PyPy. An alternative to a deque # (to avoid the linear scan of remove()) might be an # OrderedDict, but it's 2.7 only; we don't expect to have so # many waiters that removing an arbitrary element is a # bottleneck, though. self.getters = collections.deque() self.putters = collections.deque() self.hub = get_hub() self._event_unlock = None if items: self._init(maxsize, items) else: self._init(maxsize)
def schedule(self, usecs): seconds = usecs / 1000000.0 # This isn't the "clean" way, but it's much quicker.. and # since we're already using undocumented APIs, why not.. _PyxTimer.__init__(self.ev, get_hub().loop, seconds) self.ev.start(self.ready_proxy, 0)
def cancel_wait(watcher): get_hub().cancel_wait(watcher, cancel_wait_ex)
def wait(self, timeout): with get_hub().loop.timer(timeout) as evt: evt.start(self.waiter.switch, None) return self.waiter.get()
def _test_max_pool_size(self, start_request, end_request, max_pool_size=4, nthreads=10): """Start `nthreads` threads. Each calls start_request `start_request` times, then find_one and waits at a barrier; once all reach the barrier each calls end_request `end_request` times. The test asserts that the pool ends with min(max_pool_size, nthreads) sockets or, if start_request wasn't called, at least one socket. This tests both max_pool_size enforcement and that leaked request sockets are eventually returned to the pool when their threads end. You may need to increase ulimit -n on Mac. If you increase nthreads over about 35, note a Gevent 0.13.6 bug on Mac: Greenlet.join() hangs if more than about 35 Greenlets share a MongoClient. Apparently fixed in recent Gevent development. """ if start_request: assert max_pool_size >= nthreads, "Deadlock" c = self.get_client(max_pool_size=max_pool_size, auto_start_request=False) rendezvous = CreateAndReleaseSocket.Rendezvous(nthreads, self.use_greenlets) threads = [] for i in range(nthreads): t = CreateAndReleaseSocket(self, c, start_request, end_request, rendezvous) threads.append(t) for t in threads: t.start() if 'PyPy' in sys.version: # With PyPy we need to kick off the gc whenever the threads hit the # rendezvous since nthreads > max_pool_size. gc_collect_until_done(threads) else: for t in threads: t.join() # join() returns before the thread state is cleared; give it time. self.sleep(1) for t in threads: self.assertTrue(t.passed) # Socket-reclamation doesn't work in Jython if not sys.platform.startswith('java'): cx_pool = c._MongoClient__pool # Socket-reclamation depends on timely garbage-collection if 'PyPy' in sys.version: gc.collect() if self.use_greenlets: # Wait for Greenlet.link() callbacks to execute the_hub = hub.get_hub() if hasattr(the_hub, 'join'): # Gevent 1.0 the_hub.join() else: # Gevent 0.13 and less the_hub.shutdown() if start_request: # Trigger final cleanup in Python <= 2.7.0. cx_pool._ident.get() expected_idle = min(max_pool_size, nthreads) message = ( '%d idle sockets (expected %d) and %d request sockets' ' (expected 0)' % (len(cx_pool.sockets), expected_idle, len(cx_pool._tid_to_sock))) self.assertEqual(expected_idle, len(cx_pool.sockets), message) else: # Without calling start_request(), threads can safely share # sockets; the number running concurrently, and hence the # number of sockets needed, is between 1 and 10, depending # on thread-scheduling. self.assertTrue(len(cx_pool.sockets) >= 1) # thread.join completes slightly *before* thread locals are # cleaned up, so wait up to 5 seconds for them. self.sleep(0.1) cx_pool._ident.get() start = time.time() while (not cx_pool.sockets and cx_pool._socket_semaphore.counter < max_pool_size and (time.time() - start) < 5): self.sleep(0.1) cx_pool._ident.get() self.assertEqual(max_pool_size, cx_pool._socket_semaphore.counter) self.assertEqual(0, len(cx_pool._tid_to_sock))
def threadpool_write(fd, buf): """Write bytes from buffer `buf` to file descriptor `fd`. Return the number of bytes written.""" return get_hub().threadpool.apply(_write, (fd, buf))
def hub(self): # pylint:disable=method-hidden return get_hub()
def spawnv_passfds(path, args, passfds): return get_hub().threadpool.apply(_spawnv_passfd, (path, args, passfds))
def __init__(self): self.getters = collections.deque() self.putters = collections.deque() self.hub = get_hub() self._event_unlock = None
def __init__(self): self.fds = {} # {int -> watcher} self.loop = get_hub().loop
def __init__(self): self._links = deque() self.value = None self._exception = _NONE self.hub = get_hub() self._notifier = None
def start(self, *args): self.x = get_hub().loop.run_callback(*args)
def __call__(self, source): g = greenlet(self.callback, get_hub()) g.switch(source)
</method> <!-- Add more methods/signals if you want --> </interface> </node>""" self.set_response("s", [xml]) conn = GEventDBusConnection(DBUS_BUS_SESSION) handler = GEventHandler() conn.add_handler(handler) print('Listening for signals, with gevent dispatcher.') print('In another terminal, issue:') print() print( ' $ dbus-send --session --type=signal --dest={} /com/example/TDBus com.example.Hello.Hello' .format(conn.get_unique_name())) print( ' $ dbus-send --session --print-reply --type=method_call --dest={} /com/example/TDBus com.example.Hello.HelloMethod' .format(conn.get_unique_name())) print() print('Press CTRL-c to exit.') print() from gevent.hub import get_hub try: get_hub().switch() except KeyboardInterrupt: pass
def __init__(self): self.ev = get_hub().loop.io(0, 0)
try: return _read(fd, n) except OSError, e: if e.errno not in ignored_errors: raise sys.exc_clear() finally: # Be sure to restore the fcntl flags before we switch into the hub. # Sometimes multiple file descriptors share the same fcntl flags # (e.g. when using ttys/ptys). Those other file descriptors are # impacted by our change of flags, so we should restore them # before any other code can possibly run. if not flags & os.O_NONBLOCK: _map_errors(fcntl.fcntl, fd, fcntl.F_SETFL, flags) if hub is None: hub = get_hub() event = hub.loop.io(fd, 1) hub.wait(event) def posix_write(fd, buf): """Write bytes from buffer `buf` to file descriptor `fd`. Return the number of bytes written.""" hub, event = None, None while True: flags = _map_errors(fcntl.fcntl, fd, fcntl.F_GETFL, 0) if not flags & os.O_NONBLOCK: _map_errors(fcntl.fcntl, fd, fcntl.F_SETFL, flags | os.O_NONBLOCK) try: return _write(fd, buf) except OSError, e:
def __init__(self): self.ev = get_hub().loop.timer(0)
def threadpool_read(fd, n): """Read up to `n` bytes from file descriptor `fd`. Return a string containing the bytes read. If end-of-file is reached, an empty string is returned.""" return get_hub().threadpool.apply(_read, (fd, n))
def acquire(self, *args, **kwargs): return get_hub().threadpool.apply(self._acquire, args, kwargs)
def _test_max_pool_size_no_rendezvous(self, start_request, end_request): max_pool_size = 5 c = self.get_client(max_pool_size=max_pool_size, auto_start_request=False) # If you increase nthreads over about 35, note a # Gevent 0.13.6 bug on Mac, Greenlet.join() hangs if more than # about 35 Greenlets share a MongoClient. Apparently fixed in # recent Gevent development. # On the other hand, nthreads had better be much larger than # max_pool_size to ensure that max_pool_size sockets are actually # required at some point in this test's execution. nthreads = 30 if (sys.platform.startswith('java') and start_request > end_request and nthreads > max_pool_size): # Since Jython can't reclaim the socket and release the semaphore # after a thread leaks a request, we'll exhaust the semaphore and # deadlock. raise SkipTest("Jython can't do socket reclamation") threads = [] for i in range(nthreads): t = CreateAndReleaseSocketNoRendezvous(self, c, start_request, end_request) threads.append(t) for t in threads: t.start() if 'PyPy' in sys.version: # With PyPy we need to kick off the gc whenever the threads hit the # rendezvous since nthreads > max_pool_size. gc_collect_until_done(threads) else: for t in threads: t.join() for t in threads: self.assertTrue(t.passed) cx_pool = c._MongoClient__pool # Socket-reclamation depends on timely garbage-collection if 'PyPy' in sys.version: gc.collect() if self.use_greenlets: # Wait for Greenlet.link() callbacks to execute the_hub = hub.get_hub() if hasattr(the_hub, 'join'): # Gevent 1.0 the_hub.join() else: # Gevent 0.13 and less the_hub.shutdown() # thread.join completes slightly *before* thread locals are # cleaned up, so wait up to 5 seconds for them. self.sleep(0.1) cx_pool._ident.get() start = time.time() while (not cx_pool.sockets and cx_pool._socket_semaphore.counter < max_pool_size and (time.time() - start) < 5): self.sleep(0.1) cx_pool._ident.get() self.assertTrue(len(cx_pool.sockets) >= 1) self.assertEqual(max_pool_size, cx_pool._socket_semaphore.counter)
def getnameinfo(sockaddr, flags): return get_hub().resolver.getnameinfo(sockaddr, flags)
def __init__(self, seconds=None, exception=None, ref=True, priority=-1): self.seconds = seconds self.exception = exception self.timer = get_hub().loop.timer(seconds or 0.0, ref=ref, priority=priority)
def tearDown(self): try: del get_hub().handle_error except AttributeError: pass
def getaddrinfo(host, port, family=0, socktype=0, proto=0, flags=0): return get_hub().resolver.getaddrinfo(host, port, family, socktype, proto, flags)
def gethostbyaddr(ip_address): return get_hub().resolver.gethostbyaddr(ip_address)
def __enter__(self): return get_hub().threadpool.apply(super().__enter__)
def gethostbyname_ex(hostname): return get_hub().resolver.gethostbyname_ex(hostname)
def __init__(self): super(GEventIOEvent, self).__init__() self.ev = get_hub().loop.io(0,0)
def __init__(self): super(GEventTimer, self).__init__() self.ev = get_hub().loop.timer(0)
def __init__(self): self._links = set() self._todo = set() self._flag = False self.hub = get_hub() self._notifier = None
def __init__(self, hub=None): if hub is None: hub = get_hub() self.pool = hub.threadpool