From eebd457b031d4527ff430ff75d771021e9ff7651 Mon Sep 17 00:00:00 2001 From: "Manuel Amador (Rudd-O)" Date: Tue, 15 Dec 2015 00:06:56 +0000 Subject: [PATCH] bombshell-client gains a lock that prevents it from hanging if two parallel requests happen too fast --- bin/bombshell-client | 50 ++++++++++++++++++++++++++++---------------- 1 file changed, 32 insertions(+), 18 deletions(-) diff --git a/bin/bombshell-client b/bin/bombshell-client index 678a9f5..de2c504 100755 --- a/bin/bombshell-client +++ b/bin/bombshell-client @@ -1,6 +1,7 @@ #!/usr/bin/python -u import cPickle +import contextlib import fcntl import os import pipes @@ -13,6 +14,18 @@ import sys import threading +@contextlib.contextmanager +def mutexfile(filepath): + oldumask = os.umask(0077) + try: + f = file(filepath, "a") + finally: + os.umask(oldumask) + fcntl.lockf(f.fileno(), fcntl.LOCK_EX) + yield + f.close() + + debug_lock = threading.Lock() debug_enabled = False class LoggingEmu(): @@ -250,26 +263,27 @@ def main_master(): saved_stderr = os.fdopen(os.dup(sys.stderr.fileno()), "a") - try: - p = subprocess.Popen( - ["qrexec-client-vm", remote_vm, "qubes.VMShell"], - stdin=subprocess.PIPE, - stdout=subprocess.PIPE, - close_fds=True, - preexec_fn=os.setpgrp, - ) - except OSError, e: - logging.error("cannot launch qrexec-client-vm: %s", e) - return 127 + with mutexfile(os.path.expanduser("~/.bombshell-lock")): + try: + p = subprocess.Popen( + ["qrexec-client-vm", remote_vm, "qubes.VMShell"], + stdin=subprocess.PIPE, + stdout=subprocess.PIPE, + close_fds=True, + preexec_fn=os.setpgrp, + ) + except OSError, e: + logging.error("cannot launch qrexec-client-vm: %s", e) + return 127 - p.stdin.write(remote_helper_text) - p.stdin.flush() + p.stdin.write(remote_helper_text) + p.stdin.flush() - send_command(p.stdin, remote_command) - confirmation, errmsg = recv_confirmation(p.stdout) - if confirmation != 0: - logging.error("remote: %s", errmsg) - return confirmation + send_command(p.stdin, remote_command) + confirmation, errmsg = recv_confirmation(p.stdout) + if confirmation != 0: + logging.error("remote: %s", errmsg) + return confirmation handled_signals = ( signal.SIGINT,