FazBrowse GitHub Viewer | Trending |
URL:
| Home
Tools: [Download Repo ZIP]   [Original HTTPS Page]

This is roughly socket2.diff from issue 1378, with a few changes applied · python/cpython@39eb8fa · GitHub

Repository navigation

Commit 39eb8fa

Browse files
committed
This is roughly socket2.diff from issue 1378, with a few changes applied
to ssl.py (no need to test whether we can dup any more). Regular sockets no longer have a _base, but we still have explicit reference counting of socket objects for the benefit of makefile(); using duplicate sockets won't work for SSLSocket.
1 parent dd9e3b8 commit 39eb8fa

5 files changed

Lines changed: 125 additions & 117 deletions

File tree

‎Include/longobject.h‎

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,15 @@ PyAPI_FUNC(size_t) PyLong_AsSize_t(PyObject *);
2626
PyAPI_FUNC(unsigned long) PyLong_AsUnsignedLong(PyObject *);
2727
PyAPI_FUNC(unsigned long) PyLong_AsUnsignedLongMask(PyObject *);
2828

29+
/* Used by socketmodule.c */
30+
#if SIZEOF_SOCKET_T <= SIZEOF_LONG
31+
#define PyLong_FromSocket_t(fd) PyLong_FromLong((SOCKET_T)(fd))
32+
#define PyLong_AsSocket_t(fd) (SOCKET_T)PyLong_AsLong(fd)
33+
#else
34+
#define PyLong_FromSocket_t(fd) PyLong_FromLongLong(((SOCKET_T)(fd));
35+
#define PyLong_AsSocket_t(fd) (SOCKET_T)PyLong_AsLongLong(fd)
36+
#endif
37+
2938
/* For use by intobject.c only */
3039
PyAPI_DATA(int) _PyLong_DigitValue[256];
3140

‎Lib/socket.py‎

Lines changed: 30 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -79,28 +79,14 @@
7979
__all__.append("errorTab")
8080

8181

82-
# True if os.dup() can duplicate socket descriptors.
83-
# (On Windows at least, os.dup only works on files)
84-
_can_dup_socket = hasattr(_socket.socket, "dup")
85-
86-
if _can_dup_socket:
87-
def fromfd(fd, family=AF_INET, type=SOCK_STREAM, proto=0):
88-
nfd = os.dup(fd)
89-
return socket(family, type, proto, fileno=nfd)
90-
9182
class socket(_socket.socket):
9283

9384
"""A subclass of _socket.socket adding the makefile() method."""
9485

9586
__slots__ = ["__weakref__", "_io_refs", "_closed"]
96-
if not _can_dup_socket:
97-
__slots__.append("_base")
9887

9988
def __init__(self, family=AF_INET, type=SOCK_STREAM, proto=0, fileno=None):
100-
if fileno is None:
101-
_socket.socket.__init__(self, family, type, proto)
102-
else:
103-
_socket.socket.__init__(self, family, type, proto, fileno)
89+
_socket.socket.__init__(self, family, type, proto, fileno)
10490
self._io_refs = 0
10591
self._closed = False
10692

@@ -114,23 +100,29 @@ def __repr__(self):
114100
s[7:])
115101
return s
116102

103+
def dup(self):
104+
"""dup() -> socket object
105+
106+
Return a new socket object connected to the same system resource.
107+
"""
108+
fd = dup(self.fileno())
109+
sock = self.__class__(self.family, self.type, self.proto, fileno=fd)
110+
sock.settimeout(self.gettimeout())
111+
return sock
112+
117113
def accept(self):
118-
"""Wrap accept() to give the connection the right type."""
119-
conn, addr = _socket.socket.accept(self)
120-
fd = conn.fileno()
121-
nfd = fd
122-
if _can_dup_socket:
123-
nfd = os.dup(fd)
124-
wrapper = socket(self.family, self.type, self.proto, fileno=nfd)
125-
if fd == nfd:
126-
wrapper._base = conn # Keep the base alive
127-
else:
128-
conn.close()
129-
return wrapper, addr
114+
"""accept() -> (socket object, address info)
115+
116+
Wait for an incoming connection. Return a new socket
117+
representing the connection, and the address of the client.
118+
For IP sockets, the address info is a pair (hostaddr, port).
119+
"""
120+
fd, addr = self._accept()
121+
return socket(self.family, self.type, self.proto, fileno=fd), addr
130122

