prompt: We are currently solving the following issue within our repository. Here is the issue text:
  --- BEGIN ISSUE ---
  proxy protocol info lost after first keep-alive request
  env:
  - python v2.7
  - gunicorn v19.1.1
  - gevent v1.0.1 worker type
  - keep-alive proxy-protcol'd lb (aws elb) in front of gunicorn
  
  for multiple reqs during keep-alive session:
  - first parses `req.proxy_protocol_info`
  - subsequent reqs do not
    so workers see only proxy network info (`REMOTE_ADDR`, `REMOTE_PORT` ).
  
  probably should save off from 1st and propagate to later requests.
  
  proxy protocol info lost after first keep-alive request
  env:
  - python v2.7
  - gunicorn v19.1.1
  - gevent v1.0.1 worker type
  - keep-alive proxy-protcol'd lb (aws elb) in front of gunicorn
  
  for multiple reqs during keep-alive session:
  - first parses `req.proxy_protocol_info`
  - subsequent reqs do not
    so workers see only proxy network info (`REMOTE_ADDR`, `REMOTE_PORT` ).
  
  probably should save off from 1st and propagate to later requests.
  
  
  --- 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 import sys
  11 
  12 import gunicorn.http as http
  13 import gunicorn.http.wsgi as wsgi
  14 import gunicorn.util as util
  15 import gunicorn.workers.base as base
  16 from gunicorn import six
  17 
  18 ALREADY_HANDLED = object()
  19 
  20 
  21 class AsyncWorker(base.Worker):
  22 
  23     def __init__(self, *args, **kwargs):
  24         super(AsyncWorker, self).__init__(*args, **kwargs)
  25         self.worker_connections = self.cfg.worker_connections
  26 
  27     def timeout_ctx(self):
  28         raise NotImplementedError()
  29 
  30     def handle(self, listener, client, addr):
  31         req = None
  32         try:
  33             parser = http.RequestParser(self.cfg, client)
  34             try:
  35                 listener_name = listener.getsockname()
  36                 if not self.cfg.keepalive:
  37                     req = six.next(parser)
  38                     self.handle_request(listener_name, req, client, addr)
  39                 else:
  40                     # keepalive loop
  41                     while True:
  42                         req = None
  43                         with self.timeout_ctx():
  44                             req = six.next(parser)
  45                         if not req:
  46                             break
  47                         self.handle_request(listener_name, req, client, addr)
  48             except http.errors.NoMoreData as e:
  49                 self.log.debug("Ignored premature client disconnection. %s", e)
  50             except StopIteration as e:
  51                 self.log.debug("Closing connection. %s", e)
  52             except ssl.SSLError:
  53                 exc_info = sys.exc_info()
  54                 # pass to next try-except level
  55                 six.reraise(exc_info[0], exc_info[1], exc_info[2])
  56             except socket.error:
  57                 exc_info = sys.exc_info()
  58                 # pass to next try-except level
  59                 six.reraise(exc_info[0], exc_info[1], exc_info[2])
  60             except Exception as e:
  61                 self.handle_error(req, client, addr, e)
  62         except ssl.SSLError as e:
  63             if e.args[0] == ssl.SSL_ERROR_EOF:
  64                 self.log.debug("ssl connection closed")
  65                 client.close()
  66             else:
  67                 self.log.debug("Error processing SSL request.")
  68                 self.handle_error(req, client, addr, e)
  69         except socket.error as e:
  70             if e.args[0] not in (errno.EPIPE, errno.ECONNRESET):
  71                 self.log.exception("Socket error processing request.")
  72             else:
  73                 if e.args[0] == errno.ECONNRESET:
  74                     self.log.debug("Ignoring connection reset")
  75                 else:
  76                     self.log.debug("Ignoring EPIPE")
  77         except Exception as e:
  78             self.handle_error(req, client, addr, e)
  79         finally:
  80             util.close(client)
  81 
  82     def handle_request(self, listener_name, req, sock, addr):
  83         request_start = datetime.now()
  84         environ = {}
  85         resp = None
  86         try:
  87             self.cfg.pre_request(self, req)
  88             resp, environ = wsgi.create(req, sock, addr,
  89                     listener_name, self.cfg)
  90             environ["wsgi.multithread"] = True
  91             self.nr += 1
  92             if self.alive and self.nr >= self.max_requests:
  93                 self.log.info("Autorestarting worker after current request.")
  94                 resp.force_close()
  95                 self.alive = False
  96 
  97             if not self.cfg.keepalive:
  98                 resp.force_close()
  99 
  100             respiter = self.wsgi(environ, resp.start_response)
  101             if respiter == ALREADY_HANDLED:
  102                 return False
  103             try:
  104                 if isinstance(respiter, environ['wsgi.file_wrapper']):
  105                     resp.write_file(respiter)
  106                 else:
  107                     for item in respiter:
  108                         resp.write(item)
  109                 resp.close()
  110                 request_time = datetime.now() - request_start
  111                 self.log.access(resp, req, environ, request_time)
  112             finally:
  113                 if hasattr(respiter, "close"):
  114                     respiter.close()
  115             if resp.should_close():
  116                 raise StopIteration()
  117         except StopIteration:
  118             raise
  119         except Exception:
  120             if resp and resp.headers_sent:
  121                 # If the requests have already been sent, we should close the
  122                 # connection to indicate the error.
  123                 self.log.exception("Error handling request")
  124                 try:
  125                     sock.shutdown(socket.SHUT_RDWR)
  126                     sock.close()
  127                 except socket.error:
  128                     pass
  129                 raise StopIteration()
  130             raise
  131         finally:
  132             try:
  133                 self.cfg.post_request(self, req, environ, resp)
  134             except Exception:
  135                 self.log.exception("Exception in post_request hook")
  136         return True
  137
  ```
  --- 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()
  
  ```
  
