diff options
author | Guido van Rossum <guido@python.org> | 2007-11-14 22:32:02 (GMT) |
---|---|---|
committer | Guido van Rossum <guido@python.org> | 2007-11-14 22:32:02 (GMT) |
commit | 86bc33cb7c248ede88ff9bd82775aab818f6224f (patch) | |
tree | 14046a25a34813eead8d92c8e46d712229307dac /Lib | |
parent | e69a08ea933e69262b08dc18bb3565892de0ad9b (diff) | |
download | cpython-86bc33cb7c248ede88ff9bd82775aab818f6224f.zip cpython-86bc33cb7c248ede88ff9bd82775aab818f6224f.tar.gz cpython-86bc33cb7c248ede88ff9bd82775aab818f6224f.tar.bz2 |
Patch 1439 by Bill Janssen. I think this will work.
Tested on Windows by Christian Heimes.
I changed the code slightly, renaming decref_socketios() to
_decref_socketios(), and moving it closer to the close() method
that it calls. Hopefully Bill can now submit his SSL port to 3.0.
Diffstat (limited to 'Lib')
-rw-r--r-- | Lib/socket.py | 106 |
1 files changed, 21 insertions, 85 deletions
diff --git a/Lib/socket.py b/Lib/socket.py index ba1b4ee..6a9a381 100644 --- a/Lib/socket.py +++ b/Lib/socket.py @@ -21,7 +21,6 @@ ntohs(), ntohl() -- convert 16, 32 bit int from network to host byte order htons(), htonl() -- convert 16, 32 bit int from host to network byte order inet_aton() -- convert IP addr string (123.45.67.89) to 32-bit packed format inet_ntoa() -- convert 32-bit packed format IP to string (123.45.67.89) -ssl() -- secure socket layer support (only available if configured) socket.getdefaulttimeout() -- get the default timeout value socket.setdefaulttimeout() -- set the default timeout value create_connection() -- connects to an address, with an optional timeout @@ -46,36 +45,6 @@ the setsockopt() and getsockopt() methods. import _socket from _socket import * -try: - import _ssl - import ssl as _realssl -except ImportError: - # no SSL support - pass -else: - def ssl(sock, keyfile=None, certfile=None): - # we do an internal import here because the ssl - # module imports the socket module - warnings.warn("socket.ssl() is deprecated. Use ssl.wrap_socket() instead.", - DeprecationWarning, stacklevel=2) - return _realssl.sslwrap_simple(sock, keyfile, certfile) - - # we need to import the same constants we used to... - from _ssl import SSLError as sslerror - from _ssl import \ - RAND_add, \ - RAND_egd, \ - RAND_status, \ - SSL_ERROR_ZERO_RETURN, \ - SSL_ERROR_WANT_READ, \ - SSL_ERROR_WANT_WRITE, \ - SSL_ERROR_WANT_X509_LOOKUP, \ - SSL_ERROR_SYSCALL, \ - SSL_ERROR_SSL, \ - SSL_ERROR_WANT_CONNECT, \ - SSL_ERROR_EOF, \ - SSL_ERROR_INVALID_ERROR_CODE - import os, sys, io try: @@ -119,49 +88,11 @@ if _can_dup_socket: nfd = os.dup(fd) return socket(family, type, proto, fileno=nfd) -class SocketCloser: - - """Helper to manage socket close() logic for makefile(). - - The OS socket should not be closed until the socket and all - of its makefile-children are closed. If the refcount is zero - when socket.close() is called, this is easy: Just close the - socket. If the refcount is non-zero when socket.close() is - called, then the real close should not occur until the last - makefile-child is closed. - """ - - def __init__(self, sock): - self._sock = sock - self._makefile_refs = 0 - # Test whether the socket is open. - try: - sock.fileno() - self._socket_open = True - except error: - self._socket_open = False - - def socket_close(self): - self._socket_open = False - self.close() - - def makefile_open(self): - self._makefile_refs += 1 - - def makefile_close(self): - self._makefile_refs -= 1 - self.close() - - def close(self): - if not (self._socket_open or self._makefile_refs): - self._sock._real_close() - - class socket(_socket.socket): """A subclass of _socket.socket adding the makefile() method.""" - __slots__ = ["__weakref__", "_closer"] + __slots__ = ["__weakref__", "_io_refs", "_closed"] if not _can_dup_socket: __slots__.append("_base") @@ -170,16 +101,17 @@ class socket(_socket.socket): _socket.socket.__init__(self, family, type, proto) else: _socket.socket.__init__(self, family, type, proto, fileno) - # Defer creating a SocketCloser until makefile() is actually called. - self._closer = None + self._io_refs = 0 + self._closed = False def __repr__(self): """Wrap __repr__() to reveal the real class name.""" s = _socket.socket.__repr__(self) if s.startswith("<socket object"): - s = "<%s.%s%s" % (self.__class__.__module__, - self.__class__.__name__, - s[7:]) + s = "<%s.%s%s%s" % (self.__class__.__module__, + self.__class__.__name__, + (self._closed and " [closed] ") or "", + s[7:]) return s def accept(self): @@ -216,9 +148,8 @@ class socket(_socket.socket): rawmode += "r" if writing: rawmode += "w" - if self._closer is None: - self._closer = SocketCloser(self) - raw = SocketIO(self, rawmode, self._closer) + raw = SocketIO(self, rawmode) + self._io_refs += 1 if buffering is None: buffering = -1 if buffering < 0: @@ -245,11 +176,16 @@ class socket(_socket.socket): text.mode = mode return text + def _decref_socketios(self): + if self._io_refs > 0: + self._io_refs -= 1 + if self._closed: + self.close() + def close(self): - if self._closer is None: + self._closed = True + if self._io_refs < 1: self._real_close() - else: - self._closer.socket_close() # _real_close calls close on the _socket.socket base class. @@ -275,16 +211,14 @@ class SocketIO(io.RawIOBase): # XXX More docs - def __init__(self, sock, mode, closer): + def __init__(self, sock, mode): if mode not in ("r", "w", "rw"): raise ValueError("invalid mode: %r" % mode) io.RawIOBase.__init__(self) self._sock = sock self._mode = mode - self._closer = closer self._reading = "r" in mode self._writing = "w" in mode - closer.makefile_open() def readinto(self, b): self._checkClosed() @@ -308,9 +242,11 @@ class SocketIO(io.RawIOBase): def close(self): if self.closed: return - self._closer.makefile_close() io.RawIOBase.close(self) + def __del__(self): + self._sock._decref_socketios() + def getfqdn(name=''): """Get fully qualified domain name from name. |