summaryrefslogtreecommitdiff
path: root/src/leap/bitmask
diff options
context:
space:
mode:
Diffstat (limited to 'src/leap/bitmask')
-rw-r--r--src/leap/bitmask/app.py67
-rw-r--r--src/leap/bitmask/gui/mail_status.py2
-rw-r--r--src/leap/bitmask/gui/mainwindow.py5
-rw-r--r--src/leap/bitmask/platform_init/initializers.py44
-rw-r--r--src/leap/bitmask/services/eip/linuxvpnlauncher.py6
-rw-r--r--src/leap/bitmask/services/mail/plumber.py3
-rw-r--r--src/leap/bitmask/services/soledad/soledadbootstrapper.py28
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")