예제 #1
0
 def tearDown(self):
     self.http_server.stop()
     self.io_loop.run_sync(self.http_server.close_all_connections,
                           timeout=get_async_test_timeout())
     if (not IOLoop.initialized() or
             self.http_client.io_loop is not IOLoop.instance()):
         self.http_client.close()
     super(AsyncHTTPTestCase, self).tearDown()
예제 #2
0
 def test_force_current(self):
     self.io_loop = IOLoop(make_current=True)
     self.assertIs(self.io_loop, IOLoop.current())
     with self.assertRaises(RuntimeError):
         # A second make_current=True construction cannot succeed.
         IOLoop(make_current=True)
     # current() was not affected by the failed construction.
     self.assertIs(self.io_loop, IOLoop.current())
예제 #3
0
class ReactorTestCase(unittest.TestCase):
    def setUp(self):
        self._saved_signals = save_signal_handlers()
        self._io_loop = IOLoop()
        self._reactor = TornadoReactor(self._io_loop)

    def tearDown(self):
        self._io_loop.close(all_fds=True)
        restore_signal_handlers(self._saved_signals)
예제 #4
0
 def configure_ioloop():
     kwargs = {}
     if options.ioloop_time_monotonic:
         from salt.ext.tornado.platform.auto import monotonic_time
         if monotonic_time is None:
             raise RuntimeError("monotonic clock not found")
         kwargs['time_func'] = monotonic_time
     if options.ioloop or kwargs:
         IOLoop.configure(options.ioloop, **kwargs)
예제 #5
0
    def process_logs(port):
        server = LogServer()
        server.listen(port, address='127.0.0.1')
        try:
            IOLoop.current().start()
        except KeyboardInterrupt:
            pass

        server.stop()
예제 #6
0
파일: gen.py 프로젝트: rjmateus/salt
    def wrapper(*args, **kwargs):
        future = TracebackFuture()

        if replace_callback and 'callback' in kwargs:
            callback = kwargs.pop('callback')
            IOLoop.current().add_future(
                future, lambda future: callback(future.result()))

        try:
            result = func(*args, **kwargs)
        except (Return, StopIteration) as e:
            result = _value_from_stopiteration(e)
        except Exception:
            future.set_exc_info(sys.exc_info())
            return future
        else:
            if isinstance(result, GeneratorType):
                # Inline the first iteration of Runner.run.  This lets us
                # avoid the cost of creating a Runner when the coroutine
                # never actually yields, which in turn allows us to
                # use "optional" coroutines in critical path code without
                # performance penalty for the synchronous case.
                try:
                    orig_stack_contexts = stack_context._state.contexts
                    yielded = next(result)
                    if stack_context._state.contexts is not orig_stack_contexts:
                        yielded = TracebackFuture()
                        yielded.set_exception(
                            stack_context.StackContextInconsistentError(
                                'stack_context inconsistency (probably caused '
                                'by yield within a "with StackContext" block)')
                        )
                except (StopIteration, Return) as e:
                    future.set_result(_value_from_stopiteration(e))
                except Exception:
                    future.set_exc_info(sys.exc_info())
                else:
                    _futures_to_runners[future] = Runner(
                        result, future, yielded)
                yielded = None
                try:
                    return future
                finally:
                    # Subtle memory optimization: if next() raised an exception,
                    # the future's exc_info contains a traceback which
                    # includes this stack frame.  This creates a cycle,
                    # which will be collected at the next full GC but has
                    # been shown to greatly increase memory usage of
                    # benchmarks (relative to the refcount-based scheme
                    # used in the absence of cycles).  We can avoid the
                    # cycle by clearing the local variable after we return it.
                    future = None
        future.set_result(result)
        return future
예제 #7
0
 def start(self):
     old_current = IOLoop.current(instance=False)
     try:
         self._setup_logging()
         self.make_current()
         self.reactor.run()
     finally:
         if old_current is None:
             IOLoop.clear_current()
         else:
             old_current.make_current()
예제 #8
0
 def start(self):
     old_current = IOLoop.current(instance=False)
     try:
         self._setup_logging()
         self.make_current()
         self.asyncio_loop.run_forever()
     finally:
         if old_current is None:
             IOLoop.clear_current()
         else:
             old_current.make_current()
