~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/osutils.py

  • Committer: Canonical.com Patch Queue Manager
  • Date: 2010-03-26 05:25:32 UTC
  • mfrom: (5011.3.16 no_until_no_eintr)
  • Revision ID: pqm@pqm.ubuntu.com-20100326052532-9c9bbs1f7hmfr1j4
(andrew) Either correctly handle EINTR or don't handle it at all.
        (#496813)

Show diffs side-by-side

added added

removed removed

Lines of Context:
40
40
    rmtree,
41
41
    )
42
42
import signal
 
43
import socket
43
44
import subprocess
44
45
import tempfile
45
46
from tempfile import (
50
51
from bzrlib import (
51
52
    cache_utf8,
52
53
    errors,
 
54
    trace,
53
55
    win32utils,
54
 
    trace,
55
56
    )
56
 
 
57
57
""")
58
58
 
 
59
from bzrlib.symbol_versioning import (
 
60
    deprecated_function,
 
61
    deprecated_in,
 
62
    )
 
63
 
59
64
# sha and md5 modules are deprecated in python2.6 but hashlib is available as
60
65
# of 2.5
61
66
if sys.version_info < (2, 5):
1957
1962
        return socket.gethostname().decode(get_user_encoding())
1958
1963
 
1959
1964
 
1960
 
def recv_all(socket, bytes):
 
1965
# We must not read/write any more than 64k at a time from/to a socket so we
 
1966
# don't risk "no buffer space available" errors on some platforms.  Windows in
 
1967
# particular is likely to throw WSAECONNABORTED or WSAENOBUFS if given too much
 
1968
# data at once.
 
1969
MAX_SOCKET_CHUNK = 64 * 1024
 
1970
 
 
1971
def read_bytes_from_socket(sock, report_activity=None,
 
1972
        max_read_size=MAX_SOCKET_CHUNK):
 
1973
    """Read up to max_read_size of bytes from sock and notify of progress.
 
1974
 
 
1975
    Translates "Connection reset by peer" into file-like EOF (return an
 
1976
    empty string rather than raise an error), and repeats the recv if
 
1977
    interrupted by a signal.
 
1978
    """
 
1979
    while 1:
 
1980
        try:
 
1981
            bytes = sock.recv(max_read_size)
 
1982
        except socket.error, e:
 
1983
            eno = e.args[0]
 
1984
            if eno == getattr(errno, "WSAECONNRESET", errno.ECONNRESET):
 
1985
                # The connection was closed by the other side.  Callers expect
 
1986
                # an empty string to signal end-of-stream.
 
1987
                return ""
 
1988
            elif eno == errno.EINTR:
 
1989
                # Retry the interrupted recv.
 
1990
                continue
 
1991
            raise
 
1992
        else:
 
1993
            if report_activity is not None:
 
1994
                report_activity(len(bytes), 'read')
 
1995
            return bytes
 
1996
 
 
1997
 
 
1998
def recv_all(socket, count):
1961
1999
    """Receive an exact number of bytes.
1962
2000
 
1963
2001
    Regular Socket.recv() may return less than the requested number of bytes,
1964
 
    dependning on what's in the OS buffer.  MSG_WAITALL is not available
 
2002
    depending on what's in the OS buffer.  MSG_WAITALL is not available
1965
2003
    on all platforms, but this should work everywhere.  This will return
1966
2004
    less than the requested amount if the remote end closes.
1967
2005
 
1968
2006
    This isn't optimized and is intended mostly for use in testing.
1969
2007
    """
1970
2008
    b = ''
1971
 
    while len(b) < bytes:
1972
 
        new = until_no_eintr(socket.recv, bytes - len(b))
 
2009
    while len(b) < count:
 
2010
        new = read_bytes_from_socket(socket, None, count - len(b))
1973
2011
        if new == '':
1974
2012
            break # eof
1975
2013
        b += new
1976
2014
    return b
1977
2015
 
1978
2016
 
1979
 
def send_all(socket, bytes, report_activity=None):
 
2017
def send_all(sock, bytes, report_activity=None):
1980
2018
    """Send all bytes on a socket.
1981
 
 
1982
 
    Regular socket.sendall() can give socket error 10053 on Windows.  This
1983
 
    implementation sends no more than 64k at a time, which avoids this problem.
1984
 
 
 
2019
 
 
2020
    Breaks large blocks in smaller chunks to avoid buffering limitations on
 
2021
    some platforms, and catches EINTR which may be thrown if the send is
 
2022
    interrupted by a signal.
 
2023
 
 
2024
    This is preferred to socket.sendall(), because it avoids portability bugs
 
2025
    and provides activity reporting.
 
2026
 
1985
2027
    :param report_activity: Call this as bytes are read, see
1986
2028
        Transport._report_activity
1987
2029
    """
1988
 
    chunk_size = 2**16
1989
 
    for pos in xrange(0, len(bytes), chunk_size):
1990
 
        block = bytes[pos:pos+chunk_size]
1991
 
        if report_activity is not None:
1992
 
            report_activity(len(block), 'write')
1993
 
        until_no_eintr(socket.sendall, block)
 
2030
    sent_total = 0
 
2031
    byte_count = len(bytes)
 
2032
    while sent_total < byte_count:
 
2033
        try:
 
2034
            sent = sock.send(buffer(bytes, sent_total, MAX_SOCKET_CHUNK))
 
2035
        except socket.error, e:
 
2036
            if e.args[0] != errno.EINTR:
 
2037
                raise
 
2038
        else:
 
2039
            sent_total += sent
 
2040
            report_activity(sent, 'write')
1994
2041
 
1995
2042
 
1996
2043
def dereference_path(path):
2067
2114
 
2068
2115
 
2069
2116
def until_no_eintr(f, *a, **kw):
2070
 
    """Run f(*a, **kw), retrying if an EINTR error occurs."""
 
2117
    """Run f(*a, **kw), retrying if an EINTR error occurs.
 
2118
    
 
2119
    WARNING: you must be certain that it is safe to retry the call repeatedly
 
2120
    if EINTR does occur.  This is typically only true for low-level operations
 
2121
    like os.read.  If in any doubt, don't use this.
 
2122
 
 
2123
    Keep in mind that this is not a complete solution to EINTR.  There is
 
2124
    probably code in the Python standard library and other dependencies that
 
2125
    may encounter EINTR if a signal arrives (and there is signal handler for
 
2126
    that signal).  So this function can reduce the impact for IO that bzrlib
 
2127
    directly controls, but it is not a complete solution.
 
2128
    """
2071
2129
    # Borrowed from Twisted's twisted.python.util.untilConcludes function.
2072
2130
    while True:
2073
2131
        try:
2077
2135
                continue
2078
2136
            raise
2079
2137
 
 
2138
 
2080
2139
def re_compile_checked(re_string, flags=0, where=""):
2081
2140
    """Return a compiled re, or raise a sensible error.
2082
2141