diff --git a/lbrynet/core/log_support.py b/lbrynet/core/log_support.py index 1fb3979c7..88973761f 100644 --- a/lbrynet/core/log_support.py +++ b/lbrynet/core/log_support.py @@ -139,3 +139,17 @@ class JsonFormatter(logging.Formatter): if record.exc_info: data['exc_info'] = self.formatException(record.exc_info) return json.dumps(data) + + +def failure(failure, log, msg, *args): + """Log a failure message from a deferred. + + Args: + failure: twisted.python.failure.Failure + log: a python logger instance + msg: the message to log. Can use normal logging string interpolation. + the last argument will be set to the error message from the failure. + args: values to substitute into `msg` + """ + args += (failure.getErrorMessage(),) + log.error(msg, *args, exc_info=failure.getTracebackObject()) diff --git a/lbrynet/lbrynet_daemon/Daemon.py b/lbrynet/lbrynet_daemon/Daemon.py index fc67a4132..4d3ceee77 100644 --- a/lbrynet/lbrynet_daemon/Daemon.py +++ b/lbrynet/lbrynet_daemon/Daemon.py @@ -127,6 +127,8 @@ BAD_REQUEST = 400 NOT_FOUND = 404 OK_CODE = 200 +PENDING_LBRY_ID = "not set" + class Checker: """The looping calls the daemon runs""" @@ -262,6 +264,8 @@ class Daemon(jsonrpc.JSONRPC): self.first_run_after_update = False self.uploaded_temp_files = [] self._session_id = base58.b58encode(generate_id()) + self.analytics_manager = None + self.lbryid = PENDING_LBRY_ID if os.name == "nt": from lbrynet.winhelpers.knownpaths import get_path, FOLDERID, UserHandle @@ -636,11 +640,8 @@ class Daemon(jsonrpc.JSONRPC): d.addCallback(lambda _: self._setup_server()) d.addCallback(lambda _: _log_starting_vals()) d.addCallback(lambda _: _announce_startup()) - # TODO: handle errors here d.callback(None) - - return defer.succeed(None) - + return d def _get_platform(self): r = { @@ -838,21 +839,23 @@ class Daemon(jsonrpc.JSONRPC): for lm, lp in [('lbrynet', lbrynet_log)]: if os.path.isfile(lp): if exclude_previous: - f = open(lp, "r") - f.seek(PREVIOUS_NET_LOG) - log_contents = f.read() - f.close() + with open( lp, "r") as f: + f.seek(PREVIOUS_NET_LOG) + log_contents = f.read() else: - f = open(lp, "r") - log_contents = f.read() - f.close() + with open(lp, "r") as f: + log_contents = f.read() + if self.lbryid is not PENDING_LBRY_ID: + id_hash = base58.b58encode(self.lbryid)[:20] + else: + id_hash = self.lbryid params = { - 'date': datetime.utcnow().strftime('%Y%m%d-%H%M%S'), - 'hash': base58.b58encode(self.lbryid)[:20], - 'sys': platform.system(), - 'type': "%s-%s" % (lm, log_type) if log_type else lm, - 'log': log_contents - } + 'date': datetime.utcnow().strftime('%Y%m%d-%H%M%S'), + 'hash': id_hash, + 'sys': platform.system(), + 'type': "%s-%s" % (lm, log_type) if log_type else lm, + 'log': log_contents + } requests.post(LOG_POST_URL, params) return defer.succeed(None) @@ -870,13 +873,19 @@ class Daemon(jsonrpc.JSONRPC): log.info("Closing lbrynet session") log.info("Status at time of shutdown: " + self.startup_status[0]) self.looping_call_manager.shutdown() - self.analytics_manager.shutdown() + if self.analytics_manager: + self.analytics_manager.shutdown() if self.lbry_ui_manager.update_checker.running: self.lbry_ui_manager.update_checker.stop() self._clean_up_temp_files() - d = self._upload_log(log_type="close", exclude_previous=False if self.first_run else True) + try: + d = self._upload_log( + log_type="close", exclude_previous=False if self.first_run else True) + except Exception: + log.warn('Failed to upload log', exc_info=True) + d = defer.succeed(None) d.addCallback(lambda _: self._stop_server()) d.addCallback(lambda _: self._stop_reflector()) d.addErrback(lambda err: True) @@ -976,10 +985,10 @@ class Daemon(jsonrpc.JSONRPC): self.startup_status = STARTUP_STAGES[1] log.info("Loading databases...") if self.created_data_dir: - db_revision = open(os.path.join(self.db_dir, "db_revision"), mode='w') - db_revision.write(str(self.current_db_revision)) - db_revision.close() - log.debug("Created the db revision file: %s", str(os.path.join(self.db_dir, "db_revision"))) + db_revision_path = os.path.join(self.db_dir, "db_revision") + with open(db_revision_path, mode='w') as db_revision: + db_revision.write(str(self.current_db_revision)) + log.debug("Created the db revision file: %s", db_revision_path) if not os.path.exists(self.blobfile_dir): os.mkdir(self.blobfile_dir) log.debug("Created the blobfile directory: %s", str(self.blobfile_dir)) @@ -989,6 +998,8 @@ class Daemon(jsonrpc.JSONRPC): db_revision_file = os.path.join(self.db_dir, "db_revision") if os.path.exists(db_revision_file): old_revision = int(open(db_revision_file).read().strip()) + if old_revision > self.current_db_revision: + return defer.fail(Exception('This version of lbrynet is not compatible with the database')) if old_revision < self.current_db_revision: from lbrynet.db_migrator import dbmigrator log.info("Upgrading your databases...") @@ -1016,7 +1027,7 @@ class Daemon(jsonrpc.JSONRPC): return d def _set_lbryid(self, lbryid): - if lbryid is None: + if lbryid is PENDING_LBRY_ID: return self._make_lbryid() else: log.info("LBRY ID: " + base58.b58encode(lbryid)) diff --git a/lbrynet/lbrynet_daemon/DaemonControl.py b/lbrynet/lbrynet_daemon/DaemonControl.py index 3c244b6eb..8ed28c170 100644 --- a/lbrynet/lbrynet_daemon/DaemonControl.py +++ b/lbrynet/lbrynet_daemon/DaemonControl.py @@ -109,6 +109,7 @@ def start(): branch_specified=True if args.branch else False) if args.launchui: d.addCallback(lambda _: webbrowser.open(UI_ADDRESS)) + d.addErrback(log_and_kill) lbrynet_server = server.Site(lbry.root) lbrynet_server.requestFactory = DaemonRequest @@ -123,5 +124,11 @@ def start(): print "Not connected to internet, unable to start" return + +def log_and_kill(failure): + log_support.failure(failure, log, 'Failed to startup: %s') + reactor.stop() + + if __name__ == "__main__": start() diff --git a/lbrynet/lbrynet_daemon/DaemonServer.py b/lbrynet/lbrynet_daemon/DaemonServer.py index 39268f5bd..99119618b 100644 --- a/lbrynet/lbrynet_daemon/DaemonServer.py +++ b/lbrynet/lbrynet_daemon/DaemonServer.py @@ -30,7 +30,8 @@ class DaemonServer(object): self.root.putChild(API_ADDRESS, self._api) return defer.succeed(True) - def start(self, branch=DEFAULT_UI_BRANCH, user_specified=False, branch_specified=False, wallet=None): + def start(self, branch=DEFAULT_UI_BRANCH, user_specified=False, + branch_specified=False, wallet=None): d = self._setup_server(wallet) d.addCallback(lambda _: self._api.setup(branch, user_specified, branch_specified)) return d