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

Skip to content

Commit 7e7a3db

Browse files
Issue #23865: close() methods in multiple modules now are idempotent and more
robust at shutdown. If needs to release multiple resources, they are released even if errors are occured.
1 parent 842f00e commit 7e7a3db

27 files changed

Lines changed: 300 additions & 198 deletions

Lib/aifc.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -356,7 +356,10 @@ def rewind(self):
356356
self._soundpos = 0
357357

358358
def close(self):
359-
self._file.close()
359+
file = self._file
360+
if file is not None:
361+
self._file = None
362+
file.close()
360363

361364
def tell(self):
362365
return self._soundpos

Lib/binhex.py

Lines changed: 26 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,8 @@ class Error(Exception):
3232
pass
3333

3434
# States (what have we written)
35-
[_DID_HEADER, _DID_DATA, _DID_RSRC] = range(3)
35+
_DID_HEADER = 0
36+
_DID_DATA = 1
3637

3738
# Various constants
3839
REASONABLY_LARGE = 32768 # Minimal amount we pass the rle-coder
@@ -213,16 +214,21 @@ def write_rsrc(self, data):
213214
self._write(data)
214215

215216
def close(self):
216-
if self.state < _DID_DATA:
217-
self.close_data()
218-
if self.state != _DID_DATA:
219-
raise Error('Close at the wrong time')
220-
if self.rlen != 0:
221-
raise Error("Incorrect resource-datasize, diff=%r" % (self.rlen,))
222-
self._writecrc()
223-
self.ofp.close()
224-
self.state = None
225-
del self.ofp
217+
if self.state is None:
218+
return
219+
try:
220+
if self.state < _DID_DATA:
221+
self.close_data()
222+
if self.state != _DID_DATA:
223+
raise Error('Close at the wrong time')
224+
if self.rlen != 0:
225+
raise Error("Incorrect resource-datasize, diff=%r" % (self.rlen,))
226+
self._writecrc()
227+
finally:
228+
self.state = None
229+
ofp = self.ofp
230+
del self.ofp
231+
ofp.close()
226232

227233
def binhex(inp, out):
228234
"""binhex(infilename, outfilename): create binhex-encoded copy of a file"""
@@ -436,11 +442,15 @@ def read_rsrc(self, *n):
436442
return self._read(n)
437443

438444
def close(self):
439-
if self.rlen:
440-
dummy = self.read_rsrc(self.rlen)
441-
self._checkcrc()
442-
self.state = _DID_RSRC
443-
self.ifp.close()
445+
if self.state is None:
446+
return
447+
try:
448+
if self.rlen:
449+
dummy = self.read_rsrc(self.rlen)
450+
self._checkcrc()
451+
finally:
452+
self.state = None
453+
self.ifp.close()
444454

445455
def hexbin(inp, out):
446456
"""hexbin(infilename, outfilename) - Decode binhexed file"""

Lib/chunk.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -85,8 +85,10 @@ def getsize(self):
8585

8686
def close(self):
8787
if not self.closed:
88-
self.skip()
89-
self.closed = True
88+
try:
89+
self.skip()
90+
finally:
91+
self.closed = True
9092

9193
def isatty(self):
9294
if self.closed:

Lib/dbm/dumb.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -248,8 +248,10 @@ def __len__(self):
248248
raise error('DBM object has already been closed') from None
249249

250250
def close(self):
251-
self._commit()
252-
self._index = self._datfile = self._dirfile = self._bakfile = None
251+
try:
252+
self._commit()
253+
finally:
254+
self._index = self._datfile = self._dirfile = self._bakfile = None
253255

254256
__del__ = close
255257

Lib/distutils/text_file.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,10 +118,11 @@ def open(self, filename):
118118
def close(self):
119119
"""Close the current file and forget everything we know about it
120120
(filename, current line number)."""
121-
self.file.close()
121+
file = self.file
122122
self.file = None
123123
self.filename = None
124124
self.current_line = None
125+
file.close()
125126

126127
def gen_error(self, msg, line=None):
127128
outmsg = []

Lib/fileinput.py

Lines changed: 23 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -238,8 +238,10 @@ def __del__(self):
238238
self.close()
239239

240240
def close(self):
241-
self.nextfile()
242-
self._files = ()
241+
try:
242+
self.nextfile()
243+
finally:
244+
self._files = ()
243245

244246
def __enter__(self):
245247
return self
@@ -281,23 +283,25 @@ def nextfile(self):
281283

