summaryrefslogtreecommitdiff
path: root/Lib
diff options
context:
space:
mode:
authorGregory P. Smith <greg@mad-scientist.com>2009-01-12 04:50:11 +0000
committerGregory P. Smith <greg@mad-scientist.com>2009-01-12 04:50:11 +0000
commitde3369f2ca0e2e1b26482a34fdc09d18a3a928d9 (patch)
tree65d355ce55f2c3d4c4ff507b7d7a5436b7cf82f5 /Lib
parentce36962d12b78ede24b71d5ac1075109f5e23787 (diff)
downloadcpython-git-de3369f2ca0e2e1b26482a34fdc09d18a3a928d9.tar.gz
Fixes issue #3826 and #4791:
Have SocketIO objects update their reference count in the underlying socket object on close() so that the underlying socket object is closed immediately when the last user is done rather than at an unknown later time when garbage collection can do it.
Diffstat (limited to 'Lib')
-rw-r--r--Lib/socket.py8
-rw-r--r--Lib/test/test_socket.py33
2 files changed, 39 insertions, 2 deletions
diff --git a/Lib/socket.py b/Lib/socket.py
index 045987c086..737930d003 100644
--- a/Lib/socket.py
+++ b/Lib/socket.py
@@ -225,11 +225,12 @@ class SocketIO(io.RawIOBase):
return self._writing and not self.closed
def fileno(self):
+ self._checkClosed()
return self._sock.fileno()
@property
def name(self):
- return self._sock.fileno()
+ return self.fileno()
@property
def mode(self):
@@ -239,9 +240,12 @@ class SocketIO(io.RawIOBase):
if self.closed:
return
io.RawIOBase.close(self)
+ self._sock._decref_socketios()
+ self._sock = None
def __del__(self):
- self._sock._decref_socketios()
+ if not self.closed:
+ self._sock._decref_socketios()
def getfqdn(name=''):
diff --git a/Lib/test/test_socket.py b/Lib/test/test_socket.py
index 51f41a9f2e..b0fe057771 100644
--- a/Lib/test/test_socket.py
+++ b/Lib/test/test_socket.py
@@ -856,6 +856,16 @@ class FileObjectClassTestCase(SocketConnectedTest):
self.assertEqual(self.cli_file.mode, 'wb')
self.assertEqual(self.cli_file.name, self.serv_conn.fileno())
+ def testRealClose(self):
+ self.serv_file.close()
+ self.assertRaises(ValueError, self.serv_file.fileno)
+ self.cli_conn.close()
+ self.assertRaises(socket.error, self.cli_conn.getsockname)
+
+ def _testRealClose(self):
+ pass
+
+
class UnbufferedFileObjectClassTestCase(FileObjectClassTestCase):
"""Repeat the tests from FileObjectClassTestCase with bufsize==0.
@@ -881,6 +891,29 @@ class UnbufferedFileObjectClassTestCase(FileObjectClassTestCase):
self.cli_file.write(b"B. " + MSG)
self.cli_file.flush()
+ def testMakefileClose(self):
+ # The file returned by makefile should keep the socket open...
+ self.cli_conn.close()
+ msg = self.cli_conn.recv(1024)
+ self.assertEqual(msg, MSG)
+ # ...until the file is itself closed
+ self.serv_file.close()
+ self.assertRaises(socket.error, self.cli_conn.recv, 1024)
+
+ def _testMakefileClose(self):
+ self.cli_file.write(MSG)
+ self.cli_file.flush()
+
+ def testMakefileCloseSocketDestroy(self):
+ refcount_before = sys.getrefcount(self.cli_conn)
+ self.serv_file.close()
+ refcount_after = sys.getrefcount(self.cli_conn)
+ self.assertEqual(refcount_before - 1, refcount_after)
+
+ def _testMakefileCloseSocketDestroy(self):
+ pass
+
+
class LineBufferedFileObjectClassTestCase(FileObjectClassTestCase):
bufsize = 1 # Default-buffered for reading; line-buffered for writing