aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRichard Purdie <richard.purdie@linuxfoundation.org>2018-12-24 16:34:32 +0000
committerRichard Purdie <richard.purdie@linuxfoundation.org>2019-02-25 22:20:26 +0000
commitf675293d86504db66442532258d99b26333742bf (patch)
treef2cd86fafb002cab29e7df408f3890bfd0342a54
parentf770d6a332812031682dc6bef1a2a84da52a4c32 (diff)
downloadbitbake-f675293d86504db66442532258d99b26333742bf.tar.gz
process: Rewrite multiple connection handling
If the bitbake server recieved multiple connections, it currently closes ones it can't handle (while its dealing with another). This is rather antisocial behaviour which causes clients to quickly run through their retries and abort. Instead, queue any other connections until the current one is closed. This way the client can decide when it wants to stop waiting for the server. If the client is gone by the time we handle it, we handle that gracefully. This also fixes a number of bugs in the connection handling where connections which did drop early were badly handled causing tracebacks in the logs. Also, handle queue incomming connections in a loop to ensure that the main client handling doesn't starve that piece of the system. This code was stress tested by running 50 connection attempts in parallel at once, ensuring the code correctly handled them. Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
-rw-r--r--lib/bb/server/process.py56
1 files changed, 34 insertions, 22 deletions
diff --git a/lib/bb/server/process.py b/lib/bb/server/process.py
index 49a1b7c14..aa0669fe9 100644
--- a/lib/bb/server/process.py
+++ b/lib/bb/server/process.py
@@ -130,6 +130,7 @@ class ProcessServer(multiprocessing.Process):
bb.utils.set_process_name("Cooker")
ready = []
+ newconnections = []
self.controllersock = False
fds = [self.sock]
@@ -138,37 +139,48 @@ class ProcessServer(multiprocessing.Process):
print("Entering server connection loop")
def disconnect_client(self, fds):
- if not self.haveui:
- return
print("Disconnecting Client")
- fds.remove(self.controllersock)
- fds.remove(self.command_channel)
- bb.event.unregister_UIHhandler(self.event_handle, True)
- self.command_channel_reply.writer.close()
- self.event_writer.writer.close()
- del self.event_writer
- self.controllersock.close()
- self.controllersock = False
- self.haveui = False
- self.lastui = time.time()
- self.cooker.clientComplete()
- if self.timeout is None:
+ if self.controllersock:
+ fds.remove(self.controllersock)
+ self.controllersock.close()
+ self.controllersock = False
+ if self.haveui:
+ fds.remove(self.command_channel)
+ bb.event.unregister_UIHhandler(self.event_handle, True)
+ self.command_channel_reply.writer.close()
+ self.event_writer.writer.close()
+ self.command_channel.close()
+ self.command_channel = False
+ del self.event_writer
+ self.lastui = time.time()
+ self.cooker.clientComplete()
+ self.haveui = False
+ ready = select.select(fds,[],[],0)[0]
+ if newconnections:
+ print("Starting new client")
+ conn = newconnections.pop(-1)
+ fds.append(conn)
+ self.controllersock = conn
+ elif self.timeout is None and not ready:
print("No timeout, exiting.")
self.quit = True
while not self.quit:
if self.sock in ready:
- self.controllersock, address = self.sock.accept()
- if self.haveui:
- print("Dropping connection attempt as we have a UI %s" % (str(ready)))
- self.controllersock.close()
- else:
- print("Accepting %s" % (str(ready)))
- fds.append(self.controllersock)
+ while select.select([self.sock],[],[],0)[0]:
+ controllersock, address = self.sock.accept()
+ if self.controllersock:
+ print("Queuing %s (%s)" % (str(ready), str(newconnections)))
+ newconnections.append(controllersock)
+ else:
+ print("Accepting %s (%s)" % (str(ready), str(newconnections)))
+ self.controllersock = controllersock
+ fds.append(controllersock)
if self.controllersock in ready:
try:
- print("Connecting Client")
+ print("Processing Client")
ui_fds = recvfds(self.controllersock, 3)
+ print("Connecting Client")
# Where to write events to
writer = ConnectionWriter(ui_fds[0])