We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
does not work HTTPS on gunicorn 19.3.0 and tornado 4.3
I'm not sure this is a problem on gunicorn, but please ask a question here.
I'm working on an implementation simple tornado app and it works on gunicorn, also it listen HTTPS. It worked great with gunicorn 18.0 + tornado 3.0.
However, after doing I upgrade gunicorn to 19.3.0 for using `ca-certs` option (also upgrade tornado to 4..2.1), it does not work fine.

If someone point out the cause of this is which one gunicorn or tornado, it would be great help to me.

here is a starting command line.

```
$ gunicorn --certfile=/home/hiro/201510/server.crt --keyfile=/home/hiro/201510/server.key -b 0.0.0.0:16189 -w 1 -k "tornado" 'httpproxy:get_service("tcp://0.0.0.0:5555")'
```

and stacktrace is following:

```
[2015-10-27 20:29:04 +0000] [4360] [INFO] Booting worker with pid: 4360
ERROR:tornado.application:Exception in callback (<gunicorn.sock.TCPSocket object at 0x2a6bc50>, <function null_wrapper at 0x2c91488>)
Traceback (most recent call last):
  File "/home/hiro/.virtualenvs/CP275_asyncproxy/lib/python2.7/site-packages/tornado/ioloop.py", line 866, in start
    handler_func(fd_obj, events)
  File "/home/hiro/.virtualenvs/CP275_asyncproxy/lib/python2.7/site-packages/tornado/stack_context.py", line 275, in null_wrapper
    return fn(*args, **kwargs)
  File "/home/hiro/.virtualenvs/CP275_asyncproxy/lib/python2.7/site-packages/tornado/netutil.py", line 265, in accept_handler
    callback(connection, address)
  File "/home/hiro/.virtualenvs/CP275_asyncproxy/lib/python2.7/site-packages/tornado/tcpserver.py", line 239, in _handle_connection
    do_handshake_on_connect=False)
  File "/home/hiro/.virtualenvs/CP275_asyncproxy/lib/python2.7/site-packages/tornado/netutil.py", line 501, in ssl_wrap_socket
    context = ssl_options_to_context(ssl_options)
  File "/home/hiro/.virtualenvs/CP275_asyncproxy/lib/python2.7/site-packages/tornado/netutil.py", line 471, in ssl_options_to_context
    assert all(k in _SSL_CONTEXT_KEYWORDS for k in ssl_options), ssl_options
AssertionError: {'do_handshake_on_connect': False, 'certfile': '/home/hiro/201510/server.crt', 'suppress_ragged_eofs': True, 'ciphers': 'TLSv1', 'ssl_version': 3, 'cert_reqs': 0, 'ca_certs': None, 'keyfile': '/home/hiro/201510/server.key'}
```

`_SSL_CONTEXT_KEYWORDS` declared in `netutil.py` is following:

```
_SSL_CONTEXT_KEYWORDS = frozenset(['ssl_version', 'certfile', 'keyfile',
                                   'cert_reqs', 'ca_certs', 'ciphers'])
```


