instalog: change rpc stop function to be asynchronous by default
- Fix a bug in daemon_utils which doesn't save PID to disk in
foreground mode.
- Change RPC Stop function in Core to be asynchronous by default.
BUG=None
TEST=Manually on local machine
Change-Id: I03e9f71d4735a613838004ea3f88e81bb6e9eec1
Reviewed-on: https://chromium-review.googlesource.com/429670
Commit-Ready: Joel Kitching <kitching@chromium.org>
Tested-by: Joel Kitching <kitching@chromium.org>
Reviewed-by: Chun-Tsen Kuo <chuntsen@chromium.org>
diff --git a/py/instalog/core.py b/py/instalog/core.py
index 4cb01da..5a30ff3 100644
--- a/py/instalog/core.py
+++ b/py/instalog/core.py
@@ -233,8 +233,8 @@
logging.exception(e)
# In case there was some error in the Run function (exception or otherwise),
- # call Stop at the end just in case.
- self.Stop()
+ # call Stop synchronously at the end just in case.
+ self.Stop(True)
logging.warning('Stopped')
def _Start(self):
@@ -253,9 +253,21 @@
with self._rpc_lock:
return self._state is UP
- def Stop(self):
+ def Stop(self, sync=False):
+ """Stops Instalog.
+
+ Args:
+ sync: If true, only returns when Instalog has stopped running.
+ """
+ # If a Stop is already in process, return immediately.
if self._state in (STOPPING, DOWN):
return
+
+ # If called in asynchronous mode, kick off a thread to perform the stop.
+ if not sync:
+ threading.Thread(target=self.Stop, args=(True,)).start()
+ return
+
self._ShutdownRPCServer()
with self._rpc_lock:
self._state = STOPPING
diff --git a/py/instalog/daemon_utils.py b/py/instalog/daemon_utils.py
index f4cc1dd..9ca0c7e 100644
--- a/py/instalog/daemon_utils.py
+++ b/py/instalog/daemon_utils.py
@@ -78,6 +78,11 @@
os.dup2(so.fileno(), sys.stdout.fileno())
os.dup2(se.fileno(), sys.stderr.fileno())
+ # Register pidfile.
+ self._RegisterPID()
+
+ def _RegisterPID(self):
+ """Saves the PID and registers a handler to remove the file on exit."""
# Remove pidfile when exiting.
atexit.register(self._RemovePID)
@@ -129,10 +134,15 @@
sys.stderr.write(message % self.pidfile)
sys.exit(1)
- # Start the daemon.
- if not foreground:
- if self._Daemonize() == PARENT:
- return
+ # Foreground mode: Registering the PID is sufficient.Daemonize if necessary.
+ if foreground:
+ self._RegisterPID()
+ # Daemon mode: Daemonize. The function will fork and return with two
+ # possible values: PARENT or CHILD.
+ # PARENT is the original process and should return to caller.
+ # CHILD is the daemon and should invoke self.Run.
+ elif self._Daemonize() == PARENT:
+ return
self.Run(foreground)
def Stop(self):