~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_server.py

Merge propagate-exceptions into http-leaks resolving conflicts

Show diffs side-by-side

added added

removed removed

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