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)
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
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
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')
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")
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
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
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