[3.12] gh-129726: Break gzip.GzipFile reference loop (GH-130055) (#130670)

gh-129726: Break `gzip.GzipFile` reference loop (GH-130055)

A reference loop was resulting in the `fileobj` held by the `GzipFile`
being closed before the `GzipFile`.

The issue started with gh-89550 in 3.12, but was hidden in most cases
until 3.13 when gh-62948 made it more visible.
(cherry picked from commit 7f39137662)

Co-authored-by: Cody Maloney <cmaloney@users.noreply.github.com>
This commit is contained in:
Miss Islington (bot) 2025-02-28 09:28:14 +01:00 committed by GitHub
parent 107e08dfb1
commit 500ea3b0ee
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 28 additions and 5 deletions

View file

@ -3,12 +3,14 @@
import array
import functools
import gc
import io
import os
import struct
import sys
import unittest
from subprocess import PIPE, Popen
from test.support import catch_unraisable_exception
from test.support import import_helper
from test.support import os_helper
from test.support import _4G, bigmemtest, requires_subprocess
@ -836,6 +838,17 @@ class TestGzip(BaseTest):
self.assertEqual(gzip.decompress(data), message * 2)
def test_refloop_unraisable(self):
# Ensure a GzipFile referring to a temporary fileobj deletes cleanly.
# Previously an unraisable exception would occur on close because the
# fileobj would be closed before the GzipFile as the result of a
# reference loop. See issue gh-129726
with catch_unraisable_exception() as cm:
gzip.GzipFile(fileobj=io.BytesIO(), mode="w")
gc.collect()
self.assertIsNone(cm.unraisable)
class TestOpen(BaseTest):
def test_binary_modes(self):
uncompressed = data1 * 50