~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/smart/server.py

  • Committer: Vincent Ladeuil
  • Date: 2009-10-08 14:34:02 UTC
  • mto: (5247.1.1 first-try)
  • mto: This revision was merged to the branch mainline in revision 5396.
  • Revision ID: v.ladeuil+lp@free.fr-20091008143402-b4uivhhkykn95u8v
Collect and shutdown clients for SmartTCPServer_for_testing.

* bzrlib/tests/http_server.py:
(TestingHTTPServerMixin.serve): Try to avoid hanging in the server
thread, we already catch the socket.timeout exception, we may as
well use it.
(TestingThreadingHTTPServer.process_request_thread): Get rid of
the spurious pdb.set_trace().

* bzrlib/tests/__init__.py:
(ExtendedTestResult.stopTestRun): Display how many threads are
left at the end.
(TestCase._check_leaked_threads): 

* bzrlib/smart/server.py:
(SmartTCPServer.serve_conn): Return the created thread so daughter
classes can play with it.
(SmartTCPServer_for_testing.serve_conn): Collect the client
sockets/threads.
(SmartTCPServer_for_testing.shutdown_client): shutdown a client
socket.
(SmartTCPServer_for_testing.tearDown): shutdown client
sockets/threads.

Show diffs side-by-side

added added

removed removed

Lines of Context:
172
172
            None, handler.serve, name=thread_name)
173
173
        connection_thread.setDaemon(True)
174
174
        connection_thread.start()
 
175
        return connection_thread
175
176
 
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
 
252
        self.clients = []
249
253
 
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)
281
285
 
 
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))
 
290
        return conn_thread
 
291
 
 
292
    def shutdown_client(self, client_socket):
 
293
        """Properly shutdown a client socket.
 
294
 
 
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
 
297
        may hang.
 
298
 
 
299
        This should be called only when no other thread is trying to use the
 
300
        socket.
 
301
        """
 
302
        try:
 
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
 
309
                pass
 
310
            else:
 
311
                raise
 
312
 
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)
 
318
            thread.join()
 
319
            del thread
 
320
        self.clients = []
284
321
        self.chroot_server.tearDown()
285
322
 
286
323
    def get_url(self):