예제 #9
0
class HTTPClient(object):
    """A blocking HTTP client.

    This interface is provided for convenience and testing; most applications
    that are running an IOLoop will want to use `AsyncHTTPClient` instead.
    Typical usage looks like this::

        http_client = httpclient.HTTPClient()
        try:
            response = http_client.fetch("http://www.google.com/")
            print(response.body)
        except httpclient.HTTPError as e:
            # HTTPError is raised for non-200 responses; the response
            # can be found in e.response.
            print("Error: " + str(e))
        except Exception as e:
            # Other errors are possible, such as IOError.
            print("Error: " + str(e))
        http_client.close()
    """
    def __init__(self, async_client_class=None, **kwargs):
        self._io_loop = IOLoop(make_current=False)
        if async_client_class is None:
            async_client_class = AsyncHTTPClient
        self._async_client = async_client_class(self._io_loop, **kwargs)
        self._closed = False

    def __del__(self):
        self.close()

    def close(self):
        """Closes the HTTPClient, freeing any resources used."""
        if not self._closed:
            self._async_client.close()
            self._io_loop.close()
            self._closed = True

    def fetch(self, request, **kwargs):
        """Executes a request, returning an `HTTPResponse`.

        The request may be either a string URL or an `HTTPRequest` object.
        If it is a string, we construct an `HTTPRequest` using any additional
        kwargs: ``HTTPRequest(request, **kwargs)``

        If an error occurs during the fetch, we raise an `HTTPError` unless
        the ``raise_error`` keyword argument is set to False.
        """
        response = self._io_loop.run_sync(
            functools.partial(self._async_client.fetch, request, **kwargs))
        return response
예제 #10
0
 def test_default_current(self):
     self.io_loop = IOLoop()
     # The first IOLoop with default arguments is made current.
     self.assertIs(self.io_loop, IOLoop.current())
     # A second IOLoop can be created but is not made current.
     io_loop2 = IOLoop()
     self.assertIs(self.io_loop, IOLoop.current())
     io_loop2.close()
예제 #11
0
    def test_subprocess(self):
        if IOLoop.configured_class().__name__.endswith('LayeredTwistedIOLoop'):
            # This test fails non-deterministically with LayeredTwistedIOLoop.
            # (the read_until('\n') returns '\n' instead of 'hello\n')
            # This probably indicates a problem with either TornadoReactor
            # or TwistedIOLoop, but I haven't been able to track it down
            # and for now this is just causing spurious travis-ci failures.
            raise unittest.SkipTest("Subprocess tests not compatible with "
                                    "LayeredTwistedIOLoop")
        subproc = Subprocess([sys.executable, '-u', '-i'],
                             stdin=Subprocess.STREAM,
                             stdout=Subprocess.STREAM,
                             stderr=subprocess.STDOUT,
                             io_loop=self.io_loop)
        self.addCleanup(lambda:
                        (subproc.proc.terminate(), subproc.proc.wait()))
        subproc.stdout.read_until(b'>>> ', self.stop)
        self.wait()
        subproc.stdin.write(b"print('hello')\n")
        subproc.stdout.read_until(b'\n', self.stop)
        data = self.wait()
        self.assertEqual(data, b"hello\n")

        subproc.stdout.read_until(b">>> ", self.stop)
        self.wait()
        subproc.stdin.write(b"raise SystemExit\n")
        subproc.stdout.read_until_close(self.stop)
        data = self.wait()
        self.assertEqual(data, b"")
예제 #12
0
 def start_pinging(self):
     """Start sending periodic pings to keep the connection alive"""
     if self.ping_interval > 0:
         self.last_ping = self.last_pong = IOLoop.current().time()
         self.ping_callback = PeriodicCallback(self.periodic_ping,
                                               self.ping_interval * 1000)
         self.ping_callback.start()
예제 #13
0
 def tearDown(self):
     # Clean up Subprocess, so it can be used again with a new ioloop.
     Subprocess.uninitialize()
     self.io_loop.clear_current()
     if (not IOLoop.initialized() or
             self.io_loop is not IOLoop.instance()):
         # Try to clean up any file descriptors left open in the ioloop.
         # This avoids leaks, especially when tests are run repeatedly
         # in the same process with autoreload (because curl does not
         # set FD_CLOEXEC on its file descriptors)
         self.io_loop.close(all_fds=True)
     super(AsyncTestCase, self).tearDown()
     # In case an exception escaped or the StackContext caught an exception
     # when there wasn't a wait() to re-raise it, do so here.
     # This is our last chance to raise an exception in a way that the
     # unittest machinery understands.
     self.__rethrow()
