diff --git a/securedrop_client/app.py b/securedrop_client/app.py index df50b1a956..5a043a6c45 100644 --- a/securedrop_client/app.py +++ b/securedrop_client/app.py @@ -21,10 +21,10 @@ import os import signal import sys +import socket from sqlalchemy.orm import sessionmaker from PyQt5.QtWidgets import QApplication, QMessageBox from PyQt5.QtCore import Qt, QTimer -from PyQt5.QtNetwork import QLocalServer, QLocalSocket from logging.handlers import TimedRotatingFileHandler from securedrop_client import __version__ from securedrop_client.logic import Client @@ -73,29 +73,18 @@ def configure_logging(): def prevent_second_instance(app: QApplication) -> None: - IDENTIFIER = app.applicationName() + str(os.getuid()) - - def already_running() -> bool: - TIMEOUT = 3000 - socket = QLocalSocket(app) - socket.connectToServer(IDENTIFIER, socket.NotOpen) - if socket.waitForConnected(TIMEOUT): - socket.disconnectFromServer() - return True - else: - return False - - def setup_instance_listener() -> None: - QLocalServer.removeServer(IDENTIFIER) - app.instance_listener = QLocalServer(app) - app.instance_listener.listen(IDENTIFIER) - - if already_running(): - error = QMessageBox() - error.setText(app.applicationName() + ' is already running.') - sys.exit(error.exec()) - else: - setup_instance_listener() + # Null byte triggers abstract namespace + IDENTIFIER = '\0' + app.applicationName() + str(os.getuid()) + ALREADY_BOUND_ERRNO = 98 + + app.instance_binding = socket.socket(socket.AF_UNIX, socket.SOCK_DGRAM) + try: + app.instance_binding.bind(IDENTIFIER) + except OSError as e: + if e.errno == ALREADY_BOUND_ERRNO: + error_dialog = QMessageBox() + error_dialog.setText(app.applicationName() + ' is already running.') + sys.exit(error_dialog.exec()) def run():