From ce88b52295881a3dd1bc0efec8e72b1d3a235e87 Mon Sep 17 00:00:00 2001 From: Ivan Alejandro Date: Tue, 22 Jul 2014 11:33:09 -0300 Subject: Add frontend alive check to the backend. Stop the backend if the frontend process does not exist any more and backend is not a daemon. --- changes/add-frontend-alive-check | 2 ++ src/leap/bitmask/app.py | 3 ++- src/leap/bitmask/backend/backend.py | 24 +++++++++++++++++++++++- src/leap/bitmask/backend/leapbackend.py | 4 ++-- src/leap/bitmask/backend_app.py | 5 +++-- 5 files changed, 32 insertions(+), 6 deletions(-) create mode 100644 changes/add-frontend-alive-check diff --git a/changes/add-frontend-alive-check b/changes/add-frontend-alive-check new file mode 100644 index 00000000..54f88798 --- /dev/null +++ b/changes/add-frontend-alive-check @@ -0,0 +1,2 @@ +- Stop the backend if the frontend process does not exist any more and backend + is not a daemon. Related to #5873. diff --git a/src/leap/bitmask/app.py b/src/leap/bitmask/app.py index ab49ee37..37ded92a 100644 --- a/src/leap/bitmask/app.py +++ b/src/leap/bitmask/app.py @@ -180,7 +180,8 @@ def start_app(): flags_dict = flags_to_dict() - backend = lambda: run_backend(opts.danger, flags_dict) + frontend_pid = os.getpid() + backend = lambda: run_backend(opts.danger, flags_dict, frontend_pid) backend_process = multiprocessing.Process(target=backend, name='Backend') backend_process.daemon = True backend_process.start() diff --git a/src/leap/bitmask/backend/backend.py b/src/leap/bitmask/backend/backend.py index c895f8f5..67ffe35a 100644 --- a/src/leap/bitmask/backend/backend.py +++ b/src/leap/bitmask/backend/backend.py @@ -18,6 +18,8 @@ import json import threading import time +import psutil + from twisted.internet import defer, reactor, threads import zmq @@ -39,12 +41,16 @@ class Backend(object): PORT = '5556' BIND_ADDR = "tcp://127.0.0.1:%s" % PORT - def __init__(self): + PING_INTERVAL = 2 # secs + + def __init__(self, frontend_pid=None): """ Backend constructor, create needed instances. """ self._signaler = Signaler() + self._frontend_pid = frontend_pid + self._do_work = threading.Event() # used to stop the worker thread. self._zmq_socket = None @@ -81,6 +87,8 @@ class Backend(object): Note: we use a simple while since is less resource consuming than a Twisted's LoopingCall. """ + pid = self._frontend_pid + check_wait = 0 while self._do_work.is_set(): # Wait for next request from client try: @@ -93,6 +101,20 @@ class Backend(object): raise time.sleep(0.01) + check_wait += 0.01 + if pid is not None and check_wait > self.PING_INTERVAL: + check_wait = 0 + self._check_frontend_alive() + + def _check_frontend_alive(self): + """ + Check if the frontend is alive and stop the backend if it is not. + """ + pid = self._frontend_pid + if pid is not None and not psutil.pid_exists(pid): + logger.critical("The frontend is down!") + self.stop() + def _stop_reactor(self): """ Stop the Twisted reactor, but first wait a little for some threads to diff --git a/src/leap/bitmask/backend/leapbackend.py b/src/leap/bitmask/backend/leapbackend.py index d3c4fcda..6b0328ca 100644 --- a/src/leap/bitmask/backend/leapbackend.py +++ b/src/leap/bitmask/backend/leapbackend.py @@ -36,11 +36,11 @@ class LeapBackend(Backend): """ Backend server subclass, used to implement the API methods. """ - def __init__(self, bypass_checks=False): + def __init__(self, bypass_checks=False, frontend_pid=None): """ Constructor for the backend. """ - Backend.__init__(self) + Backend.__init__(self, frontend_pid) self._settings = Settings() diff --git a/src/leap/bitmask/backend_app.py b/src/leap/bitmask/backend_app.py index 5c0e4803..716ae4a7 100644 --- a/src/leap/bitmask/backend_app.py +++ b/src/leap/bitmask/backend_app.py @@ -44,7 +44,7 @@ def signal_handler(signum, frame): logger.debug("{0}: SIGNAL #{1} catched.".format(pname, signum)) -def run_backend(bypass_checks, flags_dict): +def run_backend(bypass_checks, flags_dict, frontend_pid=None): """ Run the backend for the application. @@ -59,5 +59,6 @@ def run_backend(bypass_checks, flags_dict): dict_to_flags(flags_dict) - backend = LeapBackend(bypass_checks=bypass_checks) + backend = LeapBackend(bypass_checks=bypass_checks, + frontend_pid=frontend_pid) backend.run() -- cgit v1.2.3