~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_server.py

Merge sftp-leaks into catch-them-all resolving conflicts

Show diffs side-by-side

added added

removed removed

Lines of Context:
261
261
            # If the caller didn't pass a specific event, create our own
262
262
            event = threading.Event()
263
263
        super(ThreadWithException, self).__init__(*args, **kwargs)
264
 
        self.set_event(event)
 
264
        self.set_ready_event(event)
265
265
        self.exception = None
266
266
        self.ignored_exceptions = None # see set_ignored_exceptions
267
267
 
269
269
    if sys.version_info < (2, 6):
270
270
        name = property(threading.Thread.getName, threading.Thread.setName)
271
271
 
272
 
    def set_event(self, event):
 
272
    def set_ready_event(self, event):
 
273
        """Set the ``ready`` event used to synchronize exception catching.
 
274
 
 
275
        When the thread uses an event to synchronize itself with another thread
 
276
        (setting it when the other thread can wake up from a ``wait`` call),
 
277
        the event must be set after catching an exception or the other thread
 
278
        will hang.
 
279
 
 
280
        Some threads require multiple events and should set the relevant one
 
281
        when appropriate.
 
282
        """
273
283
        self.ready = event
274
284
 
275
285
    def set_ignored_exceptions(self, ignored):
342
352
    separate thread.
343
353
    """
344
354
 
345
 
    # FIXME: sibling_class is a hack -- vila 20100604
346
 
    def __init__(self, sibling_class):
347
 
        self.sibling_class = sibling_class
 
355
    def __init__(self):
348
356
        self.started = threading.Event()
349
 
        self.serving = threading.Event()
 
357
        self.serving = None
350
358
        self.stopped = threading.Event()
351
359
        # We collect the resources used by the clients so we can release them
352
360
        # when shutting down
354
362
        self.ignored_exceptions = None
355
363
 
356
364
    def server_bind(self):
357
 
        # We need to override the SocketServer bind, yet, we still want to use
358
 
        # it so we need to use the sibling class to call it explicitly
359
 
        self.sibling_class.server_bind(self)
360
 
        # The following has been fixed in 2.5 so we need to provide it for
361
 
        # older python versions.
362
 
        if sys.version < (2, 5):
363
 
            self.server_address = self.socket.getsockname()
 
365
        self.socket.bind(self.server_address)
 
366
        self.server_address = self.socket.getsockname()
364
367
 
365
368
    def serve(self):
366
 
        self.serving.set()
 
369
        self.serving = True
367
370
        self.stopped.clear()
368
371
        # We are listening and ready to accept connections
369
372
        self.started.set()
370
373
        try:
371
 
            while self.serving.isSet():
 
374
            while self.serving:
372
375
                # Really a connection but the python framework is generic and
373
376
                # call them requests
374
377
                self.handle_request()
391
394
                self.handle_error(request, client_address)
392
395
                self.close_request(request)
393
396
 
 
397
    def get_request(self):
 
398
        return self.socket.accept()
 
399
 
394
400
    def verify_request(self, request, client_address):
395
401
        """Verify the request.
396
402
 
398
404
        not even touch a single byte in the socket ! This is useful when we
399
405
        stop the server with a dummy last connection.
