1
0
mirror of git://sourceware.org/git/lvm2.git synced 2025-01-03 05:18:29 +03:00

lvmdbus: Fix exception during exception handling

Python 3.5 in F24 was throwing the following exception:

Traceback (most recent call last):
  File "/usr/lib/python3.5/site-packages/lvmdbusd/main.py", line 73, in process_request
    req.run_cmd()
  File "/usr/lib/python3.5/site-packages/lvmdbusd/request.py", line 73, in run_cmd
    self.register_error(-1, st)
  File "/usr/lib/python3.5/site-packages/lvmdbusd/request.py", line 123, in register_error
    self._reg_ending(None, error_rc, error)
  File "/usr/lib/python3.5/site-packages/lvmdbusd/request.py", line 115, in _reg_ending
    self.cb_error(self._rc_error)
  File "/usr/lib64/python3.5/site-packages/dbus/service.py", line 669, in <lambda>
    keywords[error_callback] = lambda exception: _method_reply_error(connection, message, exception)
  File "/usr/lib64/python3.5/site-packages/dbus/service.py", line 293, in _method_reply_error
    exception))
  File "/usr/lib64/python3.5/traceback.py", line 136, in format_exception_only
    return list(TracebackException(etype, value, None).format_exception_only())
  File "/usr/lib64/python3.5/traceback.py", line 442, in __init__
    if (exc_value and exc_value.__cause__ is not None
AttributeError: 'str' object has no attribute '__cause__'

This was caused because we were calling the dbus error callback with a
string instead of an actual exception.  On python 3.4 this was apparently
OK, but not with 3.5.  Corrected to pass the exception to error callback.
Change tested on both python 3.4 and 3.5.

Reported-by: Vratislav Podzimek <vpodzime@redhat.com>
Signed-off-by: Tony Asleson <tasleson@redhat.com>
This commit is contained in:
Tony Asleson 2016-03-08 15:57:15 -06:00
parent 90c5d470c2
commit 3f5629302a

View File

@ -64,13 +64,13 @@ class RequestEntry(object):
try: try:
result = self.method(*self.arguments) result = self.method(*self.arguments)
self.register_result(result) self.register_result(result)
except Exception: except Exception as e:
# Use the request entry to return the result as the client may # Use the request entry to return the result as the client may
# have gotten a job by the time we hit an error # have gotten a job by the time we hit an error
# Lets get the stacktrace and set that to the error message # Lets get the stacktrace and set that to the error message
st = traceback.format_exc() st = traceback.format_exc()
log_error("Exception returned to client: \n%s" % st) log_error("Exception returned to client: \n%s" % st)
self.register_error(-1, st) self.register_error(-1, str(e), e)
def is_done(self): def is_done(self):
with self.lock: with self.lock:
@ -87,7 +87,8 @@ class RequestEntry(object):
return self._result return self._result
return '/' return '/'
def _reg_ending(self, result, error_rc=0, error=None): def _reg_ending(self, result, error_rc=0, error_msg=None,
error_exception=None):
with self.lock: with self.lock:
self.done = True self.done = True
if self.timer_id != -1: if self.timer_id != -1:
@ -96,7 +97,7 @@ class RequestEntry(object):
self._result = result self._result = result
self._rc = error_rc self._rc = error_rc
self._rc_error = error self._rc_error = error_msg
if not self._job: if not self._job:
# We finished and there is no job, so return result or error # We finished and there is no job, so return result or error
@ -112,15 +113,23 @@ class RequestEntry(object):
self.cb(result) self.cb(result)
else: else:
if self.cb_error: if self.cb_error:
self.cb_error(self._rc_error) if not error_exception:
if not error_msg:
error_exception = Exception(
"An error occurred, but no reason was "
"given, see service logs!")
else:
error_exception = Exception(error_msg)
self.cb_error(error_exception)
else: else:
# We have a job and it's complete, indicate that it's done. # We have a job and it's complete, indicate that it's done.
# TODO: We need to signal the job is done too. # TODO: We need to signal the job is done too.
self._job.Complete = True self._job.Complete = True
self._job = None self._job = None
def register_error(self, error_rc, error): def register_error(self, error_rc, error_message, error_exception):
self._reg_ending(None, error_rc, error) self._reg_ending(None, error_rc, error_message, error_exception)
def register_result(self, result): def register_result(self, result):
self._reg_ending(result) self._reg_ending(result)