Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(549)

Unified Diff: scripts/slave/daemonizer.py

Issue 1328623004: Add logic to daemonizer to be able to kill what it daemonizes (Closed) Base URL: https://chromium.googlesource.com/chromium/tools/build.git@master
Patch Set: Parent of daemon waits again Created 5 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: scripts/slave/daemonizer.py
diff --git a/scripts/slave/daemonizer.py b/scripts/slave/daemonizer.py
index 2a75f98f7f4b9fda82b0ea80f3dfb21a5a1dce7d..288401ec9731c3feb423e198c1e1dd17a281bfca 100755
--- a/scripts/slave/daemonizer.py
+++ b/scripts/slave/daemonizer.py
@@ -12,7 +12,7 @@ USAGE:
daemonizer.py [options] -- <script> [args]
- - options are options to this script. Note, currently there are none!
+ - options are options to this script.
- script is the script to daemonize or run in the background
- args are the arguments that one might want to pass the <script>
"""
@@ -20,12 +20,44 @@ USAGE:
# TODO(sivachandra): Enhance this script by enforcing a protocol of
# communication between the parent (this script) and the daemon script.
+# TODO(bpastene): Improve file handling by adding flocks over file io
+# as implemented in infra/libs/service_utils/_daemon_nix.py
+
+import argparse
+import logging
import os
+import signal
import subprocess
import sys
-def daemonize():
+def restart(cmd, pid_file_path):
+ # Check for the pid_file to see if the daemon's already running
+ # and restart it if it is.
+ if pid_file_path == None:
+ logging.error('pid_file_path arg must be specified when '
+ 'restarting a daemon')
+ return 1
+ try:
+ with open(pid_file_path, 'r') as pid_file:
+ pid = int(pid_file.readline())
+ except (IOError, ValueError):
+ pid = None
+
+ if pid:
+ logging.info(
+ "%s pid file already exists, attempting to kill process %d",
+ pid_file_path,
+ pid)
+ try:
+ os.kill(pid, signal.SIGTERM)
+ except OSError:
+ logging.exception("Unable to kill old daemon process")
+
+ return daemonize(cmd, pid_file_path)
+
+
+def daemonize(cmd, pid_file_path):
"""This function is based on the Python recipe provided here:
http://www.jejik.com/articles/2007/02/a_simple_unix_linux_daemon_in_python/
"""
@@ -66,27 +98,64 @@ def daemonize():
os.dup2(so.fileno(), sys.stdout.fileno())
os.dup2(se.fileno(), sys.stderr.fileno())
+ proc = subprocess.Popen(cmd)
-def print_usage(err_msg):
- print >> sys.stderr, err_msg
- sys.exit('Usage: daemonizer.py [options] -- arg0 [argN...]')
+ # Write pid to file if applicable.
+ if pid_file_path:
+ try:
+ with open(pid_file_path, 'w') as pid_file:
+ pid_file.write('%s' % str(proc.pid))
+ except (IOError):
+ logging.exception("Unable to write pid to file")
+ proc.communicate()
+ return proc.returncode
-def main():
- try:
- idx = sys.argv.index('--')
- except ValueError:
- print_usage('Separator -- not found')
- cmd = sys.argv[idx+1:]
- if not cmd:
- print_usage('arg0 not specified for sub command')
+def stop(pid_file_path):
+ if pid_file_path == None:
+ logging.error("pid_file_path arg must be specified when stopping a daemon")
+ return 1
+ try:
+ with open(pid_file_path) as pid_file:
+ pid = int(pid_file.readline())
+ logging.info('Sending SIGTERM to %d', pid)
+ os.kill(pid, signal.SIGTERM)
+ os.remove(pid_file_path)
+ except (IOError, OSError):
+ logging.exception('Error terminating daemon process')
- # TODO(sivachandra): When required in the future, use optparse to parse args
- # from sys.argv[:idx]
- daemonize()
- return subprocess.call(cmd)
+def main():
+ parser = argparse.ArgumentParser(
+ description='Launch, or shutdown, a daemon process.')
+ parser.add_argument(
+ '--action',
+ default='daemonize',
+ choices=['restart','stop','daemonize'],
+ help='What action to take. Both restart and stop attempt to write & read '
+ 'the pid to a file so it can kill or restart it, while daemonize simply '
+ 'fires and forgets.')
+ parser.add_argument(
+ '--pid-file-path',
+ type=str,
+ default=None,
+ help='Path of tmp file to store the daemon\'s pid.')
+ parser.add_argument(
+ '--', dest='',
+ required=False,
+ help='Optional delimiter dividing daemonizer options with the command. '
+ 'This is here to ensure it\'s backwards compatible with the previous '
+ 'version of daemonizer.')
+ parser.add_argument('cmd', help='Command (+ args) to daemonize', nargs='*')
+ args = parser.parse_args()
+
+ if args.action == 'restart':
+ return restart(args.cmd, args.pid_file_path)
+ elif args.action == 'daemonize':
+ return daemonize(args.cmd, None)
+ elif args.action == 'stop':
+ return stop(args.pid_file_path)
if __name__ == '__main__':
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698