400
406
        """
401
 
        return self.serving.isSet()
 
407
        return self.serving
402
408
 
403
409
    def handle_error(self, request, client_address):
404
410
        # Stop serving and re-raise the last exception seen
405
 
        self.serving.clear()
406
 
#        self.sibling_class.handle_error(self, request, client_address)
 
411
        self.serving = False
 
412
        # The following can be used for debugging purposes, it will display the
 
413
        # exception and the traceback just when it occurs instead of waiting
 
414
        # for the thread to be joined.
 
415
 
 
416
        # SocketServer.BaseServer.handle_error(self, request, client_address)
407
417
        raise
408
418
 
409
419
    def ignored_exceptions_during_shutdown(self, e):
455
465
class TestingTCPServer(TestingTCPServerMixin, SocketServer.TCPServer):
456
466
 
457
467
    def __init__(self, server_address, request_handler_class):
458
 
        TestingTCPServerMixin.__init__(self, SocketServer.TCPServer)
 
468
        TestingTCPServerMixin.__init__(self)
459
469
        SocketServer.TCPServer.__init__(self, server_address,
460
470
                                        request_handler_class)
461
471
 
462
472
    def get_request(self):
463
473
        """Get the request and client address from the socket."""
464
 
        sock, addr = self.sibling_class.get_request(self)
 
474
        sock, addr = TestingTCPServerMixin.get_request(self)
465
475
        self.clients.append((sock, addr))
466
476
        return sock, addr
467
477
 
476
486
                                SocketServer.ThreadingTCPServer):
477
487
 
478
488
    def __init__(self, server_address, request_handler_class):
479
 
        TestingTCPServerMixin.__init__(self, SocketServer.ThreadingTCPServer)
480
 
        SocketServer.TCPServer.__init__(self, server_address,
481
 
                                        request_handler_class)
 
489
        TestingTCPServerMixin.__init__(self)
 
490
        SocketServer.ThreadingTCPServer.__init__(self, server_address,
 
491
                                                 request_handler_class)
482
492
 
483
493
    def get_request (self):
484
494
        """Get the request and client address from the socket."""
485
 
        sock, addr = self.sibling_class.get_request(self)
 
495
        sock, addr = TestingTCPServerMixin.get_request(self)
486
496
        # The thread is not create yet, it will be updated in process_request
487
497
        self.clients.append((sock, addr, None))
488
498
        return sock, addr
512
522
        t.start()
513
523
        started.wait()
514
524
        if debug_threads():
515
 
            print 'Client thread %s started' % (t.name,)
 
525
            sys.stderr.write('Client thread %s started\n' % (t.name,))
516
526
        # If an exception occured during the thread start, it will get raised.
517
527
        t.pending_exception()
518
528
 
527
537
            # shutdown. If an exception occurred in the thread it will be
528
538
            # re-raised
529
539
            if debug_threads():
530
 
                print 'Client thread %s will be joined' % (
531
 
                    connection_thread.name,)
 
540
                sys.stderr.write('Client thread %s will be joined\n'
 
541
                                 % (connection_thread.name,))
532
542
            connection_thread.join()
533
543
 
534
544
    def set_ignored_exceptions(self, thread, ignored_exceptions):
575
585
        self.host, self.port = self.server.server_address
576
586
        self._server_thread.name = self.server.server_address
577
587
        if debug_threads():
578
 
            print 'Server thread %s started' % (self._server_thread.name,)
 
588
            sys.stderr.write('Server thread %s started\n'
 
589
                             % (self._server_thread.name,))
579
590
        # If an exception occured during the server start, it will get raised,
580
591
        # otherwise, the server is blocked on its accept() call.
581
592
        self._server_thread.pending_exception()
582
593
        # From now on, we'll use a different event to ensure the server can set
583
594
        # its exception
584
 
        self._server_thread.set_event(self.server.stopped)
 
595
        self._server_thread.set_ready_event(self.server.stopped)
585
596
 
586
597
    def run_server(self):
587
598
        self.server.serve()
595
606
            # one to get out of the blocking listen.
596
607
            self.set_ignored_exceptions(
597
608
                self.server.ignored_exceptions_during_shutdown)
598
 
            self.server.serving.clear()
 
609
            self.server.serving = False
599
610
            if debug_threads():
600
 
                print 'Server thread %s will be joined' % (
601
 
                    self._server_thread.name,)
 
611
                sys.stderr.write('Server thread %s will be joined\n'
 
612
                                 % (self._server_thread.name,))
602
613
            # The server is listening for a last connection, let's give it:
603
614
            last_conn = None
604
615
            try: