diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/leap/bitmask/app.py | 67 | ||||
-rw-r--r-- | src/leap/bitmask/gui/mail_status.py | 2 | ||||
-rw-r--r-- | src/leap/bitmask/gui/mainwindow.py | 5 | ||||
-rw-r--r-- | src/leap/bitmask/platform_init/initializers.py | 44 | ||||
-rw-r--r-- | src/leap/bitmask/services/eip/linuxvpnlauncher.py | 6 | ||||
-rw-r--r-- | src/leap/bitmask/services/mail/plumber.py | 3 | ||||
-rw-r--r-- | src/leap/bitmask/services/soledad/soledadbootstrapper.py | 28 |
7 files changed, 74 insertions, 81 deletions
diff --git a/src/leap/bitmask/app.py b/src/leap/bitmask/app.py index 6a7d6ff1..d0906b7c 100644 --- a/src/leap/bitmask/app.py +++ b/src/leap/bitmask/app.py @@ -49,7 +49,6 @@ from PySide import QtCore, QtGui from leap.bitmask import __version__ as VERSION from leap.bitmask.config import flags -from leap.bitmask.gui import locale_rc # noqa - silence pylint from leap.bitmask.gui.mainwindow import MainWindow from leap.bitmask.logs.utils import create_logger from leap.bitmask.platform_init.locks import we_are_the_one_and_only @@ -67,16 +66,39 @@ import codecs codecs.register(lambda name: codecs.lookup('utf-8') if name == 'cp65001' else None) +import psutil + + +def kill_the_children(): + """ + Make sure no lingering subprocesses are left in case of a bad termination. + """ + me = os.getpid() + parent = psutil.Process(me) + print "Killing all the children processes..." + for child in parent.get_children(recursive=True): + try: + child.terminate() + except Exception as exc: + print exc + +# XXX This is currently broken, but we need to fix it to avoid +# orphaned processes in case of a crash. +#atexit.register(kill_the_children) + def sigint_handler(*args, **kwargs): """ Signal handler for SIGINT """ logger = kwargs.get('logger', None) - if logger: - logger.debug("SIGINT catched. shutting down...") - mainwindow = args[0] - mainwindow.quit() + parentpid = kwargs.get('parentpid', None) + pid = os.getpid() + if parentpid == pid: + if logger: + logger.debug("SIGINT catched. shutting down...") + mainwindow = args[0] + mainwindow.quit() def sigterm_handler(*args, **kwargs): @@ -85,10 +107,13 @@ def sigterm_handler(*args, **kwargs): This handler is actually passed to twisted reactor """ logger = kwargs.get('logger', None) - if logger: - logger.debug("SIGTERM catched. shutting down...") - mainwindow = args[0] - mainwindow.quit() + parentpid = kwargs.get('parentpid', None) + pid = os.getpid() + if parentpid == pid: + if logger: + logger.debug("SIGTERM catched. shutting down...") + mainwindow = args[0] + mainwindow.quit() def do_display_version(opts): @@ -203,32 +228,26 @@ def main(): app.setApplicationName("leap") app.setOrganizationDomain("leap.se") - # XXX --------------------------------------------------------- - # In quarantine, looks like we don't need it anymore. - # This dummy timer ensures that control is given to the outside - # loop, so we can hook our sigint handler. - #timer = QtCore.QTimer() - #timer.start(500) - #timer.timeout.connect(lambda: None) - # XXX --------------------------------------------------------- - window = MainWindow(bypass_checks=bypass_checks, start_hidden=start_hidden) - sigint_window = partial(sigint_handler, window, logger=logger) + mainpid = os.getpid() + sigint_window = partial(sigint_handler, window, + logger=logger, parentpid=mainpid) signal.signal(signal.SIGINT, sigint_window) # callable used in addSystemEventTrigger to handle SIGTERM - sigterm_window = partial(sigterm_handler, window, logger=logger) - - l = LoopingCall(QtCore.QCoreApplication.processEvents, 0, 10) - l.start(0.01) - + sigterm_window = partial(sigterm_handler, window, + logger=logger, parentpid=mainpid) # SIGTERM can't be handled the same way SIGINT is, since it's # caught by twisted. See _handleSignals method in # twisted/internet/base.py#L1150. So, addSystemEventTrigger # reactor's method is used. reactor.addSystemEventTrigger('before', 'shutdown', sigterm_window) + + l = LoopingCall(QtCore.QCoreApplication.processEvents, 0, 10) + l.start(0.01) + reactor.run() if __name__ == "__main__": diff --git a/src/leap/bitmask/gui/mail_status.py b/src/leap/bitmask/gui/mail_status.py index 5caef745..bb755b5c 100644 --- a/src/leap/bitmask/gui/mail_status.py +++ b/src/leap/bitmask/gui/mail_status.py @@ -304,7 +304,7 @@ class MailStatusWidget(QtGui.QWidget): ext_status = "" if req.event == proto.KEYMANAGER_LOOKING_FOR_KEY: - ext_status = self.tr("Looking for key for this user") + ext_status = self.tr("Initial sync in progress, please wait...") elif req.event == proto.KEYMANAGER_KEY_FOUND: ext_status = self.tr("Found key! Starting mail...") # elif req.event == proto.KEYMANAGER_KEY_NOT_FOUND: diff --git a/src/leap/bitmask/gui/mainwindow.py b/src/leap/bitmask/gui/mainwindow.py index 8a5b8275..e53ab7f3 100644 --- a/src/leap/bitmask/gui/mainwindow.py +++ b/src/leap/bitmask/gui/mainwindow.py @@ -1786,7 +1786,6 @@ class MainWindow(QtGui.QMainWindow): Final steps to quit the app, starting from here we don't care about running services or user interaction, just quitting. """ - logger.debug('Final quit...') # We can reach here because all the services are stopped or because a # timeout was triggered. Since we want to run this only once, we exit @@ -1796,6 +1795,10 @@ class MainWindow(QtGui.QMainWindow): self._finally_quitting = True + logger.debug('Closing soledad...') + self._backend.soledad_close() + logger.debug('Final quit...') + # Remove lockfiles on a clean shutdown. logger.debug('Cleaning pidfiles') if IS_WIN: diff --git a/src/leap/bitmask/platform_init/initializers.py b/src/leap/bitmask/platform_init/initializers.py index 384e1ec1..2d800703 100644 --- a/src/leap/bitmask/platform_init/initializers.py +++ b/src/leap/bitmask/platform_init/initializers.py @@ -373,30 +373,6 @@ def DarwinInitializer(): # Linux initializers # -def _get_missing_resolvconf_dialog(): - """ - Create a dialog for notifying about missing openresolv. - - :rtype: QtGui.QMessageBox instance - """ - msgstr = QtCore.QObject() - msgstr.NO_RESOLVCONF = msgstr.tr( - "Could not find <b>resolvconf</b> installed in your system.\n" - "Do you want to quit Bitmask now?") - - msgstr.EXPLAIN = msgstr.tr( - "Encrypted Internet needs resolvconf installed to work properly.\n" - "Please use your package manager to install it.\n") - - msg = QtGui.QMessageBox() - msg.setWindowTitle(msg.tr("Missing resolvconf framework")) - msg.setText(msgstr.NO_RESOLVCONF) - # but maybe the user really deserve to know more - msg.setInformativeText(msgstr.EXPLAIN) - msg.setStandardButtons(QtGui.QMessageBox.Yes | QtGui.QMessageBox.No) - msg.setDefaultButton(QtGui.QMessageBox.Yes) - return msg - def _get_missing_complain_dialog(stuff): """ @@ -445,21 +421,6 @@ def _get_missing_complain_dialog(stuff): return msg -def _linux_check_resolvconf(): - """ - Raise a dialog warning about the lack of the resolvconf framework. - """ - RESOLVCONF_PATH = "/sbin/resolvconf" - missing = not os.path.isfile(RESOLVCONF_PATH) - - if missing: - msg = _get_missing_resolvconf_dialog() - ret = msg.exec_() - - if ret == QtGui.QMessageBox.Yes: - sys.exit() - - def _linux_install_missing_scripts(badexec, notfound): """ Try to install the missing helper files. @@ -509,9 +470,8 @@ def LinuxInitializer(): """ Raise a dialog if needed files are missing. - Missing files can be either system-wide resolvconf, bitmask-root, or - policykit file. The dialog will also be raised if some of those files are + Missing files can be either bitmask-root policykit file. + The dialog will also be raised if some of those files are found to have incorrect permissions. """ - _linux_check_resolvconf() check_missing() diff --git a/src/leap/bitmask/services/eip/linuxvpnlauncher.py b/src/leap/bitmask/services/eip/linuxvpnlauncher.py index 1409d504..b6e47f25 100644 --- a/src/leap/bitmask/services/eip/linuxvpnlauncher.py +++ b/src/leap/bitmask/services/eip/linuxvpnlauncher.py @@ -127,12 +127,6 @@ class LinuxVPNLauncher(VPNLauncher): # LinuxPolicyChecker will give us the right path if standalone. return LinuxPolicyChecker.get_polkit_path() - class RESOLVCONF_BIN_PATH(object): - def __call__(self): - return ("/usr/local/sbin/leap-resolvconf" if flags.STANDALONE else - "/sbin/resolvconf") - # this only will work with debian/ubuntu distros. - OTHER_FILES = (POLKIT_PATH, BITMASK_ROOT, OPENVPN_BIN_PATH) @classmethod diff --git a/src/leap/bitmask/services/mail/plumber.py b/src/leap/bitmask/services/mail/plumber.py index c16a1fed..1ef0543e 100644 --- a/src/leap/bitmask/services/mail/plumber.py +++ b/src/leap/bitmask/services/mail/plumber.py @@ -83,7 +83,8 @@ def initialize_soledad(uuid, email, passwd, secrets, localdb, server_url, - cert_file) + cert_file, + defer_encryption=True) return soledad diff --git a/src/leap/bitmask/services/soledad/soledadbootstrapper.py b/src/leap/bitmask/services/soledad/soledadbootstrapper.py index db12fd80..b9243add 100644 --- a/src/leap/bitmask/services/soledad/soledadbootstrapper.py +++ b/src/leap/bitmask/services/soledad/soledadbootstrapper.py @@ -21,6 +21,7 @@ import logging import os import socket import sys +import time from ssl import SSLError from sqlite3 import ProgrammingError as sqlite_ProgrammingError @@ -132,6 +133,9 @@ class SoledadBootstrapper(AbstractBootstrapper): MAX_INIT_RETRIES = 10 MAX_SYNC_RETRIES = 10 + WAIT_MAX_SECONDS = 600 + #WAIT_STEP_SECONDS = 1 + WAIT_STEP_SECONDS = 5 def __init__(self, signaler=None): AbstractBootstrapper.__init__(self, signaler) @@ -181,7 +185,6 @@ class SoledadBootstrapper(AbstractBootstrapper): :param uuid: the user uuid :type uuid: str or unicode """ - print "UUID ", uuid self._address = username self._password = password self._uuid = uuid @@ -356,12 +359,20 @@ class SoledadBootstrapper(AbstractBootstrapper): Do several retries to get an initial soledad sync. """ # and now, let's sync - sync_tries = 1 - while sync_tries <= self.MAX_SYNC_RETRIES: + sync_tries = self.MAX_SYNC_RETRIES + step = self.WAIT_STEP_SECONDS + max_wait = self.WAIT_MAX_SECONDS + while sync_tries > 0: + wait = 0 try: logger.debug("Trying to sync soledad....") self._try_soledad_sync() - logger.debug("Soledad has been synced.") + while self.soledad.syncing: + time.sleep(step) + wait += step + if wait >= max_wait: + raise SoledadSyncError("timeout!") + logger.debug("Soledad has been synced!") # so long, and thanks for all the fish return except SoledadSyncError: @@ -382,6 +393,7 @@ class SoledadBootstrapper(AbstractBootstrapper): self._signaler.SOLEDAD_INVALID_AUTH_TOKEN) raise except Exception as e: + # XXX release syncing lock logger.exception("Unhandled error while syncing " "soledad: %r" % (e,)) break @@ -423,7 +435,8 @@ class SoledadBootstrapper(AbstractBootstrapper): local_db_path=local_db_path.encode(encoding), server_url=server_url, cert_file=cert_file.encode(encoding), - auth_token=auth_token) + auth_token=auth_token, + defer_encryption=True) # XXX All these errors should be handled by soledad itself, # and return a subclass of SoledadInitializationFailed @@ -448,7 +461,10 @@ class SoledadBootstrapper(AbstractBootstrapper): Raises SoledadSyncError if not successful. """ try: - self._soledad.sync() + logger.debug("BOOTSTRAPPER: trying to sync Soledad....") + # pass defer_decryption=False to get inline decryption + # for debugging. + self._soledad.sync(defer_decryption=True) except SSLError as exc: logger.error("%r" % (exc,)) raise SoledadSyncError("Failed to sync soledad") |