Backport of r64767 from trunk
Fixes Issue #3309: Fix bz2.BZFile iterator to release its internal lock
properly when raising an exception due to the bz2file being closed.
Prevents a deadlock.
diff --git a/Lib/test/test_bz2.py b/Lib/test/test_bz2.py
index 709850d..554fe86 100644
--- a/Lib/test/test_bz2.py
+++ b/Lib/test/test_bz2.py
@@ -110,6 +110,17 @@
self.assertEqual(list(iter(bz2f)), sio.readlines())
bz2f.close()
+ def testClosedIteratorDeadlock(self):
+ # "Test that iteration on a closed bz2file releases the lock."
+ # http://bugs.python.org/issue3309
+ self.createTempFile()
+ bz2f = BZ2File(self.filename)
+ bz2f.close()
+ self.assertRaises(ValueError, bz2f.next)
+ # This call will deadlock of the above .next call failed to
+ # release the lock.
+ self.assertRaises(ValueError, bz2f.readlines)
+
def testXReadLines(self):
# "Test BZ2File.xreadlines()"
self.createTempFile()
diff --git a/Misc/NEWS b/Misc/NEWS
index 8864aa9..23c2384 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -148,6 +148,10 @@
up in the child process to prevent deadlock and report proper thread counts
if the new process uses the threading module.
+- Issue #3309: Fix bz2.BZFile iterator to release its internal lock
+ properly when raising an exception due to the bz2file being closed.
+ Prevents a deadlock.
+
Extension Modules
-----------------
diff --git a/Modules/bz2module.c b/Modules/bz2module.c
index 9e868c5..73de628 100644
--- a/Modules/bz2module.c
+++ b/Modules/bz2module.c
@@ -1437,6 +1437,7 @@
PyStringObject* ret;
ACQUIRE_LOCK(self);
if (self->mode == MODE_CLOSED) {
+ RELEASE_LOCK(self);
PyErr_SetString(PyExc_ValueError,
"I/O operation on closed file");
return NULL;