예제 #14
0
    def test_non_current(self):
        self.io_loop = IOLoop(make_current=False)
        # The new IOLoop is not initially made current.
        self.assertIsNone(IOLoop.current(instance=False))
        # Starting the IOLoop makes it current, and stopping the loop
        # makes it non-current. This process is repeatable.
        for i in range(3):

            def f():
                self.current_io_loop = IOLoop.current()
                self.io_loop.stop()

            self.io_loop.add_callback(f)
            self.io_loop.start()
            self.assertIs(self.current_io_loop, self.io_loop)
            # Now that the loop is stopped, it is no longer current.
            self.assertIsNone(IOLoop.current(instance=False))
예제 #15
0
 def __init__(self, resolver=None, io_loop=None):
     self.io_loop = io_loop or IOLoop.current()
     if resolver is not None:
         self.resolver = resolver
         self._own_resolver = False
     else:
         self.resolver = Resolver(io_loop=io_loop)
         self._own_resolver = True
예제 #16
0
def sleep(duration):
    """Return a `.Future` that resolves after the given number of seconds.

    When used with ``yield`` in a coroutine, this is a non-blocking
    analogue to `time.sleep` (which should not be used in coroutines
    because it is blocking)::

        yield gen.sleep(0.5)

    Note that calling this function on its own does nothing; you must
    wait on the `.Future` it returns (usually by yielding it).

    .. versionadded:: 4.1
    """
    f = Future()
    IOLoop.current().call_later(duration, lambda: f.set_result(None))
    return f
예제 #17
0
 def initialize(self, io_loop=None, executor=None, close_executor=True):
     self.io_loop = io_loop or IOLoop.current()
     if executor is not None:
         self.executor = executor
         self.close_executor = close_executor
     else:
         self.executor = dummy_executor
         self.close_executor = False
예제 #18
0
    def __init__(self, future, io_loop=None):
        """Adapts a `.Future` to the `YieldPoint` interface.

        .. versionchanged:: 4.1
           The ``io_loop`` argument is deprecated.
        """
        self.future = future
        self.io_loop = io_loop or IOLoop.current()
예제 #19
0
def save_signal_handlers():
    saved = {}
    for sig in [signal.SIGINT, signal.SIGTERM, signal.SIGCHLD]:
        saved[sig] = signal.getsignal(sig)
    if "twisted" in repr(saved):
        if not issubclass(IOLoop.configured_class(), TwistedIOLoop):
            # when the global ioloop is twisted, we expect the signal
            # handlers to be installed.  Otherwise, it means we're not
            # cleaning up after twisted properly.
            raise Exception("twisted signal handlers already installed")
    return saved
예제 #20
0
    def initialize(self, io_loop=None):
        self.io_loop = io_loop or IOLoop.current()
        # partial copy of twisted.names.client.createResolver, which doesn't
        # allow for a reactor to be passed in.
        self.reactor = tornado.platform.twisted.TornadoReactor(io_loop)

        host_resolver = twisted.names.hosts.Resolver('/etc/hosts')
        cache_resolver = twisted.names.cache.CacheResolver(reactor=self.reactor)
        real_resolver = twisted.names.client.Resolver('/etc/resolv.conf',
                                                      reactor=self.reactor)
        self.resolver = twisted.names.resolve.ResolverChain(
            [host_resolver, cache_resolver, real_resolver])
예제 #21
0
    def test_close_file_object(self):
        """When a file object is used instead of a numeric file descriptor,
        the object should be closed (by IOLoop.close(all_fds=True),
        not just the fd.
        """

        # Use a socket since they are supported by IOLoop on all platforms.
        # Unfortunately, sockets don't support the .closed attribute for
        # inspecting their close status, so we must use a wrapper.
        class SocketWrapper(object):
            def __init__(self, sockobj):
                self.sockobj = sockobj
                self.closed = False

            def fileno(self):
                return self.sockobj.fileno()

            def close(self):
                self.closed = True
                self.sockobj.close()

        sockobj, port = bind_unused_port()
        socket_wrapper = SocketWrapper(sockobj)
        io_loop = IOLoop()
        io_loop.add_handler(socket_wrapper, lambda fd, events: None,
                            IOLoop.READ)
        io_loop.close(all_fds=True)
        self.assertTrue(socket_wrapper.closed)