131123
def makefile(self, mode="r", buffering=None, *,
132124
encoding=None, newline=None):
133-
"""Return an I/O stream connected to the socket.
125+
"""makefile(...) -> an I/O stream connected to the socket
134126
135127
The arguments are as for io.open() after the filename,
136128
except the only mode characters supported are 'r', 'w' and 'b'.
@@ -184,21 +176,18 @@ def _decref_socketios(self):
184176

185177
def close(self):
186178
self._closed = True
187-
if self._io_refs < 1:
188-
self._real_close()
179+
if self._io_refs <= 0:
180+
_socket.socket.close(self)
189181

190-
# _real_close calls close on the _socket.socket base class.
191182

192-
if not _can_dup_socket:
193-
def _real_close(self):
194-
_socket.socket.close(self)
195-
base = getattr(self, "_base", None)
196-
if base is not None:
197-
self._base = None
198-
base.close()
199-
else:
200-
def _real_close(self):
201-
_socket.socket.close(self)
183+
def fromfd(fd, family, type, proto=0):
184+
""" fromfd(fd, family, type[, proto]) -> socket object
185+
186+
Create a socket object from a duplicate of the given file
187+
descriptor. The remaining arguments are the same as for socket().
188+
"""
189+
nfd = dup(fd)
190+
return socket(family, type, proto, nfd)
202191

203192

204193
class SocketIO(io.RawIOBase):

‎Lib/ssl.py‎

Lines changed: 6 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -78,8 +78,8 @@
7878
from socket import socket, AF_INET, SOCK_STREAM, error
7979
from socket import getnameinfo as _getnameinfo
8080
from socket import error as socket_error
81+
from socket import dup as _dup
8182
import base64 # for DER-to-PEM translation
82-
_can_dup_socket = hasattr(socket, "dup")
8383

8484
class SSLSocket(socket):
8585

@@ -99,20 +99,11 @@ def __init__(self, sock=None, keyfile=None, certfile=None,
9999
if sock is not None:
100100
# copied this code from socket.accept()
101101
fd = sock.fileno()
102-
nfd = fd
103-
if _can_dup_socket:
104-
nfd = os.dup(fd)
105-
try:
106-
socket.__init__(self, family=sock.family, type=sock.type,
107-
proto=sock.proto, fileno=nfd)
108-
except:
109-
if nfd != fd:
110-
os.close(nfd)
111-
else:
112-
if fd != nfd:
113-
sock.close()
114-
sock = None
115-
102+
nfd = _dup(fd)
103+
socket.__init__(self, family=sock.family, type=sock.type,
104+
proto=sock.proto, fileno=nfd)
105+
sock.close()
106+
sock = None
116107
elif fileno is not None:
117108
socket.__init__(self, fileno=fileno)
118109
else:

‎Lib/test/test_socket.py‎

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -575,6 +575,15 @@ def testFromFd(self):
575575
def _testFromFd(self):
576576
self.serv_conn.send(MSG)
577577

578+
def testDup(self):
579+
# Testing dup()
580+
sock = self.cli_conn.dup()
581+
msg = sock.recv(1024)
582+
self.assertEqual(msg, MSG)
583+
584+
def _testDup(self):
585+
self.serv_conn.send(MSG)
586+
578587
def testShutdown(self):
579588
# Testing shutdown()
580589
msg = self.cli_conn.recv(1024)

0 commit comments

Comments
 (0)

Back | FazBrowse Home | New Git URL