19
19
Exception related utilities.
27
from heat.openstack.common.gettextutils import _
30
@contextlib.contextmanager
31
def save_and_reraise_exception():
27
from heat.openstack.common.gettextutils import _ # noqa
30
class save_and_reraise_exception(object):
32
31
"""Save current exception, run some code and then re-raise.
34
33
In some cases the exception context can be cleared, resulting in None
40
39
To work around this, we save the exception state, run handler code, and
41
40
then re-raise the original exception. If another exception occurs, the
42
41
saved exception is logged and the new exception is re-raised.
43
In some cases the caller may not want to re-raise the exception, and
44
for those circumstances this context provides a reraise flag that
45
can be used to suppress the exception. For example:
48
with save_and_reraise_exception() as ctxt:
49
decide_if_need_reraise()
50
if not should_be_reraised:
44
type_, value, tb = sys.exc_info()
48
logging.error(_('Original exception being dropped: %s'),
49
traceback.format_exception(type_, value, tb))
51
raise type_, value, tb
57
self.type_, self.value, self.tb, = sys.exc_info()
60
def __exit__(self, exc_type, exc_val, exc_tb):
61
if exc_type is not None:
62
logging.error(_('Original exception being dropped: %s'),
63
traceback.format_exception(self.type_,
68
raise self.type_, self.value, self.tb
71
def forever_retry_uncaught_exceptions(infunc):
72
def inner_func(*args, **kwargs):
74
last_exc_message = None
78
return infunc(*args, **kwargs)
79
except Exception as exc:
80
if exc.message == last_exc_message:
84
# Do not log any more frequently than once a minute unless
85
# the exception message changes
86
cur_time = int(time.time())
87
if (cur_time - last_log_time > 60 or
88
exc.message != last_exc_message):
90
_('Unexpected exception occurred %d time(s)... '
91
'retrying.') % exc_count)
92
last_log_time = cur_time
93
last_exc_message = exc.message
95
# This should be a very rare event. In case it isn't, do