@@ -1714,6 +1714,48 @@ def inner():
17141714 gc_collect () # For PyPy or other GCs.
17151715 self .assertEqual (wr (), None )
17161716
1717+ @cpython_only
1718+ def test_oserror_refleak_attributes_before_init (self ):
1719+ # gh-150988: no leak when a subclass sets OSError fields before
1720+ # super().__init__(), or when __init__ is called more than once.
1721+ class LeakingOSError (OSError ):
1722+ def __init__ (self , code , message , filename , filename2 ):
1723+ self .strerror = message
1724+ self .filename = filename
1725+ self .filename2 = filename2
1726+ super ().__init__ (code , message , filename , None , filename2 )
1727+
1728+ msg = "some error message"
1729+ filename = "some filename"
1730+ filename2 = "some filename 2"
1731+ refcount_msg = sys .getrefcount (msg )
1732+ refcount_filename = sys .getrefcount (filename )
1733+ refcount_filename2 = sys .getrefcount (filename2 )
1734+
1735+ for _ in range (5 ):
1736+ try :
1737+ raise LeakingOSError (1 , msg , filename , filename2 )
1738+ except OSError :
1739+ pass
1740+
1741+ gc_collect ()
1742+ self .assertEqual (sys .getrefcount (msg ), refcount_msg )
1743+ self .assertEqual (sys .getrefcount (filename ), refcount_filename )
1744+ self .assertEqual (sys .getrefcount (filename2 ), refcount_filename2 )
1745+
1746+ exc = LeakingOSError (1 , msg , filename , filename2 )
1747+ exc .__init__ (2 , msg , filename , filename2 )
1748+ self .assertEqual (exc .errno , 2 )
1749+ self .assertEqual (exc .strerror , msg )
1750+ self .assertEqual (exc .filename , filename )
1751+ self .assertEqual (exc .filename2 , filename2 )
1752+ del exc
1753+
1754+ gc_collect ()
1755+ self .assertEqual (sys .getrefcount (msg ), refcount_msg )
1756+ self .assertEqual (sys .getrefcount (filename ), refcount_filename )
1757+ self .assertEqual (sys .getrefcount (filename2 ), refcount_filename2 )
1758+
17171759 def test_errno_ENOTDIR (self ):
17181760 # Issue #12802: "not a directory" errors are ENOTDIR even on Windows
17191761 with self .assertRaises (OSError ) as cm :
0 commit comments