diff --git a/deluge/core/rpcserver.py b/deluge/core/rpcserver.py index d176ff01b..e2069360a 100644 --- a/deluge/core/rpcserver.py +++ b/deluge/core/rpcserver.py @@ -57,7 +57,7 @@ import deluge.component as component import deluge.configmanager from deluge.core.authmanager import (AUTH_LEVEL_NONE, AUTH_LEVEL_DEFAULT, AUTH_LEVEL_ADMIN) -from deluge.error import (DelugeError, NotAuthorizedError, +from deluge.error import (DelugeError, NotAuthorizedError, WrappedException, _ClientSideRecreateError, IncompatibleClient) RPC_RESPONSE = 1 @@ -246,6 +246,7 @@ class DelugeRPCProtocol(Protocol): Sends an error response with the contents of the exception that was raised. """ exceptionType, exceptionValue, exceptionTraceback = sys.exc_info() + formated_tb = "".join(traceback.format_tb(exceptionTraceback)) try: self.sendData(( RPC_ERROR, @@ -253,13 +254,18 @@ class DelugeRPCProtocol(Protocol): exceptionType.__name__, exceptionValue._args, exceptionValue._kwargs, - "".join(traceback.format_tb(exceptionTraceback)) + formated_tb )) except Exception, err: + # This most likely not a deluge exception, let's wrap it log.error("An exception occurred while sending RPC_ERROR to " - "client. Error to send(exception goes next): %s", - "".join(traceback.format_tb(exceptionTraceback))) + "client. Wrapping it and resending. Error to " + "send(causing exception goes next):\n%s", formated_tb) log.exception(err) + try: + raise WrappedException(str(exceptionValue), exceptionType.__name__, formated_tb) + except: + sendError() if method == "daemon.info": # This is a special case and used in the initial connection process diff --git a/deluge/error.py b/deluge/error.py index ea7c64671..825163233 100644 --- a/deluge/error.py +++ b/deluge/error.py @@ -64,6 +64,26 @@ class InvalidTorrentError(DelugeError): class InvalidPathError(DelugeError): pass +class WrappedException(DelugeError): + def _get_traceback(self): + return self._traceback + def _set_traceback(self, traceback): + self._traceback = traceback + traceback = property(_get_traceback, _set_traceback) + del _get_traceback, _set_traceback + + def _get_type(self): + return self._type + def _set_type(self, type): + self._type = type + type = property(_get_type, _set_type) + del _get_type, _set_type + + def __init__(self, message, exception_type, traceback): + self.message = message + self.type = exception_type + self.traceback = traceback + class _ClientSideRecreateError(DelugeError): pass diff --git a/deluge/ui/client.py b/deluge/ui/client.py index 31fb305a3..269da605e 100644 --- a/deluge/ui/client.py +++ b/deluge/ui/client.py @@ -194,8 +194,12 @@ class DelugeRPCProtocol(Protocol): msg += "\n" + "-" * 80 msg += "\n" + "RPCRequest: " + r.__repr__() msg += "\n" + "-" * 80 - msg += "\n" + request[5] + "\n" + request[2] + ": " - msg += str(exception) + if isinstance(exception, error.WrappedException): + msg += "\n" + exception.type + "\n" + exception.message + ": " + msg += exception.traceback + else: + msg += "\n" + request[5] + "\n" + request[2] + ": " + msg += str(exception) msg += "\n" + "-" * 80 if not isinstance(exception, error._ClientSideRecreateError): @@ -203,7 +207,7 @@ class DelugeRPCProtocol(Protocol): log.error(msg) else: # The rest just get's logged in debug level, just to log - # what's happending + # what's happening log.debug(msg) d.errback(exception) @@ -617,7 +621,7 @@ class Client(object): self._daemon_proxy.disconnect() self.stop_classic_mode() return - + if self._daemon_proxy: return self._daemon_proxy.disconnect() @@ -634,7 +638,7 @@ class Client(object): """ self._daemon_proxy = None self.__started_in_classic = False - + def start_daemon(self, port, config): """ Starts a daemon process.