Development of an internal social media platform with personalised dashboards for students
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

gtornado.py 4.3KB

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