예제 #22
0
    def run(self):
        """
        Starts the IOLoop of Salt Event Processor
        """
        self.io_loop = IOLoop.current()
        self.event.set()

        opts = salt.config.client_config('/etc/salt/master')
        stream = salt.utils.event.get_event('master', io_loop=self.io_loop,
                                            transport=opts['transport'], opts=opts)
        stream.set_event_handler(self._handle_event_recv)

        self.io_loop.start()
예제 #23
0
    def setUp(self):
        if IOLoop.configured_class().__name__ in ('TwistedIOLoop',
                                                  'AsyncIOMainLoop'):
            # TwistedIOLoop only supports the global reactor, so we can't have
            # separate IOLoops for client and server threads.
            # AsyncIOMainLoop doesn't work with the default policy
            # (although it could with some tweaks to this test and a
            # policy that created loops for non-main threads).
            raise unittest.SkipTest(
                'Sync HTTPClient not compatible with TwistedIOLoop or '
                'AsyncIOMainLoop')
        self.server_ioloop = IOLoop()

        sock, self.port = bind_unused_port()
        app = Application([('/', HelloWorldHandler)])
        self.server = HTTPServer(app, io_loop=self.server_ioloop)
        self.server.add_socket(sock)

        self.server_thread = threading.Thread(target=self.server_ioloop.start)
        self.server_thread.start()

        self.http_client = HTTPClient()
예제 #24
0
 def test_singleton(self):
     # Class "constructor" reuses objects on the same IOLoop
     self.assertTrue(
         SimpleAsyncHTTPClient(self.io_loop) is SimpleAsyncHTTPClient(
             self.io_loop))
     # unless force_instance is used
     self.assertTrue(
         SimpleAsyncHTTPClient(self.io_loop) is not SimpleAsyncHTTPClient(
             self.io_loop, force_instance=True))
     # different IOLoops use different objects
     with closing(IOLoop()) as io_loop2:
         self.assertTrue(
             SimpleAsyncHTTPClient(self.io_loop)
             is not SimpleAsyncHTTPClient(io_loop2))
예제 #25
0
    def test_add_callback_while_closing(self):
        # Issue #635: add_callback() should raise a clean exception
        # if called while another thread is closing the IOLoop.
        if IOLoop.configured_class().__name__.endswith('AsyncIOLoop'):
            raise unittest.SkipTest("AsyncIOMainLoop shutdown not thread safe")
        closing = threading.Event()

        def target():
            other_ioloop.add_callback(other_ioloop.stop)
            other_ioloop.start()
            closing.set()
            other_ioloop.close(all_fds=True)

        other_ioloop = IOLoop()
        thread = threading.Thread(target=target)
        thread.start()
        closing.wait()
        for i in range(1000):
            try:
                other_ioloop.add_callback(lambda: None)
            except RuntimeError as e:
                self.assertEqual("IOLoop is closing", str(e))
                break
예제 #26
0
 def test_add_callback_from_signal_other_thread(self):
     # Very crude test, just to make sure that we cover this case.
     # This also happens to be the first test where we run an IOLoop in
     # a non-main thread.
     other_ioloop = IOLoop()
     thread = threading.Thread(target=other_ioloop.start)
     thread.start()
     other_ioloop.add_callback_from_signal(other_ioloop.stop)
     thread.join()
     other_ioloop.close()
예제 #27
0
    def add_sockets(self, sockets):
        """Makes this server start accepting connections on the given sockets.

        The ``sockets`` parameter is a list of socket objects such as
        those returned by `~tornado.netutil.bind_sockets`.
        `add_sockets` is typically used in combination with that
        method and `tornado.process.fork_processes` to provide greater
        control over the initialization of a multi-process server.
        """
        if self.io_loop is None:
            self.io_loop = IOLoop.current()

        for sock in sockets:
            self._sockets[sock.fileno()] = sock
            add_accept_handler(sock,
                               self._handle_connection,
                               io_loop=self.io_loop)
