From 85256c8fa986f2a3258e75a22bb8d0656ffa41bf Mon Sep 17 00:00:00 2001 From: Richard Purdie Date: Tue, 8 Sep 2015 23:32:07 +0100 Subject: bitbake: prserv: SIGTERM and deamonization fixes Worryingly, if you SIGKILL the bitbake cooker, an autostarted PR server will remain behind. It turns out there are a few things we should do: * The PR service doesn't need to daemonize when started from cooker, it just complicated the process lifecycle. Add a fork() method to handle this and use the non-daemon mode for the singleton. * Reset the sigterm and sigint handlers. Bitbake cooker installs its own which we inherit meaning PR server was ignoring SIGTERM. Installing our own handlers which include a sync makes most sense here. Since we're in the code, make it sync the database on SIGINT. * Use the new bb.utils.signal_on_parent_exit() call so that we get a SIGTERM when the parent (usually cooker) exits and we can shutdown too. Alternatives would be having an open pipe or polling os.getppid() for changes but this seems more effective. (Bitbake rev: 05d31fa1f56bd3d3d363a16a421d9ba7541d4293) Signed-off-by: Richard Purdie --- bitbake/lib/prserv/serv.py | 34 +++++++++++++++++++++++++++++++--- 1 file changed, 31 insertions(+), 3 deletions(-) (limited to 'bitbake') diff --git a/bitbake/lib/prserv/serv.py b/bitbake/lib/prserv/serv.py index 05074854a2..5c0ffb9925 100644 --- a/bitbake/lib/prserv/serv.py +++ b/bitbake/lib/prserv/serv.py @@ -97,6 +97,13 @@ class PRServer(SimpleXMLRPCServer): self.table.sync() self.table.sync_if_dirty() + def sigint_handler(self, signum, stack): + self.table.sync() + + def sigterm_handler(self, signum, stack): + self.table.sync() + raise SystemExit + def process_request(self, request, client_address): self.requestqueue.put((request, client_address)) @@ -147,7 +154,11 @@ class PRServer(SimpleXMLRPCServer): return def start(self): - pid = self.daemonize() + if self.daemon: + pid = self.daemonize() + else: + pid = self.fork() + # Ensure both the parent sees this and the child from the work_forever log entry above logger.info("Started PRServer with DBfile: %s, IP: %s, PORT: %s, PID: %s" % (self.dbfile, self.host, self.port, str(pid))) @@ -180,6 +191,24 @@ class PRServer(SimpleXMLRPCServer): except OSError as e: raise Exception("%s [%d]" % (e.strerror, e.errno)) + self.cleanup_handles() + os._exit(0) + + def fork(self): + try: + pid = os.fork() + if pid > 0: + return pid + except OSError as e: + raise Exception("%s [%d]" % (e.strerror, e.errno)) + + bb.utils.signal_on_parent_exit("SIGTERM") + self.cleanup_handles() + os._exit(0) + + def cleanup_handles(self): + signal.signal(signal.SIGINT, self.sigint_handler) + signal.signal(signal.SIGTERM, self.sigterm_handler) os.umask(0) os.chdir("/") @@ -212,7 +241,6 @@ class PRServer(SimpleXMLRPCServer): self.work_forever() self.delpid() - os._exit(0) class PRServSingleton(object): def __init__(self, dbfile, logfile, interface): @@ -223,7 +251,7 @@ class PRServSingleton(object): self.port = None def start(self): - self.prserv = PRServer(self.dbfile, self.logfile, self.interface) + self.prserv = PRServer(self.dbfile, self.logfile, self.interface, daemon=False) self.prserv.start() self.host, self.port = self.prserv.getinfo() -- cgit v1.2.3-54-g00ecf