예제 #1
0
 def test_already_resolved(self):
     future = Future()
     future.set_result('asdf')
     result = yield gen.with_timeout(datetime.timedelta(seconds=3600),
                                     future,
                                     io_loop=self.io_loop)
     self.assertEqual(result, 'asdf')
예제 #2
0
 def test_no_ref(self):
     # In this usage, there is no direct hard reference to the
     # WaitIterator itself, only the Future it returns. Since
     # WaitIterator uses weak references internally to improve GC
     # performance, this used to cause problems.
     yield gen.with_timeout(datetime.timedelta(seconds=0.1),
                            gen.WaitIterator(gen.sleep(0)).next())
예제 #3
0
 def test_completes_before_timeout(self):
     future = Future()
     self.io_loop.add_timeout(datetime.timedelta(seconds=0.1),
                              lambda: future.set_result('asdf'))
     result = yield gen.with_timeout(datetime.timedelta(seconds=3600),
                                     future,
                                     io_loop=self.io_loop)
     self.assertEqual(result, 'asdf')
예제 #4
0
 def test_fails_before_timeout(self):
     future = Future()
     self.io_loop.add_timeout(
         datetime.timedelta(seconds=0.1),
         lambda: future.set_exception(ZeroDivisionError()))
     with self.assertRaises(ZeroDivisionError):
         yield gen.with_timeout(datetime.timedelta(seconds=3600),
                                future,
                                io_loop=self.io_loop)
예제 #5
0
    def wait(self, timeout=None):
        """Block until the internal flag is true.

        Returns a Future, which raises `tornado.gen.TimeoutError` after a
        timeout.
        """
        if timeout is None:
            return self._future
        else:
            return gen.with_timeout(timeout, self._future)
예제 #6
0
    def test_async_with_timeout(self):
        namespace = exec_test(
            globals(), locals(), """
        async def f1():
            return 42
        """)

        result = yield gen.with_timeout(datetime.timedelta(hours=1),
                                        namespace['f1']())
        self.assertEqual(result, 42)
        self.finished = True
예제 #7
0
    def test_gc(self):
        """Runners shouldn't GC if future is alive"""
        # Create the weakref
        weakref_scope = [None]

        def callback():
            gc.collect(2)
            weakref_scope[0]().set_result(123)

        @gen.coroutine
        def tester():
            fut = Future()
            weakref_scope[0] = weakref.ref(fut)
            self.io_loop.add_callback(callback)
            yield fut

        yield gen.with_timeout(datetime.timedelta(seconds=0.2), tester())
예제 #8
0
 def test_completed_concurrent_future(self):
     with futures.ThreadPoolExecutor(1) as executor:
         yield gen.with_timeout(datetime.timedelta(seconds=3600),
                                executor.submit(lambda: None))
예제 #9
0
 def test_timeout_concurrent_future(self):
     with futures.ThreadPoolExecutor(1) as executor:
         with self.assertRaises(gen.TimeoutError):
             yield gen.with_timeout(self.io_loop.time(),
                                    executor.submit(time.sleep, 0.1))
예제 #10
0
 def test_timeout(self):
     with self.assertRaises(gen.TimeoutError):
         yield gen.with_timeout(datetime.timedelta(seconds=0.1), Future())
예제 #11
0
    def _read_message(self, delegate):
        need_delegate_close = False
        try:
            header_future = self.stream.read_until_regex(
                b"\r?\n\r?\n", max_bytes=self.params.max_header_size)
            if self.params.header_timeout is None:
                header_data = yield header_future
            else:
                try:
                    header_data = yield gen.with_timeout(
                        self.stream.io_loop.time() +
                        self.params.header_timeout,
                        header_future,
                        io_loop=self.stream.io_loop,
                        quiet_exceptions=iostream.StreamClosedError)
                except gen.TimeoutError:
                    self.close()
                    raise gen.Return(False)
            start_line, headers = self._parse_headers(header_data)
            if self.is_client:
                start_line = httputil.parse_response_start_line(start_line)
                self._response_start_line = start_line
            else:
                start_line = httputil.parse_request_start_line(start_line)
                self._request_start_line = start_line
                self._request_headers = headers

            self._disconnect_on_finish = not self._can_keep_alive(
                start_line, headers)
            need_delegate_close = True
            with _ExceptionLoggingContext(app_log):
                header_future = delegate.headers_received(start_line, headers)
                if header_future is not None:
                    yield header_future
            if self.stream is None:
                # We've been detached.
                need_delegate_close = False
                raise gen.Return(False)
            skip_body = False
            if self.is_client:
                if (self._request_start_line is not None
                        and self._request_start_line.method == 'HEAD'):
                    skip_body = True
                code = start_line.code
                if code == 304:
                    # 304 responses may include the content-length header
                    # but do not actually have a body.
                    # http://tools.ietf.org/html/rfc7230#section-3.3
                    skip_body = True
                if code >= 100 and code < 200:
                    # 1xx responses should never indicate the presence of
                    # a body.
                    if ('Content-Length' in headers
                            or 'Transfer-Encoding' in headers):
                        raise httputil.HTTPInputError(
                            "Response code %d cannot have body" % code)
                    # TODO: client delegates will get headers_received twice
                    # in the case of a 100-continue.  Document or change?
                    yield self._read_message(delegate)
            else:
                if (headers.get("Expect") == "100-continue"
                        and not self._write_finished):
                    self.stream.write(b"HTTP/1.1 100 (Continue)\r\n\r\n")
            if not skip_body:
                body_future = self._read_body(
                    start_line.code if self.is_client else 0, headers,
                    delegate)
                if body_future is not None:
                    if self._body_timeout is None:
                        yield body_future
                    else:
                        try:
                            yield gen.with_timeout(
                                self.stream.io_loop.time() +
                                self._body_timeout,
                                body_future,
                                self.stream.io_loop,
                                quiet_exceptions=iostream.StreamClosedError)
                        except gen.TimeoutError:
                            gen_log.info("Timeout reading body from %s",
                                         self.context)
                            self.stream.close()
                            raise gen.Return(False)
            self._read_finished = True
            if not self._write_finished or self.is_client:
                need_delegate_close = False
                with _ExceptionLoggingContext(app_log):
                    delegate.finish()
            # If we're waiting for the application to produce an asynchronous
            # response, and we're not detached, register a close callback
            # on the stream (we didn't need one while we were reading)
            if (not self._finish_future.done() and self.stream is not None
                    and not self.stream.closed()):
                self.stream.set_close_callback(self._on_connection_close)
                yield self._finish_future
            if self.is_client and self._disconnect_on_finish:
                self.close()
            if self.stream is None:
                raise gen.Return(False)
        except httputil.HTTPInputError as e:
            gen_log.info("Malformed HTTP message from %s: %s", self.context, e)
            self.close()
            raise gen.Return(False)
        finally:
            if need_delegate_close:
                with _ExceptionLoggingContext(app_log):
                    delegate.on_connection_close()
            header_future = None
            self._clear_callbacks()
        raise gen.Return(True)