예제 #28
0
def add_accept_handler(sock, callback, io_loop=None):
    """Adds an `.IOLoop` event handler to accept new connections on ``sock``.

    When a connection is accepted, ``callback(connection, address)`` will
    be run (``connection`` is a socket object, and ``address`` is the
    address of the other end of the connection).  Note that this signature
    is different from the ``callback(fd, events)`` signature used for
    `.IOLoop` handlers.

    .. versionchanged:: 4.1
       The ``io_loop`` argument is deprecated.
    """
    if io_loop is None:
        io_loop = IOLoop.current()

    def accept_handler(fd, events):
        # More connections may come in while we're handling callbacks;
        # to prevent starvation of other tasks we must limit the number
        # of connections we accept at a time.  Ideally we would accept
        # up to the number of connections that were waiting when we
        # entered this method, but this information is not available
        # (and rearranging this method to call accept() as many times
        # as possible before running any callbacks would have adverse
        # effects on load balancing in multiprocess configurations).
        # Instead, we use the (default) listen backlog as a rough
        # heuristic for the number of connections we can reasonably
        # accept at once.
        for i in xrange(_DEFAULT_BACKLOG):
            try:
                connection, address = sock.accept()
            except socket.error as e:
                # _ERRNO_WOULDBLOCK indicate we have accepted every
                # connection that is available.
                if errno_from_exception(e) in _ERRNO_WOULDBLOCK:
                    return
                # ECONNABORTED indicates that there was a connection
                # but it was closed while still in the accept queue.
                # (observed on FreeBSD).
                if errno_from_exception(e) == errno.ECONNABORTED:
                    continue
                raise
            set_close_exec(connection.fileno())
            callback(connection, address)

    io_loop.add_handler(sock, accept_handler, IOLoop.READ)
예제 #29
0
class SyncHTTPClientTest(unittest.TestCase):
    def setUp(self):
        if IOLoop.configured_class().__name__ in ('TwistedIOLoop',
                                                  'AsyncIOMainLoop'):
            # TwistedIOLoop only supports the global reactor, so we can't have
            # separate IOLoops for client and server threads.
            # AsyncIOMainLoop doesn't work with the default policy
            # (although it could with some tweaks to this test and a
            # policy that created loops for non-main threads).
            raise unittest.SkipTest(
                'Sync HTTPClient not compatible with TwistedIOLoop or '
                'AsyncIOMainLoop')
        self.server_ioloop = IOLoop()

        sock, self.port = bind_unused_port()
        app = Application([('/', HelloWorldHandler)])
        self.server = HTTPServer(app, io_loop=self.server_ioloop)
        self.server.add_socket(sock)

        self.server_thread = threading.Thread(target=self.server_ioloop.start)
        self.server_thread.start()

        self.http_client = HTTPClient()

    def tearDown(self):
        def stop_server():
            self.server.stop()
            # Delay the shutdown of the IOLoop by one iteration because
            # the server may still have some cleanup work left when
            # the client finishes with the response (this is noticable
            # with http/2, which leaves a Future with an unexamined
            # StreamClosedError on the loop).
            self.server_ioloop.add_callback(self.server_ioloop.stop)

        self.server_ioloop.add_callback(stop_server)
        self.server_thread.join()
        self.http_client.close()
        self.server_ioloop.close(all_fds=True)

    def get_url(self, path):
        return 'http://127.0.0.1:%d%s' % (self.port, path)

    def test_sync_client(self):
        response = self.http_client.fetch(self.get_url('/'))
        self.assertEqual(b'Hello world!', response.body)

    def test_sync_client_error(self):
        # Synchronous HTTPClient raises errors directly; no need for
        # response.rethrow()
        with self.assertRaises(HTTPError) as assertion:
            self.http_client.fetch(self.get_url('/notfound'))
        self.assertEqual(assertion.exception.code, 404)
예제 #30
0
 def __new__(cls, io_loop=None, force_instance=False, **kwargs):
     io_loop = io_loop or IOLoop.current()
     if force_instance:
         instance_cache = None
     else:
         instance_cache = cls._async_clients()
     if instance_cache is not None and io_loop in instance_cache:
         return instance_cache[io_loop]
     instance = super(AsyncHTTPClient, cls).__new__(cls,
                                                    io_loop=io_loop,
                                                    **kwargs)
     # Make sure the instance knows which cache to remove itself from.
     # It can't simply call _async_clients() because we may be in
     # __new__(AsyncHTTPClient) but instance.__class__ may be
     # SimpleAsyncHTTPClient.
     instance._instance_cache = instance_cache
     if instance_cache is not None:
         instance_cache[instance.io_loop] = instance
     return instance