Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit e43f9d0

Browse files
committed
Issue #8524: Add a forget() method to socket objects, so as to put the
socket into the closed state without closing the underlying file descriptor.
1 parent ba8a986 commit e43f9d0

6 files changed

Lines changed: 50 additions & 3 deletions

File tree

Doc/library/socket.rst

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -548,6 +548,14 @@ correspond to Unix system calls applicable to sockets.
548548
this limitation.
549549

550550

551+
.. method:: socket.forget()
552+
553+
Put the socket object into closed state without actually closing the
554+
underlying file descriptor. This allows the latter to be reused.
555+
556+
.. versionadded:: 3.2
557+
558+
551559
.. method:: socket.getpeername()
552560

553561
Return the remote address to which the socket is connected. This is useful to

Doc/whatsnew/3.2.rst

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,12 @@ New, Improved, and Deprecated Modules
136136

137137
(Contributed by Tarek Ziadé.)
138138

139+
* Socket objects now have a :meth:`~socket.socket.forget()` method which
140+
puts the socket into closed state without actually closing the underlying
141+
file descriptor. The latter can then be reused for other purposes.
142+
143+
(Added by Antoine Pitrou; :issue:`8524`.)
144+
139145
* The *sqlite3* module has some new features:
140146

141147
* XXX *enable_load_extension*

Lib/ssl.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,6 @@
7979

8080
from socket import getnameinfo as _getnameinfo
8181
from socket import error as socket_error
82-
from socket import dup as _dup
8382
from socket import socket, AF_INET, SOCK_STREAM
8483
import base64 # for DER-to-PEM translation
8584
import traceback
@@ -148,7 +147,7 @@ def __init__(self, sock=None, keyfile=None, certfile=None,
148147
family=sock.family,
149148
type=sock.type,
150149
proto=sock.proto,
151-
fileno=_dup(sock.fileno()))
150+
fileno=sock.fileno())
152151
self.settimeout(sock.gettimeout())
153152
# see if it's connected
154153
try:
@@ -158,7 +157,7 @@ def __init__(self, sock=None, keyfile=None, certfile=None,
158157
raise
159158
else:
160159
connected = True
161-
sock.close()
160+
sock.forget()
162161
elif fileno is not None:
163162
socket.__init__(self, fileno=fileno)
164163
else:

Lib/test/test_socket.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -655,6 +655,19 @@ def _testShutdown(self):
655655
self.serv_conn.send(MSG)
656656
self.serv_conn.shutdown(2)
657657

658+
def testForget(self):
659+
# Testing forget()
660+
f = self.cli_conn.fileno()
661+
self.cli_conn.forget()
662+
self.assertRaises(socket.error, self.cli_conn.recv, 1024)
663+
self.cli_conn.close()
664+
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM, fileno=f)
665+
msg = sock.recv(1024)
666+
self.assertEqual(msg, MSG)
667+
668+
def _testForget(self):
669+
self.serv_conn.send(MSG)
670+
658671
@unittest.skipUnless(thread, 'Threading required for this test.')
659672
class BasicUDPTest(ThreadedUDPSocketTest):
660673

Misc/NEWS

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,10 @@ Core and Builtins
3030
Extensions
3131
----------
3232

33+
- Issue #8524: Add a forget() method to socket objects, so as to put the
34+
socket into the closed state without closing the underlying file
35+
descriptor.
36+
3337
- Issue #477863: Print a warning at shutdown if gc.garbage is not empty.
3438

3539
- Issue #6869: Fix a refcount problem in the _ctypes extension.

Modules/socketmodule.c

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1869,6 +1869,21 @@ PyDoc_STRVAR(close_doc,
18691869
\n\
18701870
Close the socket. It cannot be used after this call.");
18711871

1872+
static PyObject *
1873+
sock_forget(PySocketSockObject *s)
1874+
{
1875+
s->sock_fd = -1;
1876+
Py_INCREF(Py_None);
1877+
return Py_None;
1878+
}
1879+
1880+
PyDoc_STRVAR(forget_doc,
1881+
"forget()\n\
1882+
\n\
1883+
Close the socket object without closing the underlying file descriptor.\
1884+
The object cannot be used after this call, but the file descriptor\
1885+
can be reused for other purposes.");
1886+
18721887
static int
18731888
internal_connect(PySocketSockObject *s, struct sockaddr *addr, int addrlen,
18741889
int *timeoutp)
@@ -2759,6 +2774,8 @@ static PyMethodDef sock_methods[] = {
27592774
connect_ex_doc},
27602775
{"fileno", (PyCFunction)sock_fileno, METH_NOARGS,
27612776
fileno_doc},
2777+
{"forget", (PyCFunction)sock_forget, METH_NOARGS,
2778+
forget_doc},
27622779
#ifdef HAVE_GETPEERNAME
27632780
{"getpeername", (PyCFunction)sock_getpeername,
27642781
METH_NOARGS, getpeername_doc},

0 commit comments

Comments
 (0)