We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Response silently fails if app_iter returns unicode
If you pass an iterator as your response, and the iterator `yield`s unicode, Gunicorn will silently abort the request.

I'm attaching a pull request to fix this. It may also be worth considering coercing iterator output to strings, to avoid the issue altogether, but I don't know enough to say whether that's appropriate.

Below is a minimal test case to demonstrate the problem. Here are the steps I witnessed, stepping through the response process with pdb. All line numbers are referenced according to [version 18 of gunicorn/workers/sync.py](https://github.com/benoitc/gunicorn/blob/18.0/gunicorn/workers/sync.py).
- In my view: `yield u"test\n"`
- In sync.py, line 137: `resp.write(item)`
- Exception raised: `AssertionError: u'test\n' is not a byte.`
- `Except` clause on line 146 is reached
- `if` condition on line 147 is triggered
- `raise StopIteration()` on line 155 is reached
- `finally` clause on line 159 is reached, bypassing the error handling clause on line 157.

Here's the sample view (written for Pyramid):

```
@view_config(route_name='test')                                                                                                                                                             
def test(request):                                                                                                                                                                          
    def test_():                                                                                                                                                                            
        while True:                                                                                                                                                                         
            yield u"test\n"                                                                                                                                                                 
            time.sleep(.5)                                                                                                                                                                  
    return Response(content_type="text/event-stream", app_iter=test_())
```

Response silently fails if app_iter returns unicode
If you pass an iterator as your response, and the iterator `yield`s unicode, Gunicorn will silently abort the request.

I'm attaching a pull request to fix this. It may also be worth considering coercing iterator output to strings, to avoid the issue altogether, but I don't know enough to say whether that's appropriate.

Below is a minimal test case to demonstrate the problem. Here are the steps I witnessed, stepping through the response process with pdb. All line numbers are referenced according to [version 18 of gunicorn/workers/sync.py](https://github.com/benoitc/gunicorn/blob/18.0/gunicorn/workers/sync.py).
- In my view: `yield u"test\n"`
- In sync.py, line 137: `resp.write(item)`
- Exception raised: `AssertionError: u'test\n' is not a byte.`
- `Except` clause on line 146 is reached
- `if` condition on line 147 is triggered
- `raise StopIteration()` on line 155 is reached
- `finally` clause on line 159 is reached, bypassing the error handling clause on line 157.

Here's the sample view (written for Pyramid):

```
@view_config(route_name='test')                                                                                                                                                             
def test(request):                                                                                                                                                                          
    def test_():                                                                                                                                                                            
        while True:                                                                                                                                                                         
            yield u"test\n"                                                                                                                                                                 
            time.sleep(.5)                                                                                                                                                                  
    return Response(content_type="text/event-stream", app_iter=test_())
```


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `gunicorn/workers/async.py`
Content:
```
1 # -*- coding: utf-8 -
2 #
3 # This file is part of gunicorn released under the MIT license.
4 # See the NOTICE for more information.
5 
6 from datetime import datetime
7 import errno
8 import socket
9 import ssl
10 
11 import gunicorn.http as http
12 import gunicorn.http.wsgi as wsgi
13 import gunicorn.util as util
14 import gunicorn.workers.base as base
15 from gunicorn import six
16 
17 ALREADY_HANDLED = object()
18 
19 
20 class AsyncWorker(base.Worker):
21 
22     def __init__(self, *args, **kwargs):
23         super(AsyncWorker, self).__init__(*args, **kwargs)
24         self.worker_connections = self.cfg.worker_connections
25 
26     def timeout_ctx(self):
27         raise NotImplementedError()
28 
29     def handle(self, listener, client, addr):
30         req = None
31         try:
32             parser = http.RequestParser(self.cfg, client)
33             try:
34                 if not self.cfg.keepalive:
35                     req = six.next(parser)
36                     self.handle_request(listener, req, client, addr)
37                 else:
38                     # keepalive loop
39                     while True:
40                         req = None
41                         with self.timeout_ctx():
42                             req = six.next(parser)
43                         if not req:
44                             break
45                         self.handle_request(listener, req, client, addr)
46             except http.errors.NoMoreData as e:
47                 self.log.debug("Ignored premature client disconnection. %s", e)
48             except StopIteration as e:
49                 self.log.debug("Closing connection. %s", e)
50             except ssl.SSLError:
51                 raise  # pass to next try-except level
52             except socket.error:
53                 raise  # pass to next try-except level
54             except Exception as e:
55                 self.handle_error(req, client, addr, e)
56         except ssl.SSLError as e:
57             if e.args[0] == ssl.SSL_ERROR_EOF:
58                 self.log.debug("ssl connection closed")
59                 client.close()
60             else:
61                 self.log.debug("Error processing SSL request.")
62                 self.handle_error(req, client, addr, e)
63         except socket.error as e:
64             if e.args[0] not in (errno.EPIPE, errno.ECONNRESET):
65                 self.log.exception("Socket error processing request.")
66             else:
67                 if e.args[0] == errno.ECONNRESET:
68                     self.log.debug("Ignoring connection reset")
69                 else:
70                     self.log.debug("Ignoring EPIPE")
71         except Exception as e:
72             self.handle_error(req, client, addr, e)
73         finally:
74             util.close(client)
75 
76     def handle_request(self, listener, req, sock, addr):
77         request_start = datetime.now()
78         environ = {}
79         resp = None
80         try:
81             self.cfg.pre_request(self, req)
82             resp, environ = wsgi.create(req, sock, addr,
83                     listener.getsockname(), self.cfg)
84             environ["wsgi.multithread"] = True
85             self.nr += 1
86             if self.alive and self.nr >= self.max_requests:
87                 self.log.info("Autorestarting worker after current request.")
88                 resp.force_close()
89                 self.alive = False
90 
91             if not self.cfg.keepalive:
92                 resp.force_close()
93 
94             respiter = self.wsgi(environ, resp.start_response)
95             if respiter == ALREADY_HANDLED:
96                 return False
97             try:
98                 if isinstance(respiter, environ['wsgi.file_wrapper']):
99                     resp.write_file(respiter)
100                 else:
101                     for item in respiter:
102                         resp.write(item)
103                 resp.close()
104                 request_time = datetime.now() - request_start
105                 self.log.access(resp, req, environ, request_time)
106             finally:
107                 if hasattr(respiter, "close"):
108                     respiter.close()
109             if resp.should_close():
110                 raise StopIteration()
111         except Exception:
112             if resp and resp.headers_sent:
113                 # If the requests have already been sent, we should close the
114                 # connection to indicate the error.
115                 try:
116                     sock.shutdown(socket.SHUT_RDWR)
117                     sock.close()
118                 except socket.error:
119                     pass
120                 raise StopIteration()
121             raise
122         finally:
123             try:
124                 self.cfg.post_request(self, req, environ, resp)
125             except Exception:
126                 self.log.exception("Exception in post_request hook")
127         return True
128
```

Path: `gunicorn/workers/sync.py`
Content:
```
1 # -*- coding: utf-8 -
2 #
3 # This file is part of gunicorn released under the MIT license.
4 # See the NOTICE for more information.
5 #
6 
7 from datetime import datetime
8 import errno
9 import os
10 import select
11 import socket
12 import ssl
13 
14 import gunicorn.http as http
15 import gunicorn.http.wsgi as wsgi
16 import gunicorn.util as util
17 import gunicorn.workers.base as base
18 from gunicorn import six
19 
20 
21 class SyncWorker(base.Worker):
22 
23     def run(self):
24         # self.socket appears to lose its blocking status after
25         # we fork in the arbiter. Reset it here.
26         for s in self.sockets:
27             s.setblocking(0)
28 
29         ready = self.sockets
30         while self.alive:
31             self.notify()
32 
33             # Accept a connection. If we get an error telling us
34             # that no connection is waiting we fall down to the
35             # select which is where we'll wait for a bit for new
36             # workers to come give us some love.
37 
38             for sock in ready:
39                 try:
40                     client, addr = sock.accept()
41                     client.setblocking(1)
42                     util.close_on_exec(client)
43                     self.handle(sock, client, addr)
44 
45                     # Keep processing clients until no one is waiting. This
46                     # prevents the need to select() for every client that we
47                     # process.
48                     continue
49 
50                 except socket.error as e:
51                     if e.args[0] not in (errno.EAGAIN, errno.ECONNABORTED,
52                             errno.EWOULDBLOCK):
53                         raise
54 
55             # If our parent changed then we shut down.
56             if self.ppid != os.getppid():
57                 self.log.info("Parent changed, shutting down: %s", self)
58                 return
59 
60             try:
61                 self.notify()
62 
63                 # if no timeout is given the worker will never wait and will
64                 # use the CPU for nothing. This minimal timeout prevent it.
65                 timeout = self.timeout or 0.5
66 
67                 ret = select.select(self.sockets, [], self.PIPE, timeout)
68                 if ret[0]:
69                     ready = ret[0]
70                     continue
71             except select.error as e:
72                 if e.args[0] == errno.EINTR:
73                     ready = self.sockets
74                     continue
75                 if e.args[0] == errno.EBADF:
76                     if self.nr < 0:
77                         ready = self.sockets
78                         continue
79                     else:
80                         return
81                 raise
82 
83     def handle(self, listener, client, addr):
84         req = None
85         try:
86             if self.cfg.is_ssl:
87                 client = ssl.wrap_socket(client, server_side=True,
88                     **self.cfg.ssl_options)
89 
90             parser = http.RequestParser(self.cfg, client)
91             req = six.next(parser)
92             self.handle_request(listener, req, client, addr)
93         except http.errors.NoMoreData as e:
94             self.log.debug("Ignored premature client disconnection. %s", e)
95         except StopIteration as e:
96             self.log.debug("Closing connection. %s", e)
97         except ssl.SSLError as e:
98             if e.args[0] == ssl.SSL_ERROR_EOF:
99                 self.log.debug("ssl connection closed")
100                 client.close()
101             else:
102                 self.log.debug("Error processing SSL request.")
103                 self.handle_error(req, client, addr, e)
104         except socket.error as e:
105             if e.args[0] != errno.EPIPE:
106                 self.log.exception("Error processing request.")
107             else:
108                 self.log.debug("Ignoring EPIPE")
109         except Exception as e:
110             self.handle_error(req, client, addr, e)
111         finally:
112             util.close(client)
113 
114     def handle_request(self, listener, req, client, addr):
115         environ = {}
116         resp = None
117         try:
118             self.cfg.pre_request(self, req)
119             request_start = datetime.now()
120             resp, environ = wsgi.create(req, client, addr,
121                     listener.getsockname(), self.cfg)
122             # Force the connection closed until someone shows
123             # a buffering proxy that supports Keep-Alive to
124             # the backend.
125             resp.force_close()
126             self.nr += 1
127             if self.nr >= self.max_requests:
128                 self.log.info("Autorestarting worker after current request.")
129                 self.alive = False
130             respiter = self.wsgi(environ, resp.start_response)
131             try:
132                 if isinstance(respiter, environ['wsgi.file_wrapper']):
133                     resp.write_file(respiter)
134                 else:
135                     for item in respiter:
136                         resp.write(item)
137                 resp.close()
138                 request_time = datetime.now() - request_start
139                 self.log.access(resp, req, environ, request_time)
140             finally:
141                 if hasattr(respiter, "close"):
142                     respiter.close()
143         except socket.error:
144             raise
145         except Exception as e:
146             if resp and resp.headers_sent:
147                 # If the requests have already been sent, we should close the
148                 # connection to indicate the error.
149                 try:
150                     client.shutdown(socket.SHUT_RDWR)
151                     client.close()
152                 except socket.error:
153                     pass
154                 raise StopIteration()
155             # Only send back traceback in HTTP in debug mode.
156             self.handle_error(req, client, addr, e)
157             return
158         finally:
159             try:
160                 self.cfg.post_request(self, req, environ, resp)
161             except Exception:
162                 self.log.exception("Exception in post_request hook")
163
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/gunicorn/workers/async.py b/gunicorn/workers/async.py
--- a/gunicorn/workers/async.py
+++ b/gunicorn/workers/async.py
@@ -112,6 +112,7 @@
             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()
diff --git a/gunicorn/workers/sync.py b/gunicorn/workers/sync.py
--- a/gunicorn/workers/sync.py
+++ b/gunicorn/workers/sync.py
@@ -102,10 +102,13 @@
                 self.log.debug("Error processing SSL request.")
                 self.handle_error(req, client, addr, e)
         except socket.error as e:
-            if e.args[0] != errno.EPIPE:
-                self.log.exception("Error processing request.")
+            if e.args[0] not in (errno.EPIPE, errno.ECONNRESET):
+                self.log.exception("Socket error processing request.")
             else:
-                self.log.debug("Ignoring EPIPE")
+                if e.args[0] == errno.ECONNRESET:
+                    self.log.debug("Ignoring connection reset")
+                else:
+                    self.log.debug("Ignoring EPIPE")
         except Exception as e:
             self.handle_error(req, client, addr, e)
         finally:
@@ -142,19 +145,18 @@
                     respiter.close()
         except socket.error:
             raise
-        except Exception as e:
+        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:
                     client.shutdown(socket.SHUT_RDWR)
                     client.close()
                 except socket.error:
                     pass
                 raise StopIteration()
-            # Only send back traceback in HTTP in debug mode.
-            self.handle_error(req, client, addr, e)
-            return
+            raise
         finally:
             try:
                 self.cfg.post_request(self, req, environ, resp)

{"golden_diff": "diff --git a/gunicorn/workers/async.py b/gunicorn/workers/async.py\n--- a/gunicorn/workers/async.py\n+++ b/gunicorn/workers/async.py\n@@ -112,6 +112,7 @@\n             if resp and resp.headers_sent:\n                 # If the requests have already been sent, we should close the\n                 # connection to indicate the error.\n+                self.log.exception(\"Error handling request\")\n                 try:\n                     sock.shutdown(socket.SHUT_RDWR)\n                     sock.close()\ndiff --git a/gunicorn/workers/sync.py b/gunicorn/workers/sync.py\n--- a/gunicorn/workers/sync.py\n+++ b/gunicorn/workers/sync.py\n@@ -102,10 +102,13 @@\n                 self.log.debug(\"Error processing SSL request.\")\n                 self.handle_error(req, client, addr, e)\n         except socket.error as e:\n-            if e.args[0] != errno.EPIPE:\n-                self.log.exception(\"Error processing request.\")\n+            if e.args[0] not in (errno.EPIPE, errno.ECONNRESET):\n+                self.log.exception(\"Socket error processing request.\")\n             else:\n-                self.log.debug(\"Ignoring EPIPE\")\n+                if e.args[0] == errno.ECONNRESET:\n+                    self.log.debug(\"Ignoring connection reset\")\n+                else:\n+                    self.log.debug(\"Ignoring EPIPE\")\n         except Exception as e:\n             self.handle_error(req, client, addr, e)\n         finally:\n@@ -142,19 +145,18 @@\n                     respiter.close()\n         except socket.error:\n             raise\n-        except Exception as e:\n+        except Exception:\n             if resp and resp.headers_sent:\n                 # If the requests have already been sent, we should close the\n                 # connection to indicate the error.\n+                self.log.exception(\"Error handling request\")\n                 try:\n                     client.shutdown(socket.SHUT_RDWR)\n                     client.close()\n                 except socket.error:\n                     pass\n                 raise StopIteration()\n-            # Only send back traceback in HTTP in debug mode.\n-            self.handle_error(req, client, addr, e)\n-            return\n+            raise\n         finally:\n             try:\n                 self.cfg.post_request(self, req, environ, resp)\n", "issue": "Response silently fails if app_iter returns unicode\nIf you pass an iterator as your response, and the iterator `yield`s unicode, Gunicorn will silently abort the request.\r\n\r\nI'm attaching a pull request to fix this. It may also be worth considering coercing iterator output to strings, to avoid the issue altogether, but I don't know enough to say whether that's appropriate.\r\n\r\nBelow is a minimal test case to demonstrate the problem. Here are the steps I witnessed, stepping through the response process with pdb. All line numbers are referenced according to [version 18 of gunicorn/workers/sync.py](https://github.com/benoitc/gunicorn/blob/18.0/gunicorn/workers/sync.py).\r\n- In my view: `yield u\"test\\n\"`\r\n- In sync.py, line 137: `resp.write(item)`\r\n- Exception raised: `AssertionError: u'test\\n' is not a byte.`\r\n- `Except` clause on line 146 is reached\r\n- `if` condition on line 147 is triggered\r\n- `raise StopIteration()` on line 155 is reached\r\n- `finally` clause on line 159 is reached, bypassing the error handling clause on line 157.\r\n\r\nHere's the sample view (written for Pyramid):\r\n\r\n```\r\n@view_config(route_name='test')                                                                                                                                                             \r\ndef test(request):                                                                                                                                                                          \r\n    def test_():                                                                                                                                                                            \r\n        while True:                                                                                                                                                                         \r\n            yield u\"test\\n\"                                                                                                                                                                 \r\n            time.sleep(.5)                                                                                                                                                                  \r\n    return Response(content_type=\"text/event-stream\", app_iter=test_())\r\n```\r\n\nResponse silently fails if app_iter returns unicode\nIf you pass an iterator as your response, and the iterator `yield`s unicode, Gunicorn will silently abort the request.\r\n\r\nI'm attaching a pull request to fix this. It may also be worth considering coercing iterator output to strings, to avoid the issue altogether, but I don't know enough to say whether that's appropriate.\r\n\r\nBelow is a minimal test case to demonstrate the problem. Here are the steps I witnessed, stepping through the response process with pdb. All line numbers are referenced according to [version 18 of gunicorn/workers/sync.py](https://github.com/benoitc/gunicorn/blob/18.0/gunicorn/workers/sync.py).\r\n- In my view: `yield u\"test\\n\"`\r\n- In sync.py, line 137: `resp.write(item)`\r\n- Exception raised: `AssertionError: u'test\\n' is not a byte.`\r\n- `Except` clause on line 146 is reached\r\n- `if` condition on line 147 is triggered\r\n- `raise StopIteration()` on line 155 is reached\r\n- `finally` clause on line 159 is reached, bypassing the error handling clause on line 157.\r\n\r\nHere's the sample view (written for Pyramid):\r\n\r\n```\r\n@view_config(route_name='test')                                                                                                                                                             \r\ndef test(request):                                                                                                                                                                          \r\n    def test_():                                                                                                                                                                            \r\n        while True:                                                                                                                                                                         \r\n            yield u\"test\\n\"                                                                                                                                                                 \r\n            time.sleep(.5)                                                                                                                                                                  \r\n    return Response(content_type=\"text/event-stream\", app_iter=test_())\r\n```\r\n\n", "before_files": [{"content": "# -*- coding: utf-8 -\n#\n# This file is part of gunicorn released under the MIT license.\n# See the NOTICE for more information.\n\nfrom datetime import datetime\nimport errno\nimport socket\nimport ssl\n\nimport gunicorn.http as http\nimport gunicorn.http.wsgi as wsgi\nimport gunicorn.util as util\nimport gunicorn.workers.base as base\nfrom gunicorn import six\n\nALREADY_HANDLED = object()\n\n\nclass AsyncWorker(base.Worker):\n\n    def __init__(self, *args, **kwargs):\n        super(AsyncWorker, self).__init__(*args, **kwargs)\n        self.worker_connections = self.cfg.worker_connections\n\n    def timeout_ctx(self):\n        raise NotImplementedError()\n\n    def handle(self, listener, client, addr):\n        req = None\n        try:\n            parser = http.RequestParser(self.cfg, client)\n            try:\n                if not self.cfg.keepalive:\n                    req = six.next(parser)\n                    self.handle_request(listener, req, client, addr)\n                else:\n                    # keepalive loop\n                    while True:\n                        req = None\n                        with self.timeout_ctx():\n                            req = six.next(parser)\n                        if not req:\n                            break\n                        self.handle_request(listener, req, client, addr)\n            except http.errors.NoMoreData as e:\n                self.log.debug(\"Ignored premature client disconnection. %s\", e)\n            except StopIteration as e:\n                self.log.debug(\"Closing connection. %s\", e)\n            except ssl.SSLError:\n                raise  # pass to next try-except level\n            except socket.error:\n                raise  # pass to next try-except level\n            except Exception as e:\n                self.handle_error(req, client, addr, e)\n        except ssl.SSLError as e:\n            if e.args[0] == ssl.SSL_ERROR_EOF:\n                self.log.debug(\"ssl connection closed\")\n                client.close()\n            else:\n                self.log.debug(\"Error processing SSL request.\")\n                self.handle_error(req, client, addr, e)\n        except socket.error as e:\n            if e.args[0] not in (errno.EPIPE, errno.ECONNRESET):\n                self.log.exception(\"Socket error processing request.\")\n            else:\n                if e.args[0] == errno.ECONNRESET:\n                    self.log.debug(\"Ignoring connection reset\")\n                else:\n                    self.log.debug(\"Ignoring EPIPE\")\n        except Exception as e:\n            self.handle_error(req, client, addr, e)\n        finally:\n            util.close(client)\n\n    def handle_request(self, listener, req, sock, addr):\n        request_start = datetime.now()\n        environ = {}\n        resp = None\n        try:\n            self.cfg.pre_request(self, req)\n            resp, environ = wsgi.create(req, sock, addr,\n                    listener.getsockname(), self.cfg)\n            environ[\"wsgi.multithread\"] = True\n            self.nr += 1\n            if self.alive and self.nr >= self.max_requests:\n                self.log.info(\"Autorestarting worker after current request.\")\n                resp.force_close()\n                self.alive = False\n\n            if not self.cfg.keepalive:\n                resp.force_close()\n\n            respiter = self.wsgi(environ, resp.start_response)\n            if respiter == ALREADY_HANDLED:\n                return False\n            try:\n                if isinstance(respiter, environ['wsgi.file_wrapper']):\n                    resp.write_file(respiter)\n                else:\n                    for item in respiter:\n                        resp.write(item)\n                resp.close()\n                request_time = datetime.now() - request_start\n                self.log.access(resp, req, environ, request_time)\n            finally:\n                if hasattr(respiter, \"close\"):\n                    respiter.close()\n            if resp.should_close():\n                raise StopIteration()\n        except Exception:\n            if resp and resp.headers_sent:\n                # If the requests have already been sent, we should close the\n                # connection to indicate the error.\n                try:\n                    sock.shutdown(socket.SHUT_RDWR)\n                    sock.close()\n                except socket.error:\n                    pass\n                raise StopIteration()\n            raise\n        finally:\n            try:\n                self.cfg.post_request(self, req, environ, resp)\n            except Exception:\n                self.log.exception(\"Exception in post_request hook\")\n        return True\n", "path": "gunicorn/workers/async.py"}, {"content": "# -*- coding: utf-8 -\n#\n# This file is part of gunicorn released under the MIT license.\n# See the NOTICE for more information.\n#\n\nfrom datetime import datetime\nimport errno\nimport os\nimport select\nimport socket\nimport ssl\n\nimport gunicorn.http as http\nimport gunicorn.http.wsgi as wsgi\nimport gunicorn.util as util\nimport gunicorn.workers.base as base\nfrom gunicorn import six\n\n\nclass SyncWorker(base.Worker):\n\n    def run(self):\n        # self.socket appears to lose its blocking status after\n        # we fork in the arbiter. Reset it here.\n        for s in self.sockets:\n            s.setblocking(0)\n\n        ready = self.sockets\n        while self.alive:\n            self.notify()\n\n            # Accept a connection. If we get an error telling us\n            # that no connection is waiting we fall down to the\n            # select which is where we'll wait for a bit for new\n            # workers to come give us some love.\n\n            for sock in ready:\n                try:\n                    client, addr = sock.accept()\n                    client.setblocking(1)\n                    util.close_on_exec(client)\n                    self.handle(sock, client, addr)\n\n                    # Keep processing clients until no one is waiting. This\n                    # prevents the need to select() for every client that we\n                    # process.\n                    continue\n\n                except socket.error as e:\n                    if e.args[0] not in (errno.EAGAIN, errno.ECONNABORTED,\n                            errno.EWOULDBLOCK):\n                        raise\n\n            # If our parent changed then we shut down.\n            if self.ppid != os.getppid():\n                self.log.info(\"Parent changed, shutting down: %s\", self)\n                return\n\n            try:\n                self.notify()\n\n                # if no timeout is given the worker will never wait and will\n                # use the CPU for nothing. This minimal timeout prevent it.\n                timeout = self.timeout or 0.5\n\n                ret = select.select(self.sockets, [], self.PIPE, timeout)\n                if ret[0]:\n                    ready = ret[0]\n                    continue\n            except select.error as e:\n                if e.args[0] == errno.EINTR:\n                    ready = self.sockets\n                    continue\n                if e.args[0] == errno.EBADF:\n                    if self.nr < 0:\n                        ready = self.sockets\n                        continue\n                    else:\n                        return\n                raise\n\n    def handle(self, listener, client, addr):\n        req = None\n        try:\n            if self.cfg.is_ssl:\n                client = ssl.wrap_socket(client, server_side=True,\n                    **self.cfg.ssl_options)\n\n            parser = http.RequestParser(self.cfg, client)\n            req = six.next(parser)\n            self.handle_request(listener, req, client, addr)\n        except http.errors.NoMoreData as e:\n            self.log.debug(\"Ignored premature client disconnection. %s\", e)\n        except StopIteration as e:\n            self.log.debug(\"Closing connection. %s\", e)\n        except ssl.SSLError as e:\n            if e.args[0] == ssl.SSL_ERROR_EOF:\n                self.log.debug(\"ssl connection closed\")\n                client.close()\n            else:\n                self.log.debug(\"Error processing SSL request.\")\n                self.handle_error(req, client, addr, e)\n        except socket.error as e:\n            if e.args[0] != errno.EPIPE:\n                self.log.exception(\"Error processing request.\")\n            else:\n                self.log.debug(\"Ignoring EPIPE\")\n        except Exception as e:\n            self.handle_error(req, client, addr, e)\n        finally:\n            util.close(client)\n\n    def handle_request(self, listener, req, client, addr):\n        environ = {}\n        resp = None\n        try:\n            self.cfg.pre_request(self, req)\n            request_start = datetime.now()\n            resp, environ = wsgi.create(req, client, addr,\n                    listener.getsockname(), self.cfg)\n            # Force the connection closed until someone shows\n            # a buffering proxy that supports Keep-Alive to\n            # the backend.\n            resp.force_close()\n            self.nr += 1\n            if self.nr >= self.max_requests:\n                self.log.info(\"Autorestarting worker after current request.\")\n                self.alive = False\n            respiter = self.wsgi(environ, resp.start_response)\n            try:\n                if isinstance(respiter, environ['wsgi.file_wrapper']):\n                    resp.write_file(respiter)\n                else:\n                    for item in respiter:\n                        resp.write(item)\n                resp.close()\n                request_time = datetime.now() - request_start\n                self.log.access(resp, req, environ, request_time)\n            finally:\n                if hasattr(respiter, \"close\"):\n                    respiter.close()\n        except socket.error:\n            raise\n        except Exception as e:\n            if resp and resp.headers_sent:\n                # If the requests have already been sent, we should close the\n                # connection to indicate the error.\n                try:\n                    client.shutdown(socket.SHUT_RDWR)\n                    client.close()\n                except socket.error:\n                    pass\n                raise StopIteration()\n            # Only send back traceback in HTTP in debug mode.\n            self.handle_error(req, client, addr, e)\n            return\n        finally:\n            try:\n                self.cfg.post_request(self, req, environ, resp)\n            except Exception:\n                self.log.exception(\"Exception in post_request hook\")\n", "path": "gunicorn/workers/sync.py"}], "after_files": [{"content": "# -*- coding: utf-8 -\n#\n# This file is part of gunicorn released under the MIT license.\n# See the NOTICE for more information.\n\nfrom datetime import datetime\nimport errno\nimport socket\nimport ssl\n\nimport gunicorn.http as http\nimport gunicorn.http.wsgi as wsgi\nimport gunicorn.util as util\nimport gunicorn.workers.base as base\nfrom gunicorn import six\n\nALREADY_HANDLED = object()\n\n\nclass AsyncWorker(base.Worker):\n\n    def __init__(self, *args, **kwargs):\n        super(AsyncWorker, self).__init__(*args, **kwargs)\n        self.worker_connections = self.cfg.worker_connections\n\n    def timeout_ctx(self):\n        raise NotImplementedError()\n\n    def handle(self, listener, client, addr):\n        req = None\n        try:\n            parser = http.RequestParser(self.cfg, client)\n            try:\n                if not self.cfg.keepalive:\n                    req = six.next(parser)\n                    self.handle_request(listener, req, client, addr)\n                else:\n                    # keepalive loop\n                    while True:\n                        req = None\n                        with self.timeout_ctx():\n                            req = six.next(parser)\n                        if not req:\n                            break\n                        self.handle_request(listener, req, client, addr)\n            except http.errors.NoMoreData as e:\n                self.log.debug(\"Ignored premature client disconnection. %s\", e)\n            except StopIteration as e:\n                self.log.debug(\"Closing connection. %s\", e)\n            except ssl.SSLError:\n                raise  # pass to next try-except level\n            except socket.error:\n                raise  # pass to next try-except level\n            except Exception as e:\n                self.handle_error(req, client, addr, e)\n        except ssl.SSLError as e:\n            if e.args[0] == ssl.SSL_ERROR_EOF:\n                self.log.debug(\"ssl connection closed\")\n                client.close()\n            else:\n                self.log.debug(\"Error processing SSL request.\")\n                self.handle_error(req, client, addr, e)\n        except socket.error as e:\n            if e.args[0] not in (errno.EPIPE, errno.ECONNRESET):\n                self.log.exception(\"Socket error processing request.\")\n            else:\n                if e.args[0] == errno.ECONNRESET:\n                    self.log.debug(\"Ignoring connection reset\")\n                else:\n                    self.log.debug(\"Ignoring EPIPE\")\n        except Exception as e:\n            self.handle_error(req, client, addr, e)\n        finally:\n            util.close(client)\n\n    def handle_request(self, listener, req, sock, addr):\n        request_start = datetime.now()\n        environ = {}\n        resp = None\n        try:\n            self.cfg.pre_request(self, req)\n            resp, environ = wsgi.create(req, sock, addr,\n                    listener.getsockname(), self.cfg)\n            environ[\"wsgi.multithread\"] = True\n            self.nr += 1\n            if self.alive and self.nr >= self.max_requests:\n                self.log.info(\"Autorestarting worker after current request.\")\n                resp.force_close()\n                self.alive = False\n\n            if not self.cfg.keepalive:\n                resp.force_close()\n\n            respiter = self.wsgi(environ, resp.start_response)\n            if respiter == ALREADY_HANDLED:\n                return False\n            try:\n                if isinstance(respiter, environ['wsgi.file_wrapper']):\n                    resp.write_file(respiter)\n                else:\n                    for item in respiter:\n                        resp.write(item)\n                resp.close()\n                request_time = datetime.now() - request_start\n                self.log.access(resp, req, environ, request_time)\n            finally:\n                if hasattr(respiter, \"close\"):\n                    respiter.close()\n            if resp.should_close():\n                raise StopIteration()\n        except Exception:\n            if resp and resp.headers_sent:\n                # If the requests have already been sent, we should close the\n                # connection to indicate the error.\n                self.log.exception(\"Error handling request\")\n                try:\n                    sock.shutdown(socket.SHUT_RDWR)\n                    sock.close()\n                except socket.error:\n                    pass\n                raise StopIteration()\n            raise\n        finally:\n            try:\n                self.cfg.post_request(self, req, environ, resp)\n            except Exception:\n                self.log.exception(\"Exception in post_request hook\")\n        return True\n", "path": "gunicorn/workers/async.py"}, {"content": "# -*- coding: utf-8 -\n#\n# This file is part of gunicorn released under the MIT license.\n# See the NOTICE for more information.\n#\n\nfrom datetime import datetime\nimport errno\nimport os\nimport select\nimport socket\nimport ssl\n\nimport gunicorn.http as http\nimport gunicorn.http.wsgi as wsgi\nimport gunicorn.util as util\nimport gunicorn.workers.base as base\nfrom gunicorn import six\n\n\nclass SyncWorker(base.Worker):\n\n    def run(self):\n        # self.socket appears to lose its blocking status after\n        # we fork in the arbiter. Reset it here.\n        for s in self.sockets:\n            s.setblocking(0)\n\n        ready = self.sockets\n        while self.alive:\n            self.notify()\n\n            # Accept a connection. If we get an error telling us\n            # that no connection is waiting we fall down to the\n            # select which is where we'll wait for a bit for new\n            # workers to come give us some love.\n\n            for sock in ready:\n                try:\n                    client, addr = sock.accept()\n                    client.setblocking(1)\n                    util.close_on_exec(client)\n                    self.handle(sock, client, addr)\n\n                    # Keep processing clients until no one is waiting. This\n                    # prevents the need to select() for every client that we\n                    # process.\n                    continue\n\n                except socket.error as e:\n                    if e.args[0] not in (errno.EAGAIN, errno.ECONNABORTED,\n                            errno.EWOULDBLOCK):\n                        raise\n\n            # If our parent changed then we shut down.\n            if self.ppid != os.getppid():\n                self.log.info(\"Parent changed, shutting down: %s\", self)\n                return\n\n            try:\n                self.notify()\n\n                # if no timeout is given the worker will never wait and will\n                # use the CPU for nothing. This minimal timeout prevent it.\n                timeout = self.timeout or 0.5\n\n                ret = select.select(self.sockets, [], self.PIPE, timeout)\n                if ret[0]:\n                    ready = ret[0]\n                    continue\n            except select.error as e:\n                if e.args[0] == errno.EINTR:\n                    ready = self.sockets\n                    continue\n                if e.args[0] == errno.EBADF:\n                    if self.nr < 0:\n                        ready = self.sockets\n                        continue\n                    else:\n                        return\n                raise\n\n    def handle(self, listener, client, addr):\n        req = None\n        try:\n            if self.cfg.is_ssl:\n                client = ssl.wrap_socket(client, server_side=True,\n                    **self.cfg.ssl_options)\n\n            parser = http.RequestParser(self.cfg, client)\n            req = six.next(parser)\n            self.handle_request(listener, req, client, addr)\n        except http.errors.NoMoreData as e:\n            self.log.debug(\"Ignored premature client disconnection. %s\", e)\n        except StopIteration as e:\n            self.log.debug(\"Closing connection. %s\", e)\n        except ssl.SSLError as e:\n            if e.args[0] == ssl.SSL_ERROR_EOF:\n                self.log.debug(\"ssl connection closed\")\n                client.close()\n            else:\n                self.log.debug(\"Error processing SSL request.\")\n                self.handle_error(req, client, addr, e)\n        except socket.error as e:\n            if e.args[0] not in (errno.EPIPE, errno.ECONNRESET):\n                self.log.exception(\"Socket error processing request.\")\n            else:\n                if e.args[0] == errno.ECONNRESET:\n                    self.log.debug(\"Ignoring connection reset\")\n                else:\n                    self.log.debug(\"Ignoring EPIPE\")\n        except Exception as e:\n            self.handle_error(req, client, addr, e)\n        finally:\n            util.close(client)\n\n    def handle_request(self, listener, req, client, addr):\n        environ = {}\n        resp = None\n        try:\n            self.cfg.pre_request(self, req)\n            request_start = datetime.now()\n            resp, environ = wsgi.create(req, client, addr,\n                    listener.getsockname(), self.cfg)\n            # Force the connection closed until someone shows\n            # a buffering proxy that supports Keep-Alive to\n            # the backend.\n            resp.force_close()\n            self.nr += 1\n            if self.nr >= self.max_requests:\n                self.log.info(\"Autorestarting worker after current request.\")\n                self.alive = False\n            respiter = self.wsgi(environ, resp.start_response)\n            try:\n                if isinstance(respiter, environ['wsgi.file_wrapper']):\n                    resp.write_file(respiter)\n                else:\n                    for item in respiter:\n                        resp.write(item)\n                resp.close()\n                request_time = datetime.now() - request_start\n                self.log.access(resp, req, environ, request_time)\n            finally:\n                if hasattr(respiter, \"close\"):\n                    respiter.close()\n        except socket.error:\n            raise\n        except Exception:\n            if resp and resp.headers_sent:\n                # If the requests have already been sent, we should close the\n                # connection to indicate the error.\n                self.log.exception(\"Error handling request\")\n                try:\n                    client.shutdown(socket.SHUT_RDWR)\n                    client.close()\n                except socket.error:\n                    pass\n                raise StopIteration()\n            raise\n        finally:\n            try:\n                self.cfg.post_request(self, req, environ, resp)\n            except Exception:\n                self.log.exception(\"Exception in post_request hook\")\n", "path": "gunicorn/workers/sync.py"}]}