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.

geventlet.py 3.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  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. from functools import partial
  6. import errno
  7. import sys
  8. try:
  9. import eventlet
  10. except ImportError:
  11. raise RuntimeError("You need eventlet installed to use this worker.")
  12. # validate the eventlet version
  13. if eventlet.version_info < (0, 9, 7):
  14. raise RuntimeError("You need eventlet >= 0.9.7")
  15. from eventlet import hubs, greenthread
  16. from eventlet.greenio import GreenSocket
  17. from eventlet.hubs import trampoline
  18. import greenlet
  19. from gunicorn.http.wsgi import sendfile as o_sendfile
  20. from gunicorn.workers.async import AsyncWorker
  21. def _eventlet_sendfile(fdout, fdin, offset, nbytes):
  22. while True:
  23. try:
  24. return o_sendfile(fdout, fdin, offset, nbytes)
  25. except OSError as e:
  26. if e.args[0] == errno.EAGAIN:
  27. trampoline(fdout, write=True)
  28. else:
  29. raise
  30. def _eventlet_serve(sock, handle, concurrency):
  31. """
  32. Serve requests forever.
  33. This code is nearly identical to ``eventlet.convenience.serve`` except
  34. that it attempts to join the pool at the end, which allows for gunicorn
  35. graceful shutdowns.
  36. """
  37. pool = eventlet.greenpool.GreenPool(concurrency)
  38. server_gt = eventlet.greenthread.getcurrent()
  39. while True:
  40. try:
  41. conn, addr = sock.accept()
  42. gt = pool.spawn(handle, conn, addr)
  43. gt.link(_eventlet_stop, server_gt, conn)
  44. conn, addr, gt = None, None, None
  45. except eventlet.StopServe:
  46. sock.close()
  47. pool.waitall()
  48. return
  49. def _eventlet_stop(client, server, conn):
  50. """
  51. Stop a greenlet handling a request and close its connection.
  52. This code is lifted from eventlet so as not to depend on undocumented
  53. functions in the library.
  54. """
  55. try:
  56. try:
  57. client.wait()
  58. finally:
  59. conn.close()
  60. except greenlet.GreenletExit:
  61. pass
  62. except Exception:
  63. greenthread.kill(server, *sys.exc_info())
  64. def patch_sendfile():
  65. from gunicorn.http import wsgi
  66. if o_sendfile is not None:
  67. setattr(wsgi, "sendfile", _eventlet_sendfile)
  68. class EventletWorker(AsyncWorker):
  69. def patch(self):
  70. hubs.use_hub()
  71. eventlet.monkey_patch(os=False)
  72. patch_sendfile()
  73. def init_process(self):
  74. self.patch()
  75. super(EventletWorker, self).init_process()
  76. def handle_quit(self, sig, frame):
  77. eventlet.spawn(super(EventletWorker, self).handle_quit, sig, frame)
  78. def timeout_ctx(self):
  79. return eventlet.Timeout(self.cfg.keepalive or None, False)
  80. def handle(self, listener, client, addr):
  81. if self.cfg.is_ssl:
  82. client = eventlet.wrap_ssl(client, server_side=True,
  83. **self.cfg.ssl_options)
  84. super(EventletWorker, self).handle(listener, client, addr)
  85. def run(self):
  86. acceptors = []
  87. for sock in self.sockets:
  88. gsock = GreenSocket(sock)
  89. gsock.setblocking(1)
  90. hfun = partial(self.handle, gsock)
  91. acceptor = eventlet.spawn(_eventlet_serve, gsock, hfun,
  92. self.worker_connections)
  93. acceptors.append(acceptor)
  94. eventlet.sleep(0.0)
  95. while self.alive:
  96. self.notify()
  97. eventlet.sleep(1.0)
  98. self.notify()
  99. try:
  100. with eventlet.Timeout(self.cfg.graceful_timeout) as t:
  101. [a.kill(eventlet.StopServe()) for a in acceptors]
  102. [a.wait() for a in acceptors]
  103. except eventlet.Timeout as te:
  104. if te != t:
  105. raise
  106. [a.kill() for a in acceptors]