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.

common.py 3.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. # -*- coding: utf-8 -*-
  2. """
  3. This module contains utilities added by billiard, to keep
  4. "non-core" functionality out of ``.util``."""
  5. from __future__ import absolute_import
  6. import os
  7. import signal
  8. import sys
  9. import pickle as pypickle
  10. try:
  11. import cPickle as cpickle
  12. except ImportError: # pragma: no cover
  13. cpickle = None # noqa
  14. from .exceptions import RestartFreqExceeded
  15. from .five import monotonic
  16. if sys.version_info < (2, 6): # pragma: no cover
  17. # cPickle does not use absolute_imports
  18. pickle = pypickle
  19. pickle_load = pypickle.load
  20. pickle_loads = pypickle.loads
  21. else:
  22. pickle = cpickle or pypickle
  23. pickle_load = pickle.load
  24. pickle_loads = pickle.loads
  25. # cPickle.loads does not support buffer() objects,
  26. # but we can just create a StringIO and use load.
  27. if sys.version_info[0] == 3:
  28. from io import BytesIO
  29. else:
  30. try:
  31. from cStringIO import StringIO as BytesIO # noqa
  32. except ImportError:
  33. from StringIO import StringIO as BytesIO # noqa
  34. EX_SOFTWARE = 70
  35. TERMSIGS_DEFAULT = (
  36. 'SIGHUP',
  37. 'SIGQUIT',
  38. 'SIGTERM',
  39. 'SIGUSR1',
  40. 'SIGUSR2'
  41. )
  42. TERMSIGS_FULL = (
  43. 'SIGHUP',
  44. 'SIGQUIT',
  45. 'SIGTRAP',
  46. 'SIGABRT',
  47. 'SIGEMT',
  48. 'SIGSYS',
  49. 'SIGPIPE',
  50. 'SIGALRM',
  51. 'SIGTERM',
  52. 'SIGXCPU',
  53. 'SIGXFSZ',
  54. 'SIGVTALRM',
  55. 'SIGPROF',
  56. 'SIGUSR1',
  57. 'SIGUSR2',
  58. )
  59. #: set by signal handlers just before calling exit.
  60. #: if this is true after the sighandler returns it means that something
  61. #: went wrong while terminating the process, and :func:`os._exit`
  62. #: must be called ASAP.
  63. _should_have_exited = [False]
  64. def pickle_loads(s, load=pickle_load):
  65. # used to support buffer objects
  66. return load(BytesIO(s))
  67. def maybe_setsignal(signum, handler):
  68. try:
  69. signal.signal(signum, handler)
  70. except (OSError, AttributeError, ValueError, RuntimeError):
  71. pass
  72. def _shutdown_cleanup(signum, frame):
  73. # we will exit here so if the signal is received a second time
  74. # we can be sure that something is very wrong and we may be in
  75. # a crashing loop.
  76. if _should_have_exited[0]:
  77. os._exit(EX_SOFTWARE)
  78. maybe_setsignal(signum, signal.SIG_DFL)
  79. _should_have_exited[0] = True
  80. sys.exit(-(256 - signum))
  81. def reset_signals(handler=_shutdown_cleanup, full=False):
  82. for sig in TERMSIGS_FULL if full else TERMSIGS_DEFAULT:
  83. try:
  84. signum = getattr(signal, sig)
  85. except AttributeError:
  86. pass
  87. else:
  88. current = signal.getsignal(signum)
  89. if current is not None and current != signal.SIG_IGN:
  90. maybe_setsignal(signum, handler)
  91. class restart_state(object):
  92. RestartFreqExceeded = RestartFreqExceeded
  93. def __init__(self, maxR, maxT):
  94. self.maxR, self.maxT = maxR, maxT
  95. self.R, self.T = 0, None
  96. def step(self, now=None):
  97. now = monotonic() if now is None else now
  98. R = self.R
  99. if self.T and now - self.T >= self.maxT:
  100. # maxT passed, reset counter and time passed.
  101. self.T, self.R = now, 0
  102. elif self.maxR and self.R >= self.maxR:
  103. # verify that R has a value as the result handler
  104. # resets this when a job is accepted. If a job is accepted
  105. # the startup probably went fine (startup restart burst
  106. # protection)
  107. if self.R: # pragma: no cover
  108. self.R = 0 # reset in case someone catches the error
  109. raise self.RestartFreqExceeded("%r in %rs" % (R, self.maxT))
  110. # first run sets T
  111. if self.T is None:
  112. self.T = now
  113. self.R += 1