We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Upcoming Tornado change breaks gunicorn.workers.gtornado
The next release of Tornado (will be 4.0 when released, although the current master branch hasn't been updated to change all mentions of 3.3 to 4.0) makes some major changes to the HTTP internals and breaks gunicorn's monkey-patching of HTTPConnection.finish.  Fortunately, there is now a cleaner way to do the tracking that gunicorn wants to do here, since the interface between HTTPServer and Application is more formally defined by the HTTPServerConnectionDelegate and HTTPMessageDelegate interfaces, so you should be able to wrap the Application (which implements/subclasses HTTPServerConnectionDelegate) and the HTTPMessageDelegate its start_request method returns.  


--- 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/gtornado.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 import os
7 import sys
8 
9 try:
10     import tornado.web
11 except ImportError:
12     raise RuntimeError("You need tornado installed to use this worker.")
13 import tornado.httpserver
14 from tornado.ioloop import IOLoop, PeriodicCallback
15 from tornado.wsgi import WSGIContainer
16 from gunicorn.workers.base import Worker
17 from gunicorn import __version__ as gversion
18 
19 
20 class TornadoWorker(Worker):
21 
22     @classmethod
23     def setup(cls):
24         web = sys.modules.pop("tornado.web")
25         old_clear = web.RequestHandler.clear
26 
27         def clear(self):
28             old_clear(self)
29             self._headers["Server"] += " (Gunicorn/%s)" % gversion
30         web.RequestHandler.clear = clear
31         sys.modules["tornado.web"] = web
32 
33     def handle_exit(self, sig, frame):
34         if self.alive:
35             super(TornadoWorker, self).handle_exit(sig, frame)
36             self.stop()
37 
38     def handle_request(self):
39         self.nr += 1
40         if self.alive and self.nr >= self.max_requests:
41             self.alive = False
42             self.log.info("Autorestarting worker after current request.")
43             self.stop()
44 
45     def watchdog(self):
46         if self.alive:
47             self.notify()
48 
49         if self.ppid != os.getppid():
50             self.log.info("Parent changed, shutting down: %s", self)
51             self.stop()
52 
53     def run(self):
54         self.ioloop = IOLoop.instance()
55         self.alive = True
56         PeriodicCallback(self.watchdog, 1000, io_loop=self.ioloop).start()
57 
58         # Assume the app is a WSGI callable if its not an
59         # instance of tornado.web.Application or is an
60         # instance of tornado.wsgi.WSGIApplication
61         app = self.wsgi
62         if not isinstance(app, tornado.web.Application) or \
63            isinstance(app, tornado.wsgi.WSGIApplication):
64             app = WSGIContainer(app)
65 
66         # Monkey-patching HTTPConnection.finish to count the
67         # number of requests being handled by Tornado. This
68         # will help gunicorn shutdown the worker if max_requests
69         # is exceeded.
70         httpserver = sys.modules["tornado.httpserver"]
71         old_connection_finish = httpserver.HTTPConnection.finish
72 
73         def finish(other):
74             self.handle_request()
75             old_connection_finish(other)
76         httpserver.HTTPConnection.finish = finish
77         sys.modules["tornado.httpserver"] = httpserver
78 
79         if self.cfg.is_ssl:
80             server = tornado.httpserver.HTTPServer(app, io_loop=self.ioloop,
81                     ssl_options=self.cfg.ssl_options)
82         else:
83             server = tornado.httpserver.HTTPServer(app,
84                     io_loop=self.ioloop)
85 
86         self.server = server
87 
88         for s in self.sockets:
89             s.setblocking(0)
90             if hasattr(server, "add_socket"):  # tornado > 2.0
91                 server.add_socket(s)
92             elif hasattr(server, "_sockets"):  # tornado 2.0
93                 server._sockets[s.fileno()] = s
94 
95         server.no_keep_alive = self.cfg.keepalive <= 0
96         server.start(num_processes=1)
97 
98         self.ioloop.start()
99 
100     def stop(self):
101         if hasattr(self, 'server'):
102             try:
103                 self.server.stop()
104             except Exception:
105                 pass
106         PeriodicCallback(self.stop_ioloop, 1000, io_loop=self.ioloop).start()
107 
108     def stop_ioloop(self):
109         if not self.ioloop._callbacks and len(self.ioloop._timeouts) <= 1:
110             self.ioloop.stop()
111
```
--- 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/gtornado.py b/gunicorn/workers/gtornado.py
--- a/gunicorn/workers/gtornado.py
+++ b/gunicorn/workers/gtornado.py
@@ -68,20 +68,31 @@
         # will help gunicorn shutdown the worker if max_requests
         # is exceeded.
         httpserver = sys.modules["tornado.httpserver"]
-        old_connection_finish = httpserver.HTTPConnection.finish
+        if hasattr(httpserver, 'HTTPConnection'):
+            old_connection_finish = httpserver.HTTPConnection.finish
 
-        def finish(other):
-            self.handle_request()
-            old_connection_finish(other)
-        httpserver.HTTPConnection.finish = finish
-        sys.modules["tornado.httpserver"] = httpserver
+            def finish(other):
+                self.handle_request()
+                old_connection_finish(other)
+            httpserver.HTTPConnection.finish = finish
+            sys.modules["tornado.httpserver"] = httpserver
+
+            server_class = tornado.httpserver.HTTPServer
+        else:
+
+            class _HTTPServer(tornado.httpserver.HTTPServer):
+
+                def on_close(instance, server_conn):
+                    self.handle_request()
+                    super(_HTTPServer, instance).on_close(server_conn)
+
+            server_class = _HTTPServer
 
         if self.cfg.is_ssl:
-            server = tornado.httpserver.HTTPServer(app, io_loop=self.ioloop,
+            server = server_class(app, io_loop=self.ioloop,
                     ssl_options=self.cfg.ssl_options)
         else:
-            server = tornado.httpserver.HTTPServer(app,
-                    io_loop=self.ioloop)
+            server = server_class(app, io_loop=self.ioloop)
 
         self.server = server

{"golden_diff": "diff --git a/gunicorn/workers/gtornado.py b/gunicorn/workers/gtornado.py\n--- a/gunicorn/workers/gtornado.py\n+++ b/gunicorn/workers/gtornado.py\n@@ -68,20 +68,31 @@\n         # will help gunicorn shutdown the worker if max_requests\n         # is exceeded.\n         httpserver = sys.modules[\"tornado.httpserver\"]\n-        old_connection_finish = httpserver.HTTPConnection.finish\n+        if hasattr(httpserver, 'HTTPConnection'):\n+            old_connection_finish = httpserver.HTTPConnection.finish\n \n-        def finish(other):\n-            self.handle_request()\n-            old_connection_finish(other)\n-        httpserver.HTTPConnection.finish = finish\n-        sys.modules[\"tornado.httpserver\"] = httpserver\n+            def finish(other):\n+                self.handle_request()\n+                old_connection_finish(other)\n+            httpserver.HTTPConnection.finish = finish\n+            sys.modules[\"tornado.httpserver\"] = httpserver\n+\n+            server_class = tornado.httpserver.HTTPServer\n+        else:\n+\n+            class _HTTPServer(tornado.httpserver.HTTPServer):\n+\n+                def on_close(instance, server_conn):\n+                    self.handle_request()\n+                    super(_HTTPServer, instance).on_close(server_conn)\n+\n+            server_class = _HTTPServer\n \n         if self.cfg.is_ssl:\n-            server = tornado.httpserver.HTTPServer(app, io_loop=self.ioloop,\n+            server = server_class(app, io_loop=self.ioloop,\n                     ssl_options=self.cfg.ssl_options)\n         else:\n-            server = tornado.httpserver.HTTPServer(app,\n-                    io_loop=self.ioloop)\n+            server = server_class(app, io_loop=self.ioloop)\n \n         self.server = server\n", "issue": "Upcoming Tornado change breaks gunicorn.workers.gtornado\nThe next release of Tornado (will be 4.0 when released, although the current master branch hasn't been updated to change all mentions of 3.3 to 4.0) makes some major changes to the HTTP internals and breaks gunicorn's monkey-patching of HTTPConnection.finish.  Fortunately, there is now a cleaner way to do the tracking that gunicorn wants to do here, since the interface between HTTPServer and Application is more formally defined by the HTTPServerConnectionDelegate and HTTPMessageDelegate interfaces, so you should be able to wrap the Application (which implements/subclasses HTTPServerConnectionDelegate) and the HTTPMessageDelegate its start_request method returns.  \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\nimport os\nimport sys\n\ntry:\n    import tornado.web\nexcept ImportError:\n    raise RuntimeError(\"You need tornado installed to use this worker.\")\nimport tornado.httpserver\nfrom tornado.ioloop import IOLoop, PeriodicCallback\nfrom tornado.wsgi import WSGIContainer\nfrom gunicorn.workers.base import Worker\nfrom gunicorn import __version__ as gversion\n\n\nclass TornadoWorker(Worker):\n\n    @classmethod\n    def setup(cls):\n        web = sys.modules.pop(\"tornado.web\")\n        old_clear = web.RequestHandler.clear\n\n        def clear(self):\n            old_clear(self)\n            self._headers[\"Server\"] += \" (Gunicorn/%s)\" % gversion\n        web.RequestHandler.clear = clear\n        sys.modules[\"tornado.web\"] = web\n\n    def handle_exit(self, sig, frame):\n        if self.alive:\n            super(TornadoWorker, self).handle_exit(sig, frame)\n            self.stop()\n\n    def handle_request(self):\n        self.nr += 1\n        if self.alive and self.nr >= self.max_requests:\n            self.alive = False\n            self.log.info(\"Autorestarting worker after current request.\")\n            self.stop()\n\n    def watchdog(self):\n        if self.alive:\n            self.notify()\n\n        if self.ppid != os.getppid():\n            self.log.info(\"Parent changed, shutting down: %s\", self)\n            self.stop()\n\n    def run(self):\n        self.ioloop = IOLoop.instance()\n        self.alive = True\n        PeriodicCallback(self.watchdog, 1000, io_loop=self.ioloop).start()\n\n        # Assume the app is a WSGI callable if its not an\n        # instance of tornado.web.Application or is an\n        # instance of tornado.wsgi.WSGIApplication\n        app = self.wsgi\n        if not isinstance(app, tornado.web.Application) or \\\n           isinstance(app, tornado.wsgi.WSGIApplication):\n            app = WSGIContainer(app)\n\n        # Monkey-patching HTTPConnection.finish to count the\n        # number of requests being handled by Tornado. This\n        # will help gunicorn shutdown the worker if max_requests\n        # is exceeded.\n        httpserver = sys.modules[\"tornado.httpserver\"]\n        old_connection_finish = httpserver.HTTPConnection.finish\n\n        def finish(other):\n            self.handle_request()\n            old_connection_finish(other)\n        httpserver.HTTPConnection.finish = finish\n        sys.modules[\"tornado.httpserver\"] = httpserver\n\n        if self.cfg.is_ssl:\n            server = tornado.httpserver.HTTPServer(app, io_loop=self.ioloop,\n                    ssl_options=self.cfg.ssl_options)\n        else:\n            server = tornado.httpserver.HTTPServer(app,\n                    io_loop=self.ioloop)\n\n        self.server = server\n\n        for s in self.sockets:\n            s.setblocking(0)\n            if hasattr(server, \"add_socket\"):  # tornado > 2.0\n                server.add_socket(s)\n            elif hasattr(server, \"_sockets\"):  # tornado 2.0\n                server._sockets[s.fileno()] = s\n\n        server.no_keep_alive = self.cfg.keepalive <= 0\n        server.start(num_processes=1)\n\n        self.ioloop.start()\n\n    def stop(self):\n        if hasattr(self, 'server'):\n            try:\n                self.server.stop()\n            except Exception:\n                pass\n        PeriodicCallback(self.stop_ioloop, 1000, io_loop=self.ioloop).start()\n\n    def stop_ioloop(self):\n        if not self.ioloop._callbacks and len(self.ioloop._timeouts) <= 1:\n            self.ioloop.stop()\n", "path": "gunicorn/workers/gtornado.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\nimport os\nimport sys\n\ntry:\n    import tornado.web\nexcept ImportError:\n    raise RuntimeError(\"You need tornado installed to use this worker.\")\nimport tornado.httpserver\nfrom tornado.ioloop import IOLoop, PeriodicCallback\nfrom tornado.wsgi import WSGIContainer\nfrom gunicorn.workers.base import Worker\nfrom gunicorn import __version__ as gversion\n\n\nclass TornadoWorker(Worker):\n\n    @classmethod\n    def setup(cls):\n        web = sys.modules.pop(\"tornado.web\")\n        old_clear = web.RequestHandler.clear\n\n        def clear(self):\n            old_clear(self)\n            self._headers[\"Server\"] += \" (Gunicorn/%s)\" % gversion\n        web.RequestHandler.clear = clear\n        sys.modules[\"tornado.web\"] = web\n\n    def handle_exit(self, sig, frame):\n        if self.alive:\n            super(TornadoWorker, self).handle_exit(sig, frame)\n            self.stop()\n\n    def handle_request(self):\n        self.nr += 1\n        if self.alive and self.nr >= self.max_requests:\n            self.alive = False\n            self.log.info(\"Autorestarting worker after current request.\")\n            self.stop()\n\n    def watchdog(self):\n        if self.alive:\n            self.notify()\n\n        if self.ppid != os.getppid():\n            self.log.info(\"Parent changed, shutting down: %s\", self)\n            self.stop()\n\n    def run(self):\n        self.ioloop = IOLoop.instance()\n        self.alive = True\n        PeriodicCallback(self.watchdog, 1000, io_loop=self.ioloop).start()\n\n        # Assume the app is a WSGI callable if its not an\n        # instance of tornado.web.Application or is an\n        # instance of tornado.wsgi.WSGIApplication\n        app = self.wsgi\n        if not isinstance(app, tornado.web.Application) or \\\n           isinstance(app, tornado.wsgi.WSGIApplication):\n            app = WSGIContainer(app)\n\n        # Monkey-patching HTTPConnection.finish to count the\n        # number of requests being handled by Tornado. This\n        # will help gunicorn shutdown the worker if max_requests\n        # is exceeded.\n        httpserver = sys.modules[\"tornado.httpserver\"]\n        if hasattr(httpserver, 'HTTPConnection'):\n            old_connection_finish = httpserver.HTTPConnection.finish\n\n            def finish(other):\n                self.handle_request()\n                old_connection_finish(other)\n            httpserver.HTTPConnection.finish = finish\n            sys.modules[\"tornado.httpserver\"] = httpserver\n\n            server_class = tornado.httpserver.HTTPServer\n        else:\n\n            class _HTTPServer(tornado.httpserver.HTTPServer):\n\n                def on_close(instance, server_conn):\n                    self.handle_request()\n                    super(_HTTPServer, instance).on_close(server_conn)\n\n            server_class = _HTTPServer\n\n        if self.cfg.is_ssl:\n            server = server_class(app, io_loop=self.ioloop,\n                    ssl_options=self.cfg.ssl_options)\n        else:\n            server = server_class(app, io_loop=self.ioloop)\n\n        self.server = server\n\n        for s in self.sockets:\n            s.setblocking(0)\n            if hasattr(server, \"add_socket\"):  # tornado > 2.0\n                server.add_socket(s)\n            elif hasattr(server, \"_sockets\"):  # tornado 2.0\n                server._sockets[s.fileno()] = s\n\n        server.no_keep_alive = self.cfg.keepalive <= 0\n        server.start(num_processes=1)\n\n        self.ioloop.start()\n\n    def stop(self):\n        if hasattr(self, 'server'):\n            try:\n                self.server.stop()\n            except Exception:\n                pass\n        PeriodicCallback(self.stop_ioloop, 1000, io_loop=self.ioloop).start()\n\n    def stop_ioloop(self):\n        if not self.ioloop._callbacks and len(self.ioloop._timeouts) <= 1:\n            self.ioloop.stop()\n", "path": "gunicorn/workers/gtornado.py"}]}