Esempio n. 1
0
    def handle(self, server_sock, client_sock, addr):
        """Handle client connection

        The client may send one or more requests.
        """
        req = None
        try:
            parser = http.RequestParser(self.cfg, client_sock)
            try:
                server_name = server_sock.getsockname()
                if not self.cfg.keepalive:
                    req = next(parser)
                    self.handle_request(server_name, req, client_sock, addr)
                else:
                    # keepalive loop
                    while True:
                        req = None
                        with self.timeout_ctx():
                            req = next(parser)
                        if not req:
                            break
                        self.handle_request(server_name, req, client_sock, addr)
                        gyield()
            except http.errors.NoMoreData as e:
                self.log.debug("Ignored premature client disconnection. %s", e)
            except StopIteration as e:
                self.log.debug("Closing connection. %s", e)
            except ssl.SSLError:
                exc_info = sys.exc_info()
                # pass to next try-except level
                reraise(exc_info[0], exc_info[1], exc_info[2])
            except socket.error:
                exc_info = sys.exc_info()
                # pass to next try-except level
                reraise(exc_info[0], exc_info[1], exc_info[2])
            except Exception as e:
                self.handle_error(req, client_sock, addr, e)
        except ssl.SSLError as e:
            if get_errno(e) == ssl.SSL_ERROR_EOF:
                self.log.debug("ssl connection closed")
                client_sock.close()
            else:
                self.log.debug("Error processing SSL request.")
                self.handle_error(req, client_sock, addr, e)
        except socket.error as e:
            if get_errno(e) not in BROKEN_SOCK:
                self.log.exception("Socket error processing request.")
            else:
                if get_errno(e) == errno.ECONNRESET:
                    self.log.debug("Ignoring connection reset")
                else:
                    self.log.debug("Ignoring EPIPE")
        except Exception as e:
            self.handle_error(req, client_sock, addr, e)
        finally:
            util.close(client_sock)
Esempio n. 2
0
    def handle_read(self):
        while True:
            try:
                log.debug('Trampoline on fd: {}, READ'.format(self._socket.fileno()))
                trampoline(self._socket.fileno(), READ)
            except Exception as exc:
                if not self.is_closed:
                    log.debug("Exception during read trampoline() for %s: %s", self, exc)
                    self.defunct(exc)
                    return

            try:
                while True:
                    buf = self._socket.recv(self.in_buffer_size)
                    self._iobuf.write(buf)
                    if len(buf) < self.in_buffer_size:
                        break
            except socket.error as err:
                if not get_errno(err) in CONNECT_ERR:
                    log.debug('Exception during socket recv for %s: %s', self, err)
                    self.defunct(err)
                    return  # leave the read loop

            if self._iobuf.tell():
                self.process_io_buffer()
            else:
                log.debug('Connection %s closed by server', self)
                self.close()
                return
Esempio n. 3
0
    def handle_request(self, listener_name, req, sock, addr):
        request_start = datetime.now()
        environ = {}
        resp = None
        try:
            self.cfg.pre_request(self, req)
            resp, environ = wsgi.create(req, sock, addr,
                                        listener_name, self.cfg)
            environ["wsgi.multithread"] = True
            self.nr += 1
            if self.alive and self.nr >= self.max_requests:
                self.log.info("Autorestarting worker after current request.")
                resp.force_close()
                self.alive = False

            if not self.cfg.keepalive:
                resp.force_close()

            respiter = self.wsgi(environ, resp.start_response)
            if respiter == ALREADY_HANDLED:
                return False
            try:
                if isinstance(respiter, environ['wsgi.file_wrapper']):
                    resp.write_file(respiter)
                else:
                    for item in respiter:
                        resp.write(item)
                resp.close()
                request_time = datetime.now() - request_start
                self.log.access(resp, req, environ, request_time)
            except socket.error as e:
                # BROKEN_SOCK not interesting here
                if not get_errno(e) in BROKEN_SOCK:
                    raise
            finally:
                if hasattr(respiter, "close"):
                    respiter.close()
            if resp.should_close():
                raise StopIteration()
        except StopIteration:
            raise
        except Exception:
            if resp and resp.headers_sent:
                # If the requests have already been sent, we should close the
                # connection to indicate the error.
                self.log.exception("Error handling request")
                try:
                    sock.shutdown(socket.SHUT_RDWR)
                    sock.close()
                except socket.error:
                    pass
                raise StopIteration()
            raise
        finally:
            try:
                self.cfg.post_request(self, req, environ, resp)
            except Exception:
                self.log.exception("Exception in post_request hook")
        return True
Esempio n. 4
0
    def test_send_to_closed_sock_raises(self, gsock):
        try:
            gsock.send(b'hello')
        except socket.error as e:
            assert get_errno(e) == errno.EPIPE

        if pyversion >= (3, 3):
            # on python 3.3+, the exception can be caught like this as well
            with pytest.raises(BrokenPipeError):
                gsock.send(b'hello')
Esempio n. 5
0
    def test_send_to_closed_sock_raises(self, gsock):
        try:
            gsock.send(b"hello")
        except socket.error as e:
            assert get_errno(e) == errno.EPIPE

        if pyversion >= (3, 3):
            # on python 3.3+, the exception can be caught like this as well
            with pytest.raises(BrokenPipeError):
                gsock.send(b"hello")
Esempio n. 6
0
 def test_create_connection_timeout_error(self, fail_addr):
     # Inspired by eventlet Greenio_test
     try:
         socket_patched.create_connection(fail_addr, timeout=0.01)
         pytest.fail('Timeout not raised')
     except socket.timeout as e:
         assert str(e) == 'timed out'
     except socket.error as e:
         # unreachable is also a valid outcome
         if not get_errno(e) in (errno.EHOSTUNREACH, errno.ENETUNREACH):
             raise
Esempio n. 7
0
 def test_create_connection_timeout_error(self, fail_addr):
     # Inspired by eventlet Greenio_test
     try:
         socket_patched.create_connection(fail_addr, timeout=0.01)
         pytest.fail("Timeout not raised")
     except socket.timeout as e:
         assert str(e) == "timed out"
     except socket.error as e:
         # unreachable is also a valid outcome
         if not get_errno(e) in (errno.EHOSTUNREACH, errno.ENETUNREACH):
             raise
Esempio n. 8
0
def _guv_sendfile(fdout, fdin, offset, nbytes):
    while True:
        try:
            return o_sendfile(fdout, fdin, offset, nbytes)
        except OSError as e:
            if get_errno(e) == errno.EAGAIN:
                if not isinstance(fdout, int):
                    fd = fdout.fileno()
                else:
                    fd = fdout
                trampoline(fd, WRITE)
            else:
                raise