--- 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 
37     def handle_request(self):
38         self.nr += 1
39         if self.alive and self.nr >= self.max_requests:
40             self.log.info("Autorestarting worker after current request.")
41             self.alive = False
42 
43     def watchdog(self):
44         if self.alive:
45             self.notify()
46 
47         if self.ppid != os.getppid():
48             self.log.info("Parent changed, shutting down: %s", self)
49             self.alive = False
50 
51     def heartbeat(self):
52         if not self.alive:
53             if self.server_alive:
54                 if hasattr(self, 'server'):
55                     try:
56                         self.server.stop()
57                     except Exception:
58                         pass
59                 self.server_alive = False
60             else:
61                 if not self.ioloop._callbacks:
62                     self.ioloop.stop()
63 
64     def run(self):
65         self.ioloop = IOLoop.instance()
66         self.alive = True
67         self.server_alive = False
68         PeriodicCallback(self.watchdog, 1000, io_loop=self.ioloop).start()
69         PeriodicCallback(self.heartbeat, 1000, io_loop=self.ioloop).start()
70 
71         # Assume the app is a WSGI callable if its not an
72         # instance of tornado.web.Application or is an
73         # instance of tornado.wsgi.WSGIApplication
74         app = self.wsgi
75         if not isinstance(app, tornado.web.Application) or \
76            isinstance(app, tornado.wsgi.WSGIApplication):
77             app = WSGIContainer(app)
78 
79         # Monkey-patching HTTPConnection.finish to count the
80         # number of requests being handled by Tornado. This
81         # will help gunicorn shutdown the worker if max_requests
82         # is exceeded.
83         httpserver = sys.modules["tornado.httpserver"]
84         if hasattr(httpserver, 'HTTPConnection'):
85             old_connection_finish = httpserver.HTTPConnection.finish
86 
87             def finish(other):
88                 self.handle_request()
89                 old_connection_finish(other)
90             httpserver.HTTPConnection.finish = finish
91             sys.modules["tornado.httpserver"] = httpserver
92 
93             server_class = tornado.httpserver.HTTPServer
94         else:
95 
96             class _HTTPServer(tornado.httpserver.HTTPServer):
97 
98                 def on_close(instance, server_conn):
99                     self.handle_request()
100                     super(_HTTPServer, instance).on_close(server_conn)
101 
102             server_class = _HTTPServer
103 
104         if self.cfg.is_ssl:
105             server = server_class(app, io_loop=self.ioloop,
106                     ssl_options=self.cfg.ssl_options)
107         else:
108             server = server_class(app, io_loop=self.ioloop)
109 
110         self.server = server
111         self.server_alive = True
112 
113         for s in self.sockets:
114             s.setblocking(0)
115             if hasattr(server, "add_socket"):  # tornado > 2.0
116                 server.add_socket(s)
117             elif hasattr(server, "_sockets"):  # tornado 2.0
118                 server._sockets[s.fileno()] = s
119 
120         server.no_keep_alive = self.cfg.keepalive <= 0
121         server.start(num_processes=1)
122 
123         self.ioloop.start()
124
```
--- 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
@@ -3,6 +3,7 @@
 # This file is part of gunicorn released under the MIT license.
 # See the NOTICE for more information.
 
+import copy
 import os
 import sys
 
@@ -102,8 +103,13 @@
             server_class = _HTTPServer
 
         if self.cfg.is_ssl:
+             _ssl_opt = copy.deepcopy(self.cfg.ssl_options)
+             # tornado refuses initialization if ssl_options contains following
+             # options
+             del _ssl_opt["do_handshake_on_connect"]
+             del _ssl_opt["suppress_ragged_eofs"]
             server = server_class(app, io_loop=self.ioloop,
-                    ssl_options=self.cfg.ssl_options)
+                    ssl_options=_ssl_opt)
         else:
             server = server_class(app, io_loop=self.ioloop)

{"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@@ -3,6 +3,7 @@\n # This file is part of gunicorn released under the MIT license.\n # See the NOTICE for more information.\n \n+import copy\n import os\n import sys\n \n@@ -102,8 +103,13 @@\n             server_class = _HTTPServer\n \n         if self.cfg.is_ssl:\n+             _ssl_opt = copy.deepcopy(self.cfg.ssl_options)\n+             # tornado refuses initialization if ssl_options contains following\n+             # options\n+             del _ssl_opt[\"do_handshake_on_connect\"]\n+             del _ssl_opt[\"suppress_ragged_eofs\"]\n             server = server_class(app, io_loop=self.ioloop,\n-                    ssl_options=self.cfg.ssl_options)\n+                    ssl_options=_ssl_opt)\n         else:\n             server = server_class(app, io_loop=self.ioloop)\n", "issue": "does not work HTTPS on gunicorn 19.3.0 and tornado 4.3\nI'm not sure this is a problem on gunicorn, but please ask a question here.\nI'm working on an implementation simple tornado app and it works on gunicorn, also it listen HTTPS. It worked great with gunicorn 18.0 + tornado 3.0.\nHowever, after doing I upgrade gunicorn to 19.3.0 for using `ca-certs` option (also upgrade tornado to 4..2.1), it does not work fine.\n\nIf someone point out the cause of this is which one gunicorn or tornado, it would be great help to me.\n\nhere is a starting command line.\n\n```\n$ gunicorn --certfile=/home/hiro/201510/server.crt --keyfile=/home/hiro/201510/server.key -b 0.0.0.0:16189 -w 1 -k \"tornado\" 'httpproxy:get_service(\"tcp://0.0.0.0:5555\")'\n```\n\nand stacktrace is following:\n\n```\n[2015-10-27 20:29:04 +0000] [4360] [INFO] Booting worker with pid: 4360\nERROR:tornado.application:Exception in callback (<gunicorn.sock.TCPSocket object at 0x2a6bc50>, <function null_wrapper at 0x2c91488>)\nTraceback (most recent call last):\n  File \"/home/hiro/.virtualenvs/CP275_asyncproxy/lib/python2.7/site-packages/tornado/ioloop.py\", line 866, in start\n    handler_func(fd_obj, events)\n  File \"/home/hiro/.virtualenvs/CP275_asyncproxy/lib/python2.7/site-packages/tornado/stack_context.py\", line 275, in null_wrapper\n    return fn(*args, **kwargs)\n  File \"/home/hiro/.virtualenvs/CP275_asyncproxy/lib/python2.7/site-packages/tornado/netutil.py\", line 265, in accept_handler\n    callback(connection, address)\n  File \"/home/hiro/.virtualenvs/CP275_asyncproxy/lib/python2.7/site-packages/tornado/tcpserver.py\", line 239, in _handle_connection\n    do_handshake_on_connect=False)\n  File \"/home/hiro/.virtualenvs/CP275_asyncproxy/lib/python2.7/site-packages/tornado/netutil.py\", line 501, in ssl_wrap_socket\n    context = ssl_options_to_context(ssl_options)\n  File \"/home/hiro/.virtualenvs/CP275_asyncproxy/lib/python2.7/site-packages/tornado/netutil.py\", line 471, in ssl_options_to_context\n    assert all(k in _SSL_CONTEXT_KEYWORDS for k in ssl_options), ssl_options\nAssertionError: {'do_handshake_on_connect': False, 'certfile': '/home/hiro/201510/server.crt', 'suppress_ragged_eofs': True, 'ciphers': 'TLSv1', 'ssl_version': 3, 'cert_reqs': 0, 'ca_certs': None, 'keyfile': '/home/hiro/201510/server.key'}\n```\n\n`_SSL_CONTEXT_KEYWORDS` declared in `netutil.py` is following:\n\n```\n_SSL_CONTEXT_KEYWORDS = frozenset(['ssl_version', 'certfile', 'keyfile',\n                                   'cert_reqs', 'ca_certs', 'ciphers'])\n```\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\n    def handle_request(self):\n        self.nr += 1\n        if self.alive and self.nr >= self.max_requests:\n            self.log.info(\"Autorestarting worker after current request.\")\n            self.alive = False\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.alive = False\n\n    def heartbeat(self):\n        if not self.alive:\n            if self.server_alive:\n                if hasattr(self, 'server'):\n                    try:\n                        self.server.stop()\n                    except Exception:\n                        pass\n                self.server_alive = False\n            else:\n                if not self.ioloop._callbacks:\n                    self.ioloop.stop()\n\n    def run(self):\n        self.ioloop = IOLoop.instance()\n        self.alive = True\n        self.server_alive = False\n        PeriodicCallback(self.watchdog, 1000, io_loop=self.ioloop).start()\n        PeriodicCallback(self.heartbeat, 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        self.server_alive = True\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", "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 copy\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\n    def handle_request(self):\n        self.nr += 1\n        if self.alive and self.nr >= self.max_requests:\n            self.log.info(\"Autorestarting worker after current request.\")\n            self.alive = False\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.alive = False\n\n    def heartbeat(self):\n        if not self.alive:\n            if self.server_alive:\n                if hasattr(self, 'server'):\n                    try:\n                        self.server.stop()\n                    except Exception:\n                        pass\n                self.server_alive = False\n            else:\n                if not self.ioloop._callbacks:\n                    self.ioloop.stop()\n\n    def run(self):\n        self.ioloop = IOLoop.instance()\n        self.alive = True\n        self.server_alive = False\n        PeriodicCallback(self.watchdog, 1000, io_loop=self.ioloop).start()\n        PeriodicCallback(self.heartbeat, 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             _ssl_opt = copy.deepcopy(self.cfg.ssl_options)\n             # tornado refuses initialization if ssl_options contains following\n             # options\n             del _ssl_opt[\"do_handshake_on_connect\"]\n             del _ssl_opt[\"suppress_ragged_eofs\"]\n            server = server_class(app, io_loop=self.ioloop,\n                    ssl_options=_ssl_opt)\n        else:\n            server = server_class(app, io_loop=self.ioloop)\n\n        self.server = server\n        self.server_alive = True\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", "path": "gunicorn/workers/gtornado.py"}]}