172
172
None, handler.serve, name=thread_name)
173
173
connection_thread.setDaemon(True)
174
174
connection_thread.start()
175
return connection_thread
176
177
def start_background_thread(self, thread_name_suffix=''):
177
178
self._started.clear()
246
247
SmartTCPServer.__init__(self, None)
247
248
self.client_path_extra = None
248
249
self.thread_name_suffix = thread_name_suffix
250
# We collect the sockets/threads used by the clients so we can
251
# close/join them when shutting down
250
254
def get_backing_transport(self, backing_transport_server):
251
255
"""Get a backing transport from a server we are decorating."""
279
283
self.root_client_path = self.client_path_extra = client_path_extra
280
284
self.start_background_thread(self.thread_name_suffix)
286
def serve_conn(self, conn, thread_name_suffix):
287
conn_thread = super(SmartTCPServer_for_testing, self).serve_conn(
288
conn, thread_name_suffix)
289
self.clients.append((conn, conn_thread))
292
def shutdown_client(self, client_socket):
293
"""Properly shutdown a client socket.
295
Under some circumstances (as in bug #383920), we need to force the
296
shutdown as python delays it until gc occur otherwise and the client
299
This should be called only when no other thread is trying to use the
303
# The request process has been completed, the thread is about to
304
# die, let's shutdown the socket if we can.
305
client_socket.shutdown(socket.SHUT_RDWR)
306
except (socket.error, select.error), e:
307
if e[0] in (errno.EBADF, errno.ENOTCONN):
308
# Right, the socket is already down
282
313
def tearDown(self):
283
314
self.stop_background_thread()
315
# Let's close all our pending clients too
316
for sock, thread in self.clients:
317
self.shutdown_client(sock)
284
321
self.chroot_server.tearDown()
286
323
def get_url(self):