summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRichard Purdie <richard.purdie@linuxfoundation.org>2018-12-24 16:34:32 +0000
committerRichard Purdie <richard.purdie@linuxfoundation.org>2018-12-26 11:10:33 +0000
commit2365e00b7c5e78f2ce5043a2e2495fef346ecb3d (patch)
tree57fa2b5228395bd94162c791eb580a04e4a15cc5
parent5bc4f6935bf94b1d4e05e8652b5700f9fca389e5 (diff)
downloadpoky-2365e00b7c5e78f2ce5043a2e2495fef346ecb3d.tar.gz
bitbake: 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. (Bitbake rev: 02845a561b38658ac3edf5cc9c34625ed860d34f) Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
-rw-r--r--bitbake/lib/bb/server/process.py56
1 files changed, 34 insertions, 22 deletions
diff --git a/bitbake/lib/bb/server/process.py b/bitbake/lib/bb/server/process.py
index 1e4b51e35e..28b8eb9b86 100644
--- a/bitbake/lib/bb/server/process.py
+++ b/bitbake/lib/bb/server/process.py
@@ -130,6 +130,7 @@ class ProcessServer(multiprocessing.Process):
130 bb.utils.set_process_name("Cooker") 130 bb.utils.set_process_name("Cooker")
131 131
132 ready = [] 132 ready = []
133 newconnections = []
133 134
134 self.controllersock = False 135 self.controllersock = False
135 fds = [self.sock] 136 fds = [self.sock]
@@ -138,37 +139,48 @@ class ProcessServer(multiprocessing.Process):
138 print("Entering server connection loop") 139 print("Entering server connection loop")
139 140
140 def disconnect_client(self, fds): 141 def disconnect_client(self, fds):
141 if not self.haveui:
142 return
143 print("Disconnecting Client") 142 print("Disconnecting Client")
144 fds.remove(self.controllersock) 143 if self.controllersock:
145 fds.remove(self.command_channel) 144 fds.remove(self.controllersock)
146 bb.event.unregister_UIHhandler(self.event_handle, True) 145 self.controllersock.close()
147 self.command_channel_reply.writer.close() 146 self.controllersock = False
148 self.event_writer.writer.close() 147 if self.haveui:
149 del self.event_writer 148 fds.remove(self.command_channel)
150 self.controllersock.close() 149 bb.event.unregister_UIHhandler(self.event_handle, True)
151 self.controllersock = False 150 self.command_channel_reply.writer.close()
152 self.haveui = False 151 self.event_writer.writer.close()
153 self.lastui = time.time() 152 self.command_channel.close()
154 self.cooker.clientComplete() 153 self.command_channel = False
155 if self.timeout is None: 154 del self.event_writer
155 self.lastui = time.time()
156 self.cooker.clientComplete()
157 self.haveui = False
158 ready = select.select(fds,[],[],0)[0]
159 if newconnections:
160 print("Starting new client")
161 conn = newconnections.pop(-1)
162 fds.append(conn)
163 self.controllersock = conn
164 elif self.timeout is None and not ready:
156 print("No timeout, exiting.") 165 print("No timeout, exiting.")
157 self.quit = True 166 self.quit = True
158 167
159 while not self.quit: 168 while not self.quit:
160 if self.sock in ready: 169 if self.sock in ready:
161 self.controllersock, address = self.sock.accept() 170 while select.select([self.sock],[],[],0)[0]:
162 if self.haveui: 171 controllersock, address = self.sock.accept()
163 print("Dropping connection attempt as we have a UI %s" % (str(ready))) 172 if self.controllersock:
164 self.controllersock.close() 173 print("Queuing %s (%s)" % (str(ready), str(newconnections)))
165 else: 174 newconnections.append(controllersock)
166 print("Accepting %s" % (str(ready))) 175 else:
167 fds.append(self.controllersock) 176 print("Accepting %s (%s)" % (str(ready), str(newconnections)))
177 self.controllersock = controllersock
178 fds.append(controllersock)
168 if self.controllersock in ready: 179 if self.controllersock in ready:
169 try: 180 try:
170 print("Connecting Client") 181 print("Processing Client")
171 ui_fds = recvfds(self.controllersock, 3) 182 ui_fds = recvfds(self.controllersock, 3)
183 print("Connecting Client")
172 184
173 # Where to write events to 185 # Where to write events to
174 writer = ConnectionWriter(ui_fds[0]) 186 writer = ConnectionWriter(ui_fds[0])