diff options
| author | Richard Purdie <richard.purdie@linuxfoundation.org> | 2017-07-24 13:39:12 +0100 |
|---|---|---|
| committer | Richard Purdie <richard.purdie@linuxfoundation.org> | 2017-07-24 16:57:14 +0100 |
| commit | 57196bc6e4a07f855b3073b6120211ddda179077 (patch) | |
| tree | 1f796d3c57afb2605fe1ba0a9899936f2396de5b /bitbake/lib/prserv | |
| parent | 0f20512deac20f3ec7241ff431c8523ce3c66034 (diff) | |
| download | poky-57196bc6e4a07f855b3073b6120211ddda179077.tar.gz | |
bitbake: prserv/serv: Improve process exit handling
The server shutdown is currenlty laggy and race prone. This patch:
* adds a waitpid so that no zombie server is left around if its not
running in daemon mode.
* adds a quit "sentinal" using a pipe so that we're not sitting in
a socket poll() until timeout in order just to quit.
* use a select() call to poll the socket and the pipe for a quit signal.
The net result of this change is that the prserv exits with the cooker server
and it does so immediately and doesn't wait for the select/poll calls to
timeout. This makes bitbake a lot more responsive for startup/shutdown and
doesn't cause UI timeout errors as often when prserv is used.
(Bitbake rev: 0b5a837477d18442caf97dd0fa14a806c54f5842)
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Diffstat (limited to 'bitbake/lib/prserv')
| -rw-r--r-- | bitbake/lib/prserv/serv.py | 19 |
1 files changed, 17 insertions, 2 deletions
diff --git a/bitbake/lib/prserv/serv.py b/bitbake/lib/prserv/serv.py index 5f061c2623..3145689ba8 100644 --- a/bitbake/lib/prserv/serv.py +++ b/bitbake/lib/prserv/serv.py | |||
| @@ -10,6 +10,7 @@ import bb.server.xmlrpcclient | |||
| 10 | import prserv | 10 | import prserv |
| 11 | import prserv.db | 11 | import prserv.db |
| 12 | import errno | 12 | import errno |
| 13 | import select | ||
| 13 | 14 | ||
| 14 | logger = logging.getLogger("BitBake.PRserv") | 15 | logger = logging.getLogger("BitBake.PRserv") |
| 15 | 16 | ||
| @@ -59,6 +60,8 @@ class PRServer(SimpleXMLRPCServer): | |||
| 59 | self.register_function(self.importone, "importone") | 60 | self.register_function(self.importone, "importone") |
| 60 | self.register_introspection_functions() | 61 | self.register_introspection_functions() |
| 61 | 62 | ||
| 63 | self.quitpipein, self.quitpipeout = os.pipe() | ||
| 64 | |||
| 62 | self.requestqueue = queue.Queue() | 65 | self.requestqueue = queue.Queue() |
| 63 | self.handlerthread = threading.Thread(target = self.process_request_thread) | 66 | self.handlerthread = threading.Thread(target = self.process_request_thread) |
| 64 | self.handlerthread.daemon = False | 67 | self.handlerthread.daemon = False |
| @@ -153,11 +156,16 @@ class PRServer(SimpleXMLRPCServer): | |||
| 153 | 156 | ||
| 154 | def quit(self): | 157 | def quit(self): |
| 155 | self.quit=True | 158 | self.quit=True |
| 159 | os.write(self.quitpipeout, b"q") | ||
| 160 | os.close(self.quitpipeout) | ||
| 156 | return | 161 | return |
| 157 | 162 | ||
| 158 | def work_forever(self,): | 163 | def work_forever(self,): |
| 159 | self.quit = False | 164 | self.quit = False |
| 160 | self.timeout = 0.5 | 165 | # This timeout applies to the poll in TCPServer, we need the select |
| 166 | # below to wake on our quit pipe closing. We only ever call into handle_request | ||
| 167 | # if there is data there. | ||
| 168 | self.timeout = 0.01 | ||
| 161 | 169 | ||
| 162 | bb.utils.set_process_name("PRServ") | 170 | bb.utils.set_process_name("PRServ") |
| 163 | 171 | ||
| @@ -170,11 +178,16 @@ class PRServer(SimpleXMLRPCServer): | |||
| 170 | 178 | ||
| 171 | self.handlerthread.start() | 179 | self.handlerthread.start() |
| 172 | while not self.quit: | 180 | while not self.quit: |
| 173 | self.handle_request() | 181 | ready = select.select([self.fileno(), self.quitpipein], [], [], 30) |
| 182 | if self.quit: | ||
| 183 | break | ||
| 184 | if self.fileno() in ready[0]: | ||
| 185 | self.handle_request() | ||
| 174 | self.handlerthread.join() | 186 | self.handlerthread.join() |
| 175 | self.db.disconnect() | 187 | self.db.disconnect() |
| 176 | logger.info("PRServer: stopping...") | 188 | logger.info("PRServer: stopping...") |
| 177 | self.server_close() | 189 | self.server_close() |
| 190 | os.close(self.quitpipein) | ||
| 178 | return | 191 | return |
| 179 | 192 | ||
| 180 | def start(self): | 193 | def start(self): |
| @@ -182,6 +195,7 @@ class PRServer(SimpleXMLRPCServer): | |||
| 182 | pid = self.daemonize() | 195 | pid = self.daemonize() |
| 183 | else: | 196 | else: |
| 184 | pid = self.fork() | 197 | pid = self.fork() |
| 198 | self.pid = pid | ||
| 185 | 199 | ||
| 186 | # Ensure both the parent sees this and the child from the work_forever log entry above | 200 | # Ensure both the parent sees this and the child from the work_forever log entry above |
| 187 | logger.info("Started PRServer with DBfile: %s, IP: %s, PORT: %s, PID: %s" % | 201 | logger.info("Started PRServer with DBfile: %s, IP: %s, PORT: %s, PID: %s" % |
| @@ -472,6 +486,7 @@ def auto_shutdown(d=None): | |||
| 472 | PRServerConnection(host, port).terminate() | 486 | PRServerConnection(host, port).terminate() |
| 473 | except: | 487 | except: |
| 474 | logger.critical("Stop PRService %s:%d failed" % (host,port)) | 488 | logger.critical("Stop PRService %s:%d failed" % (host,port)) |
| 489 | os.waitpid(singleton.prserv.pid, 0) | ||
| 475 | singleton = None | 490 | singleton = None |
| 476 | 491 | ||
| 477 | def ping(host, port): | 492 | def ping(host, port): |
