- Issue #3309: Fix bz2.BZFile itererator 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 b8b3c03..c4d9b69 100644
--- a/Lib/test/test_bz2.py
+++ b/Lib/test/test_bz2.py
@@ -112,6 +112,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 2dfa33a..c544739 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -68,6 +68,10 @@
 - Issue #2113: Fix error in subprocess.Popen if the select system call is
   interrupted by a signal.
 
+- Issue #3309: Fix bz2.BZFile itererator to release its internal lock
+  properly when raising an exception due to the bz2file being closed.
+  Prevents a deadlock.
+
 Build
 -----
 
diff --git a/Modules/bz2module.c b/Modules/bz2module.c
index bbabe10..16201bd 100644
--- a/Modules/bz2module.c
+++ b/Modules/bz2module.c
@@ -1451,6 +1451,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;