~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_server.py

  • Committer: Tarmac
  • Author(s): Vincent Ladeuil
  • Date: 2017-01-30 14:42:05 UTC
  • mfrom: (6620.1.1 trunk)
  • Revision ID: tarmac-20170130144205-r8fh2xpmiuxyozpv
Merge  2.7 into trunk including fix for bug #1657238 [r=vila]

Show diffs side-by-side

added added

removed removed

Lines of Context:
19
19
import SocketServer
20
20
import sys
21
21
import threading
 
22
import traceback
22
23
 
23
24
 
24
25
from bzrlib import (
25
26
    cethread,
 
27
    errors,
26
28
    osutils,
27
29
    transport,
28
30
    urlutils,
287
289
 
288
290
    def serve(self):
289
291
        self.serving = True
290
 
        self.stopped.clear()
291
292
        # We are listening and ready to accept connections
292
293
        self.started.set()
293
294
        try:
312
313
                self.process_request(request, client_address)
313
314
            except:
314
315
                self.handle_error(request, client_address)
315
 
                self.close_request(request)
 
316
        else:
 
317
            self.close_request(request)
316
318
 
317
319
    def get_request(self):
318
320
        return self.socket.accept()
332
334
        # The following can be used for debugging purposes, it will display the
333
335
        # exception and the traceback just when it occurs instead of waiting
334
336
        # for the thread to be joined.
335
 
 
336
337
        # SocketServer.BaseServer.handle_error(self, request, client_address)
 
338
 
 
339
        # We call close_request manually, because we are going to raise an
 
340
        # exception. The SocketServer implementation calls:
 
341
        #   handle_error(...)
 
342
        #   close_request(...)
 
343
        # But because we raise the exception, close_request will never be
 
344
        # triggered. This helps client not block waiting for a response when
 
345
        # the server gets an exception.
 
346
        self.close_request(request)
337
347
        raise
338
348
 
339
349
    def ignored_exceptions_during_shutdown(self, e):
419
429
        SocketServer.ThreadingTCPServer.__init__(self, server_address,
420
430
                                                 request_handler_class)
421
431
 
422
 
    def get_request (self):
 
432
    def get_request(self):
423
433
        """Get the request and client address from the socket."""
424
434
        sock, addr = TestingTCPServerMixin.get_request(self)
425
 
        # The thread is not create yet, it will be updated in process_request
 
435
        # The thread is not created yet, it will be updated in process_request
426
436
        self.clients.append((sock, addr, None))
427
437
        return sock, addr
428
438
 
429
 
    def process_request_thread(self, started, stopped, request, client_address):
 
439
    def process_request_thread(self, started, detached, stopped,
 
440
                               request, client_address):
430
441
        started.set()
 
442
        # We will be on our own once the server tells us we're detached
 
443
        detached.wait()
431
444
        SocketServer.ThreadingTCPServer.process_request_thread(
432
445
            self, request, client_address)
433
446
        self.close_request(request)
436
449
    def process_request(self, request, client_address):
437
450
        """Start a new thread to process the request."""
438
451
        started = threading.Event()
 
452
        detached = threading.Event()
439
453
        stopped = threading.Event()
440
454
        t = TestThread(
441
455
            sync_event=stopped,
442
456
            name='%s -> %s' % (client_address, self.server_address),
443
457
            target = self.process_request_thread,
444
 
            args = (started, stopped, request, client_address))
 
458
            args = (started, detached, stopped, request, client_address))
445
459
        # Update the client description
446
460
        self.clients.pop()
447
461
        self.clients.append((request, client_address, t))
450
464
        t.set_ignored_exceptions(self.ignored_exceptions)
451
465
        t.start()
452
466
        started.wait()
453
 
        if debug_threads():
454
 
            sys.stderr.write('Client thread %s started\n' % (t.name,))
455
467
        # If an exception occured during the thread start, it will get raised.
456
468
        t.pending_exception()
 
469
        if debug_threads():
 
470
            sys.stderr.write('Client thread %s started\n' % (t.name,))
 
471
        # Tell the thread, it's now on its own for exception handling.
 
472
        detached.set()
457
473
 
458
474
    # The following methods are called by the main thread
459
475
 
508
524
            sync_event=self.server.started,
509
525
            target=self.run_server)
510
526
        self._server_thread.start()
511
 
        # Wait for the server thread to start (i.e release the lock)
 
527
        # Wait for the server thread to start (i.e. release the lock)
512
528
        self.server.started.wait()
513
529
        # Get the real address, especially the port
514
530
        self.host, self.port = self.server.server_address
596
612
                                                 server)
597
613
 
598
614
    def handle(self):
599
 
        while not self.finished:
600
 
            server_protocol = self._build_protocol()
601
 
            self._serve_one_request(server_protocol)
602
 
 
603
 
 
604
 
_DEFAULT_TESTING_CLIENT_TIMEOUT = 4.0
 
615
        try:
 
616
            while not self.finished:
 
617
                server_protocol = self._build_protocol()
 
618
                self._serve_one_request(server_protocol)
 
619
        except errors.ConnectionTimeout:
 
620
            # idle connections aren't considered a failure of the server
 
621
            return
 
622
 
 
623
 
 
624
_DEFAULT_TESTING_CLIENT_TIMEOUT = 60.0
605
625
 
606
626
class TestingSmartServer(TestingThreadingTCPServer, server.SmartTCPServer):
607
627