Skip to content

Commit 1aa2c0f

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 c26afcc commit 1aa2c0f

24 files changed

Lines changed: 264 additions & 176 deletions

Lib/aifc.py

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -357,10 +357,13 @@ def rewind(self):
357357
self._soundpos = 0
358358

359359
def close(self):
360-
if self._decomp:
361-
self._decomp.CloseDecompressor()
362-
self._decomp = None
363-
self._file.close()
360+
decomp = self._decomp
361+
try:
362+
if decomp:
363+
self._decomp = None
364+
decomp.CloseDecompressor()
365+
finally:
366+
self._file.close()
364367

365368
def tell(self):
366369
return self._soundpos

Lib/binhex.py

Lines changed: 27 additions & 17 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
@@ -235,17 +236,22 @@ def write_rsrc(self, data):
235236
self._write(data)
236237

237238
def close(self):
238-
if self.state < _DID_DATA:
239-
self.close_data()
240-
if self.state != _DID_DATA:
241-
raise Error, 'Close at the wrong time'
242-
if self.rlen != 0:
243-
raise Error, \
244-
"Incorrect resource-datasize, diff=%r" % (self.rlen,)
245-
self._writecrc()
246-
self.ofp.close()
247-
self.state = None
248-
del self.ofp
239+
if self.state is None:
240+
return
241+
try:
242+
if self.state < _DID_DATA:
243+
self.close_data()
244+
if self.state != _DID_DATA:
245+
raise Error, 'Close at the wrong time'
246+
if self.rlen != 0:
247+
raise Error, \
248+
"Incorrect resource-datasize, diff=%r" % (self.rlen,)
249+
self._writecrc()
250+
finally:
251+
self.state = None
252+
ofp = self.ofp
253+
del self.ofp
254+
ofp.close()
249255

250256
def binhex(inp, out):
251257
"""(infilename, outfilename) - Create binhex-encoded copy of a file"""
@@ -463,11 +469,15 @@ def read_rsrc(self, *n):
463469
return self._read(n)
464470

465471
def close(self):
466-
if self.rlen:
467-
dummy = self.read_rsrc(self.rlen)
468-
self._checkcrc()
469-
self.state = _DID_RSRC
470-
self.ifp.close()
472+
if self.state is None:
473+
return
474+
try:
475+
if self.rlen:
476+
dummy = self.read_rsrc(self.rlen)
477+
self._checkcrc()
478+
finally:
479+
self.state = None
480+
self.ifp.close()
471481