282284
output = self._output
283285
self._output = 0
284-
if output:
285-
output.close()
286-
287-
file = self._file
288-
self._file = 0
289-
if file and not self._isstdin:
290-
file.close()
291-
292-
backupfilename = self._backupfilename
293-
self._backupfilename = 0
294-
if backupfilename and not self._backup:
295-
try: os.unlink(backupfilename)
296-
except OSError: pass
297-
298-
self._isstdin = False
299-
self._buffer = []
300-
self._bufindex = 0
286+
try:
287+
if output:
288+
output.close()
289+
finally:
290+
file = self._file
291+
self._file = 0
292+
try:
293+
if file and not self._isstdin:
294+
file.close()
295+
finally:
296+
backupfilename = self._backupfilename
297+
self._backupfilename = 0
298+
if backupfilename and not self._backup:
299+
try: os.unlink(backupfilename)
300+
except OSError: pass
301+
302+
self._isstdin = False
303+
self._buffer = []
304+
self._bufindex = 0
301305

302306
def readline(self):
303307
try:

Lib/ftplib.py

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -667,11 +667,16 @@ def quit(self):
667667

668668
def close(self):
669669
'''Close the connection without assuming anything about it.'''
670-
if self.file is not None:
671-
self.file.close()
672-
if self.sock is not None:
673-
self.sock.close()
674-
self.file = self.sock = None
670+
try:
671+
file = self.file
672+
self.file = None
673+
if file is not None:
674+
file.close()
675+
finally:
676+
sock = self.sock
677+
self.sock = None
678+
if sock is not None:
679+
sock.close()
675680

676681
try:
677682
import ssl

Lib/gzip.py

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -500,19 +500,21 @@ def closed(self):
500500
return self.fileobj is None
501501

502502
def close(self):
503-
if self.fileobj is None:
503+
fileobj = self.fileobj
504+
if fileobj is None:
504505
return
505-
if self.mode == WRITE:
506-
self.fileobj.write(self.compress.flush())
507-
write32u(self.fileobj, self.crc)
508-
# self.size may exceed 2GB, or even 4GB
509-
write32u(self.fileobj, self.size & 0xffffffff)
510-
self.fileobj = None
511-
elif self.mode == READ:
512-
self.fileobj = None
513-
if self.myfileobj:
514-
self.myfileobj.close()
515-
self.myfileobj = None
506+
self.fileobj = None
507+
try:
508+
if self.mode == WRITE:
509+
fileobj.write(self.compress.flush())
510+
write32u(fileobj, self.crc)
511+
# self.size may exceed 2GB, or even 4GB
512+
write32u(fileobj, self.size & 0xffffffff)
513+
finally:
514+
myfileobj = self.myfileobj
515+
if myfileobj:
516+
self.myfileobj = None
517+
myfileobj.close()
516518

517519
def flush(self,zlib_mode=zlib.Z_SYNC_FLUSH):
518520
self._check_closed()

Lib/http/client.py

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -492,9 +492,11 @@ def _close_conn(self):
492492
fp.close()
493493

494494
def close(self):
495-
super().close() # set "closed" flag
496-
if self.fp:
497-
self._close_conn()
495+
try:
496+
super().close() # set "closed" flag
497+
finally:
498+
if self.fp:
499+
self._close_conn()
498500

499501
# These implementations are for the benefit of io.BufferedReader.
500502

@@ -873,13 +875,17 @@ def connect(self):
873875

874876
def close(self):
875877
"""Close the connection to the HTTP server."""
876-
if self.sock:
877-
self.sock.close() # close it manually... there may be other refs
878-
self.sock = None
879-
if self.__response:
880-
self.__response.close()
881-
self.__response = None
882878
self.__state = _CS_IDLE
879+
try:
880+
sock = self.sock
881+
if sock:
882+
self.sock = None
883+
sock.close() # close it manually... there may be other refs
884+
finally:
885+
response = self.__response
886+
if response:
887+
self.__response = None
888+
response.close()
883889

884890
def send(self, data):
885891
"""Send `data' to the server.

Lib/logging/__init__.py

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1011,14 +1011,19 @@ def close(self):
10111011
"""
10121012
self.acquire()
10131013
try:
1014-
if self.stream:
1015-
self.flush()
1016-
if hasattr(self.stream, "close"):
1017-
self.stream.close()
1018-
self.stream = None
1019-
# Issue #19523: call unconditionally to
1020-
# prevent a handler leak when delay is set
1021-
StreamHandler.close(self)
1014+
try:
1015+
if self.stream:
1016+
try:
1017+
self.flush()
1018+
finally:
1019+
stream = self.stream
1020+
self.stream = None
1021+
if hasattr(stream, "close"):
1022+
stream.close()
1023+
finally:
1024+
# Issue #19523: call unconditionally to
1025+
# prevent a handler leak when delay is set
1026+
StreamHandler.close(self)
10221027
finally:
10231028
self.release()
10241029

0 commit comments

Comments
 (0)