golden_diff: diff --git a/gunicorn/workers/async.py b/gunicorn/workers/async.py
  --- a/gunicorn/workers/async.py
  +++ b/gunicorn/workers/async.py
  @@ -38,12 +38,14 @@
                       self.handle_request(listener_name, req, client, addr)
                   else:
                       # keepalive loop
  +                    proxy_protocol_info = req.proxy_protocol_info
                       while True:
                           req = None
                           with self.timeout_ctx():
                               req = six.next(parser)
                           if not req:
                               break
  +                        req.proxy_protocol_info = proxy_protocol_info
                           self.handle_request(listener_name, req, client, addr)
               except http.errors.NoMoreData as e:
                   self.log.debug("Ignored premature client disconnection. %s", e)
  
verification_info: {"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@@ -38,12 +38,14 @@\n                     self.handle_request(listener_name, req, client, addr)\n                 else:\n                     # keepalive loop\n+                    proxy_protocol_info = req.proxy_protocol_info\n                     while True:\n                         req = None\n                         with self.timeout_ctx():\n                             req = six.next(parser)\n                         if not req:\n                             break\n+                        req.proxy_protocol_info = proxy_protocol_info\n                         self.handle_request(listener_name, req, client, addr)\n             except http.errors.NoMoreData as e:\n                 self.log.debug(\"Ignored premature client disconnection. %s\", e)\n", "issue": "proxy protocol info lost after first keep-alive request\nenv:\n- python v2.7\n- gunicorn v19.1.1\n- gevent v1.0.1 worker type\n- keep-alive proxy-protcol'd lb (aws elb) in front of gunicorn\n\nfor multiple reqs during keep-alive session:\n- first parses `req.proxy_protocol_info`\n- subsequent reqs do not\n  so workers see only proxy network info (`REMOTE_ADDR`, `REMOTE_PORT` ).\n\nprobably should save off from 1st and propagate to later requests.\n\nproxy protocol info lost after first keep-alive request\nenv:\n- python v2.7\n- gunicorn v19.1.1\n- gevent v1.0.1 worker type\n- keep-alive proxy-protcol'd lb (aws elb) in front of gunicorn\n\nfor multiple reqs during keep-alive session:\n- first parses `req.proxy_protocol_info`\n- subsequent reqs do not\n  so workers see only proxy network info (`REMOTE_ADDR`, `REMOTE_PORT` ).\n\nprobably should save off from 1st and propagate to later requests.\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\nimport sys\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                listener_name = listener.getsockname()\n                if not self.cfg.keepalive:\n                    req = six.next(parser)\n                    self.handle_request(listener_name, 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_name, 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                exc_info = sys.exc_info()\n                # pass to next try-except level\n                six.reraise(exc_info[0], exc_info[1], exc_info[2])\n            except socket.error:\n                exc_info = sys.exc_info()\n                # pass to next try-except level\n                six.reraise(exc_info[0], exc_info[1], exc_info[2])\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_name, 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_name, 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 StopIteration:\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                    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"}], "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\nimport sys\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                listener_name = listener.getsockname()\n                if not self.cfg.keepalive:\n                    req = six.next(parser)\n                    self.handle_request(listener_name, req, client, addr)\n                else:\n                    # keepalive loop\n                    proxy_protocol_info = req.proxy_protocol_info\n                    while True:\n                        req = None\n                        with self.timeout_ctx():\n                            req = six.next(parser)\n                        if not req:\n                            break\n                        req.proxy_protocol_info = proxy_protocol_info\n                        self.handle_request(listener_name, 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                exc_info = sys.exc_info()\n                # pass to next try-except level\n                six.reraise(exc_info[0], exc_info[1], exc_info[2])\n            except socket.error:\n                exc_info = sys.exc_info()\n                # pass to next try-except level\n                six.reraise(exc_info[0], exc_info[1], exc_info[2])\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_name, 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_name, 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 StopIteration:\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                    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"}]}