/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to bzrlib/tests/servers.py

  • Committer: Vincent Ladeuil
  • Date: 2011-11-28 11:49:58 UTC
  • mto: This revision was merged to the branch mainline in revision 6321.
  • Revision ID: v.ladeuil+lp@free.fr-20111128114958-ovgttuphf5y0z9xb
Simpler fix for test_smart_server_connection_reset re-using more of the existing test server infrastructure.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2005-2011 Canonical Ltd
2
 
#
3
 
# This program is free software; you can redistribute it and/or modify
4
 
# it under the terms of the GNU General Public License as published by
5
 
# the Free Software Foundation; either version 2 of the License, or
6
 
# (at your option) any later version.
7
 
#
8
 
# This program is distributed in the hope that it will be useful,
9
 
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10
 
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
 
# GNU General Public License for more details.
12
 
#
13
 
# You should have received a copy of the GNU General Public License
14
 
# along with this program; if not, write to the Free Software
15
 
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16
 
 
17
 
 
18
 
import errno
19
 
import socket
20
 
import select
21
 
import threading
22
 
 
23
 
 
24
 
class DisconnectingTCPServer(object):
25
 
    """A TCP server that immediately closes any connection made to it."""
26
 
 
27
 
    def start_server(self):
28
 
        self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
29
 
        self.sock.bind(('127.0.0.1', 0))
30
 
        self.sock.listen(1)
31
 
        self.port = self.sock.getsockname()[1]
32
 
        self.thread = threading.Thread(
33
 
            name='%s (port %d)' % (self.__class__.__name__, self.port),
34
 
            target=self.accept_and_close)
35
 
        self._please_stop = False
36
 
        self.thread.start()
37
 
 
38
 
    def accept_and_close(self):
39
 
        fd = self.sock.fileno()
40
 
        self.sock.setblocking(False)
41
 
        while not self._please_stop:
42
 
            try:
43
 
                # We can't just accept here, because accept is not interrupted
44
 
                # by the listen socket being asynchronously closed by
45
 
                # stop_server.  However, select will be interrupted.
46
 
                select.select([fd], [fd], [fd], 10)
47
 
                conn, addr = self.sock.accept()
48
 
            except (select.error, socket.error), e:
49
 
                en = getattr(e, 'errno') or e[0]
50
 
                if en == errno.EBADF:
51
 
                    # Probably (hopefully) because the stop method was called
52
 
                    # and we should stop.
53
 
                    break
54
 
                elif en == errno.EAGAIN or en == errno.EWOULDBLOCK:
55
 
                    continue
56
 
                else:
57
 
                    raise
58
 
            conn.shutdown(socket.SHUT_RDWR)
59
 
            conn.close()
60
 
 
61
 
    def get_url(self):
62
 
        return 'bzr://127.0.0.1:%d/' % (self.port,)
63
 
 
64
 
    def stop_server(self):
65
 
        self._please_stop = True
66
 
        try:
67
 
            # make sure the thread dies by connecting to the listening socket,
68
 
            # just in case the test failed to do so.
69
 
            conn = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
70
 
            conn.connect(self.sock.getsockname())
71
 
            conn.close()
72
 
        except socket.error:
73
 
            pass
74
 
        self.sock.close()
75
 
        self.thread.join()