472482
def hexbin(inp, out):
473483
"""(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/distutils/text_file.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -124,11 +124,11 @@ def open (self, filename):
124124
def close (self):
125125
"""Close the current file and forget everything we know about it
126126
(filename, current line number)."""
127-
128-
self.file.close ()
127+
file = self.file
129128
self.file = None
130129
self.filename = None
131130
self.current_line = None
131+
file.close()
132132

133133

134134
def gen_error (self, msg, line=None):

Lib/dumbdbm.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -209,8 +209,10 @@ def __len__(self):
209209
return len(self._index)
210210

211211
def close(self):
212-
self._commit()
213-
self._index = self._datfile = self._dirfile = self._bakfile = None
212+
try:
213+
self._commit()
214+
finally:
215+
self._index = self._datfile = self._dirfile = self._bakfile = None
214216

215217
__del__ = close
216218

Lib/fileinput.py

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

235235
def close(self):
236-
self.nextfile()
237-
self._files = ()
236+
try:
237+
self.nextfile()
238+
finally:
239+
self._files = ()
238240

239241
def __iter__(self):
240242
return self
@@ -270,23 +272,25 @@ def nextfile(self):
270272

271273
output = self._output
272274
self._output = 0
273-
if output:
274-
output.close()
275-
276-
file = self._file
277-
self._file = 0
278-
if file and not self._isstdin:
279-
file.close()
280-
281-
backupfilename = self._backupfilename
282-
self._backupfilename = 0
283-
if backupfilename and not self._backup:
284-
try: os.unlink(backupfilename)
285-
except OSError: pass
286-
287-
self._isstdin = False
288-
self._buffer = []
289-
self._bufindex = 0
275+
try:
276+
if output:
277+
output.close()
278+
finally:
279+
file = self._file
280+
self._file = 0
281+
try:
282+
if file and not self._isstdin:
283+
file.close()
284+
finally:
285+
backupfilename = self._backupfilename
286+
self._backupfilename = 0
287+
if backupfilename and not self._backup:
288+
try: os.unlink(backupfilename)
289+
except OSError: pass
290+
291+
self._isstdin = False
292+
self._buffer = []
293+
self._bufindex = 0
290294

291295
def readline(self):
292296
try:

Lib/ftplib.py

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

595595
def close(self):
596596
'''Close the connection without assuming anything about it.'''
597-
if self.file is not None:
598-
self.file.close()
599-
if self.sock is not None:
600-
self.sock.close()
601-
self.file = self.sock = None
597+
try:
598+
file = self.file
599+
self.file = None
600+
if file is not None:
601+
file.close()
602+
finally:
603+
sock = self.sock
604+
self.sock = None
605+
if sock is not None:
606+
sock.close()
602607

603608
try:
604609
import ssl

Lib/gzip.py

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

371371
def close(self):
372-
if self.fileobj is None:
372+
fileobj = self.fileobj
373+
if fileobj is None:
373374
return
374-
if self.mode == WRITE:
375-
self.fileobj.write(self.compress.flush())
376-
write32u(self.fileobj, self.crc)
377-
# self.size may exceed 2GB, or even 4GB
378-
write32u(self.fileobj, self.size & 0xffffffffL)
379-
self.fileobj = None
380-
elif self.mode == READ:
381-
self.fileobj = None
382-
if self.myfileobj:
383-
self.myfileobj.close()
384-
self.myfileobj = None
375+
self.fileobj = None
376+
try:
377+
if self.mode == WRITE:
378+
fileobj.write(self.compress.flush())
379+
write32u(fileobj, self.crc)
380+
# self.size may exceed 2GB, or even 4GB
381+
write32u(fileobj, self.size & 0xffffffffL)
382+
finally:
383+
myfileobj = self.myfileobj
384+
if myfileobj:
385+
self.myfileobj = None
386+
myfileobj.close()
385387

386388
def flush(self,zlib_mode=zlib.Z_SYNC_FLUSH):
387389
self._check_closed()

Lib/httplib.py

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -560,9 +560,10 @@ def _check_close(self):
560560
return True
561561

562562
def close(self):
563-
if self.fp:
564-
self.fp.close()
563+
fp = self.fp
564+
if fp:
565565
self.fp = None
566+
fp.close()
566567

567568
def isclosed(self):
568569
# NOTE: it is possible that we will not ever call self.close(). This
@@ -835,13 +836,17 @@ def connect(self):
835836

836837
def close(self):
837838
"""Close the connection to the HTTP server."""
838-
if self.sock:
839-
self.sock.close() # close it manually... there may be other refs
840-
self.sock = None
841-
if self.__response:
842-
self.__response.close()
843-
self.__response = None
844839
self.__state = _CS_IDLE
840+
try:
841+
sock = self.sock
842+
if sock:
843+
self.sock = None
844+
sock.close() # close it manually... there may be other refs
845+
finally:
846+
response = self.__response
847+
if response:
848+
self.__response = None
849+
response.close()
845850

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

Lib/logging/__init__.py

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -916,14 +916,19 @@ def close(self):
916916
"""
917917
self.acquire()
918918
try:
919-
if self.stream:
920-
self.flush()
921-
if hasattr(self.stream, "close"):
922-
self.stream.close()
923-
self.stream = None
924-
# Issue #19523: call unconditionally to
925-
# prevent a handler leak when delay is set
926-
StreamHandler.close(self)
919+
try:
920+
if self.stream:
921+
try:
922+
self.flush()
923+
finally:
924+
stream = self.stream
925+
self.stream = None
926+
if hasattr(stream, "close"):
927+
stream.close()
928+
finally:
929+
# Issue #19523: call unconditionally to
930+
# prevent a handler leak when delay is set
931+
StreamHandler.close(self)
927932
finally:
928933
self.release()
929934

0 commit comments

Comments
 (0)