Make Server class octoprint_daemon-aware, make sure terminated() gets invoked on it upon SIGTERM and update respective test

(cherry picked from commit 75f8fac)
This commit is contained in:
Kyle Evans 2016-05-06 23:18:57 +02:00 committed by Gina Häußge
parent 91b5fc6b0d
commit 8263c6072a
2 changed files with 35 additions and 29 deletions

View file

@ -12,35 +12,35 @@ class Daemon:
Usage: subclass the daemon class and override the run() method."""
def __init__(self, pidfile): self.pidfile = pidfile
def daemonize(self):
"""Deamonize class. UNIX double fork mechanism."""
try:
pid = os.fork()
try:
pid = os.fork()
if pid > 0:
# exit first parent
sys.exit(0)
except OSError as err:
sys.exit(0)
except OSError as err:
sys.stderr.write('fork #1 failed: {0}\n'.format(err))
sys.exit(1)
# decouple from parent environment
os.chdir('/')
os.setsid()
os.chdir('/')
os.setsid()
os.umask(002)
# do second fork
try:
pid = os.fork()
try:
pid = os.fork()
if pid > 0:
# exit from second parent
sys.exit(0)
except OSError as err:
sys.exit(0)
except OSError as err:
sys.stderr.write('fork #2 failed: {0}\n'.format(err))
sys.exit(1)
sys.exit(1)
# redirect standard file descriptors
sys.stdout.flush()
sys.stderr.flush()
@ -51,18 +51,14 @@ class Daemon:
os.dup2(si.fileno(), sys.stdin.fileno())
os.dup2(so.fileno(), sys.stdout.fileno())
os.dup2(se.fileno(), sys.stderr.fileno())
# write pidfile
pid = str(os.getpid())
with open(self.pidfile,'w+') as f:
f.write(pid + '\n')
# register listener for SIGTERM
signal.signal(signal.SIGTERM, self.term)
def term(self, _signo, _stack_frame):
os.remove(self.pidfile)
sys.exit(0)
def terminated(self):
self.remove_pidfile()
def start(self):
"""Start the daemon."""
@ -74,13 +70,13 @@ class Daemon:
pid = int(pf.read().strip())
except IOError:
pid = None
if pid:
message = "pidfile {0} already exist. " + \
"Daemon already running?\n"
sys.stderr.write(message.format(self.pidfile))
sys.exit(1)
# Start the daemon
self.daemonize()
self.run()
@ -94,14 +90,14 @@ class Daemon:
pid = int(pf.read().strip())
except IOError:
pid = None
if not pid:
message = "pidfile {0} does not exist. " + \
"Daemon not running?\n"
sys.stderr.write(message.format(self.pidfile))
return # not an error in a restart
# Try killing the daemon process
# Try killing the daemon process
try:
while 1:
os.kill(pid, signal.SIGTERM)
@ -122,7 +118,11 @@ class Daemon:
def run(self):
"""You should override this method when you subclass Daemon.
It will be called after the process has been daemonized by
It will be called after the process has been daemonized by
start() or restart()."""
def remove_pidfile(self):
"""Removes the pidfile."""
if os.path.isfile(self.pidfile):
os.remove(self.pidfile)

View file

@ -114,7 +114,7 @@ def load_user(id):
class Server(object):
def __init__(self, configfile=None, basedir=None, host="0.0.0.0", port=5000, debug=False, allowRoot=False, logConf=None):
def __init__(self, configfile=None, basedir=None, host="0.0.0.0", port=5000, debug=False, allowRoot=False, logConf=None, octoprint_daemon=None):
self._configfile = configfile
self._basedir = basedir
self._host = host
@ -123,6 +123,7 @@ class Server(object):
self._allowRoot = allowRoot
self._logConf = logConf
self._server = None
self._octoprint_daemon = octoprint_daemon
self._logger = None
@ -505,6 +506,11 @@ class Server(object):
observer.join()
octoprint.plugin.call_plugin(octoprint.plugin.ShutdownPlugin,
"on_shutdown")
if self._octoprint_daemon is not None:
self._logger.info("Cleaning up daemon pidfile")
self._octoprint_daemon.terminated()
self._logger.info("Goodbye!")
atexit.register(on_shutdown)