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/serv.py | |
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/serv.py')
-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): |