diff --git a/Doc/data/python3.14.abi b/Doc/data/python3.14.abi
index 372c35f3713..486c54565c4 100644
--- a/Doc/data/python3.14.abi
+++ b/Doc/data/python3.14.abi
@@ -1232,6 +1232,7 @@
+
@@ -1450,6 +1451,7 @@
+
@@ -1814,7 +1816,7 @@
-
+
@@ -1835,7 +1837,7 @@
-
+
@@ -1850,7 +1852,7 @@
-
+
@@ -1888,7 +1890,7 @@
-
+
@@ -1900,10 +1902,10 @@
-
+
-
+
@@ -1991,11 +1993,11 @@
-
+
-
+
@@ -2007,14 +2009,14 @@
-
+
-
+
@@ -2033,7 +2035,7 @@
-
+
@@ -2061,7 +2063,7 @@
-
+
@@ -2103,7 +2105,7 @@
-
+
@@ -2120,7 +2122,7 @@
-
+
@@ -2148,43 +2150,43 @@
-
-
+
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
@@ -2192,7 +2194,7 @@
-
+
@@ -2277,7 +2279,7 @@
-
+
@@ -2302,7 +2304,7 @@
-
+
@@ -2346,7 +2348,7 @@
-
+
@@ -2630,7 +2632,7 @@
-
+
@@ -3554,7 +3556,7 @@
-
+
@@ -3608,7 +3610,7 @@
-
+
@@ -3634,7 +3636,7 @@
-
+
@@ -3723,7 +3725,7 @@
-
+
@@ -3732,7 +3734,7 @@
-
+
@@ -3815,7 +3817,7 @@
-
+
@@ -3837,12 +3839,12 @@
-
+
-
+
@@ -3859,7 +3861,7 @@
-
+
@@ -3899,7 +3901,7 @@
-
+
@@ -3922,7 +3924,7 @@
-
+
@@ -3959,7 +3961,7 @@
-
+
@@ -4032,52 +4034,52 @@
-
+
-
-
+
+
-
-
+
+
-
+
-
-
+
+
-
+
-
+
-
-
+
+
-
-
-
-
+
+
+
+
-
-
-
+
+
+
-
-
+
+
-
-
+
+
@@ -4096,7 +4098,7 @@
-
+
@@ -4182,7 +4184,7 @@
-
+
@@ -4219,7 +4221,7 @@
-
+
@@ -4283,7 +4285,7 @@
-
+
@@ -4361,7 +4363,7 @@
-
+
@@ -5032,7 +5034,7 @@
-
+
@@ -5076,7 +5078,7 @@
-
+
@@ -5411,35 +5413,35 @@
-
-
+
+
-
-
-
+
+
+
-
-
+
+
-
-
+
+
-
-
-
+
+
+
-
-
-
+
+
+
-
+
@@ -5497,7 +5499,7 @@
-
+
@@ -5696,7 +5698,7 @@
-
+
@@ -5731,7 +5733,7 @@
-
+
@@ -5877,30 +5879,30 @@
-
-
-
-
+
+
+
+
-
-
-
+
+
+
-
-
-
+
+
+
-
-
+
+
-
+
@@ -5975,7 +5977,7 @@
-
+
@@ -5997,7 +5999,7 @@
-
+
@@ -6053,7 +6055,7 @@
-
+
@@ -6698,7 +6700,7 @@
-
+
@@ -6896,7 +6898,7 @@
-
+
@@ -7015,7 +7017,7 @@
-
+
@@ -7134,190 +7136,190 @@
-
-
+
+
-
-
-
+
+
+
-
-
-
-
+
+
+
+
-
-
-
-
-
+
+
+
+
+
-
-
-
+
+
+
-
-
-
-
+
+
+
+
-
-
-
-
-
+
+
+
+
+
-
-
-
-
+
+
+
+
-
-
-
-
-
+
+
+
+
+
-
-
-
-
-
+
+
+
+
+
-
-
-
-
+
+
+
+
-
-
-
-
-
+
+
+
+
+
-
-
+
+
-
-
-
-
+
+
+
+
-
-
-
-
+
+
+
+
-
-
-
-
+
+
+
+
-
-
-
-
+
+
+
+
-
-
-
-
+
+
+
+
-
-
-
-
-
+
+
+
+
+
-
-
-
-
+
+
+
+
-
-
+
+
-
-
-
+
+
+
-
-
-
+
+
+
-
-
-
-
+
+
+
+
-
-
-
+
+
+
-
-
-
-
+
+
+
+
-
-
-
+
+
+
-
-
+
+
-
-
-
+
+
+
-
-
-
+
+
+
-
-
+
+
-
-
+
+
-
-
-
-
-
-
+
+
+
+
+
+
@@ -7326,11 +7328,11 @@
-
+
-
+
@@ -7653,7 +7655,7 @@
-
+
@@ -7742,7 +7744,7 @@
-
+
@@ -7947,7 +7949,7 @@
-
+
@@ -8117,7 +8119,7 @@
-
+
@@ -8227,7 +8229,7 @@
-
+
@@ -8271,7 +8273,7 @@
-
+
@@ -8369,9 +8371,13 @@
-
+
+
+
+
+
@@ -8426,38 +8432,38 @@
-
-
+
+
-
-
+
+
-
-
-
-
+
+
+
+
-
-
+
+
-
-
+
+
-
-
-
-
+
+
+
+
-
-
-
-
+
+
+
+
@@ -8539,7 +8545,7 @@
-
+
@@ -8549,7 +8555,7 @@
-
+
@@ -8562,7 +8568,7 @@
-
+
@@ -8648,7 +8654,7 @@
-
+
@@ -8996,7 +9002,7 @@
-
+
@@ -9024,7 +9030,7 @@
-
+
@@ -9051,7 +9057,7 @@
-
+
@@ -9248,7 +9254,7 @@
-
+
@@ -9265,7 +9271,7 @@
-
+
@@ -9306,11 +9312,11 @@
-
+
-
+
@@ -9569,96 +9575,96 @@
-
-
+
+
-
-
+
+
-
-
+
+
-
-
+
+
-
-
-
+
+
+
-
-
+
+
-
-
+
+
-
-
+
+
-
-
+
+
-
-
-
+
+
+
-
-
+
+
-
-
+
+
-
-
+
+
-
-
-
+
+
+
-
-
-
+
+
+
-
-
+
+
-
-
+
+
-
-
+
+
-
-
+
+
-
-
+
+
-
-
+
+
-
+
@@ -10445,7 +10451,7 @@
-
+
@@ -10509,7 +10515,7 @@
-
+
@@ -10524,7 +10530,7 @@
-
+
@@ -10559,7 +10565,7 @@
-
+
@@ -10614,35 +10620,35 @@
-
-
-
+
+
+
-
-
-
+
+
+
-
-
+
+
-
-
+
+
-
-
-
+
+
+
-
-
+
+
-
+
@@ -10664,7 +10670,7 @@
-
+
@@ -10735,7 +10741,7 @@
-
+
@@ -10747,13 +10753,13 @@
-
-
-
+
+
+
-
+
@@ -10773,7 +10779,7 @@
-
+
@@ -11084,51 +11090,57 @@
-
+
-
-
-
+
+
+
+
+
+
+
+
+
-
-
+
+
-
-
+
+
-
-
-
+
+
+
-
-
-
+
+
+
-
+
-
-
+
+
-
-
-
-
-
+
+
+
+
+
-
+
@@ -11137,7 +11149,7 @@
-
+
@@ -11159,7 +11171,7 @@
-
+
@@ -11306,7 +11318,7 @@
-
+
@@ -11860,7 +11872,7 @@
-
+
@@ -11874,7 +11886,7 @@
-
+
@@ -11934,7 +11946,7 @@
-
+
@@ -13065,7 +13077,7 @@
-
+
@@ -13144,7 +13156,7 @@
-
+
@@ -13219,7 +13231,7 @@
-
+
@@ -14414,7 +14426,7 @@
-
+
@@ -14453,7 +14465,7 @@
-
+
@@ -20846,18 +20858,18 @@
-
+
-
+
-
-
+
+
-
-
+
+
-
+
@@ -20879,446 +20891,455 @@
-
-
-
-
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
+
-
+
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
+
-
+
+
-
+
-
+
-
-
+
+
-
+
-
-
-
-
-
-
+
-
+
-
-
-
-
+
-
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
+
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
+
-
-
+
+
+
+
+
-
+
-
-
-
-
+
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
+
-
+
-
-
-
-
-
-
+
-
+
-
+
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
+
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
-
-
-
-
+
-
+
+
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -21330,385 +21351,385 @@
-
-
+
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
-
+
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
@@ -22174,7 +22195,7 @@
-
+
@@ -22247,64 +22268,64 @@
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
@@ -22449,10 +22470,10 @@
-
+
-
+
@@ -22461,75 +22482,75 @@
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
@@ -24287,7 +24308,7 @@
-
+
@@ -24354,7 +24375,7 @@
-
+
@@ -24405,7 +24426,7 @@
-
+
@@ -24430,7 +24451,7 @@
-
+
@@ -24608,14 +24629,14 @@
-
+
-
+
@@ -24642,7 +24663,7 @@
-
+
@@ -24671,7 +24692,7 @@
-
+
@@ -24684,7 +24705,7 @@
-
+
@@ -24772,7 +24793,7 @@
-
+
@@ -24931,7 +24952,7 @@
-
+
@@ -24977,7 +24998,7 @@
-
+
@@ -25048,7 +25069,7 @@
-
+
@@ -25122,7 +25143,7 @@
-
+
@@ -25166,7 +25187,7 @@
-
+
@@ -25194,19 +25215,19 @@
-
-
+
+
-
+
-
+
-
+
-
+
@@ -25289,15 +25310,15 @@
-
+
-
-
-
-
-
+
+
+
+
+
@@ -25568,230 +25589,230 @@
-
-
+
+
-
-
-
-
+
+
+
+
-
-
+
+
-
-
-
-
+
+
+
+
-
-
-
-
-
-
+
+
+
+
+
+
-
-
+
+
-
-
-
+
+
+
-
-
-
-
+
+
+
+
-
-
-
+
+
+
-
-
-
+
+
+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
-
-
-
-
-
-
+
+
+
+
+
+
-
-
-
-
-
-
+
+
+
+
+
+
-
-
-
-
+
+
+
+
-
-
+
+
-
-
+
+
-
-
-
+
+
+
-
-
-
+
+
+
-
-
-
+
+
+
-
-
-
+
+
+
-
+
-
+
-
+
-
+
-
+
-
-
+
+
-
-
+
+
-
-
-
-
-
-
+
+
+
+
+
+
-
-
-
-
+
+
+
+
-
-
-
+
+
+
-
-
-
+
+
+
-
-
-
-
+
+
+
+
-
-
-
-
+
+
+
+
-
-
-
-
-
+
+
+
+
+
-
-
-
-
+
+
+
+
-
-
-
-
+
+
+
+
-
-
+
+
-
-
+
+
-
-
-
-
-
+
+
+
+
+
-
-
-
+
+
+
-
-
-
-
+
+
+
+
-
-
-
+
+
+
-
+
@@ -25931,7 +25952,7 @@
-
+
@@ -26030,7 +26051,7 @@
-
+
@@ -26646,7 +26667,7 @@
-
+
@@ -26849,7 +26870,7 @@
-
+
@@ -26927,13 +26948,13 @@
-
-
-
+
+
+
-
+
@@ -26993,7 +27014,7 @@
-
+
@@ -27525,7 +27546,7 @@
-
+
@@ -27651,7 +27672,7 @@
-
+
@@ -27762,7 +27783,7 @@
-
+
@@ -27786,7 +27807,7 @@
-
+
@@ -27906,7 +27927,7 @@
-
+
@@ -27933,7 +27954,7 @@
-
+
@@ -27966,7 +27987,7 @@
-
+
@@ -28023,7 +28044,7 @@
-
+
@@ -28081,7 +28102,7 @@
-
+
@@ -28089,7 +28110,7 @@
-
+
@@ -28163,21 +28184,21 @@
-
+
-
+
-
+
-
+
@@ -28186,7 +28207,7 @@
-
+
@@ -28230,7 +28251,7 @@
-
+
@@ -28322,7 +28343,7 @@
-
+
@@ -28376,16 +28397,16 @@
-
+
-
+
-
+
@@ -28409,111 +28430,111 @@
-
+
-
-
+
+
-
-
+
+
-
-
+
+
-
-
+
+
-
-
-
-
+
+
+
+
-
-
-
+
+
+
-
-
+
+
-
-
-
+
+
+
-
-
+
+
-
-
-
+
+
+
-
+
-
+
-
-
-
+
+
+
-
-
-
-
+
+
+
+
-
-
-
-
-
+
+
+
+
+
-
-
-
-
-
+
+
+
+
+
-
-
+
+
-
-
+
+
-
-
+
+
-
-
+
+
-
-
-
+
+
+
-
+
-
+
@@ -28551,24 +28572,24 @@
-
+
-
+
-
+
-
+
-
+
-
+
-
+
@@ -28717,7 +28738,7 @@
-
+
@@ -28743,7 +28764,7 @@
-
+
@@ -28870,123 +28891,123 @@
-
-
-
-
+
+
+
+
-
-
-
-
-
+
+
+
+
+
-
-
+
+
-
+
-
+
-
-
+
+
-
-
-
+
+
+
-
-
-
+
+
+
-
-
-
+
+
+
-
-
-
-
+
+
+
+
-
-
-
-
+
+
+
+
-
-
-
-
-
+
+
+
+
+
-
-
-
+
+
+
-
-
-
-
+
+
+
+
-
-
-
-
+
+
+
+
-
-
-
-
-
+
+
+
+
+
-
-
-
-
+
+
+
+
-
-
+
+
-
-
+
+
-
-
-
+
+
+
-
+
-
-
-
+
+
+
-
+
-
+
@@ -29129,7 +29150,7 @@
-
+
@@ -29150,7 +29171,7 @@
-
+
@@ -29257,7 +29278,7 @@
-
+
@@ -29284,7 +29305,7 @@
-
+
@@ -29438,7 +29459,7 @@
-
+
@@ -29540,7 +29561,7 @@
-
+
@@ -29587,7 +29608,7 @@
-
+
@@ -29596,7 +29617,7 @@
-
+
@@ -29647,7 +29668,7 @@
-
+
@@ -29705,30 +29726,30 @@
-
+
-
+
-
-
+
+
-
-
+
+
-
-
+
+
-
+
@@ -29773,12 +29794,12 @@
-
+
-
+
@@ -29797,7 +29818,7 @@
-
+
@@ -29809,7 +29830,7 @@
-
+
@@ -29894,7 +29915,7 @@
-
+
@@ -29940,15 +29961,12 @@
-
-
-
-
+
-
+
@@ -30099,21 +30117,21 @@
-
+
-
+
-
+
-
+
@@ -30275,7 +30293,7 @@
-
+
@@ -30404,10 +30422,13 @@
-
+
+
+
+
-
+
@@ -30501,21 +30522,21 @@
-
-
-
-
+
+
+
+
-
-
+
+
-
-
+
+
-
+
@@ -30556,7 +30577,7 @@
-
+
@@ -30564,11 +30585,11 @@
-
+
-
+
@@ -30635,7 +30656,7 @@
-
+
@@ -30736,66 +30757,66 @@
-
+
-
-
+
+
-
-
+
+
-
-
-
+
+
+
-
+
-
+
-
+
-
+
-
-
+
+
-
-
-
+
+
+
-
+
-
-
-
-
+
+
+
+
-
-
-
-
-
+
+
+
+
+
-
+
@@ -30984,7 +31005,7 @@
-
+
@@ -31177,7 +31198,7 @@
-
+
@@ -31211,7 +31232,7 @@
-
+
@@ -31372,7 +31393,7 @@
-
+
@@ -31380,10 +31401,10 @@
-
+
-
+
@@ -31559,7 +31580,7 @@
-
+
@@ -31610,35 +31631,35 @@
-
-
-
-
+
+
+
+
-
-
+
+
-
+
-
+
-
-
-
+
+
+
-
-
-
+
+
+
diff --git a/Include/internal/pycore_ceval.h b/Include/internal/pycore_ceval.h
index 89504f6bfbb..4e197c2e29e 100644
--- a/Include/internal/pycore_ceval.h
+++ b/Include/internal/pycore_ceval.h
@@ -105,7 +105,6 @@ extern int _PyPerfTrampoline_SetCallbacks(_PyPerf_Callbacks *);
extern void _PyPerfTrampoline_GetCallbacks(_PyPerf_Callbacks *);
extern int _PyPerfTrampoline_Init(int activate);
extern int _PyPerfTrampoline_Fini(void);
-extern void _PyPerfTrampoline_FreeArenas(void);
extern int _PyIsPerfTrampolineActive(void);
extern PyStatus _PyPerfTrampoline_AfterFork_Child(void);
#ifdef PY_HAVE_PERF_TRAMPOLINE
diff --git a/Include/internal/pycore_interp_structs.h b/Include/internal/pycore_interp_structs.h
index 15885b5f228..c3d9533e90f 100644
--- a/Include/internal/pycore_interp_structs.h
+++ b/Include/internal/pycore_interp_structs.h
@@ -87,6 +87,9 @@ struct _ceval_runtime_state {
struct trampoline_api_st trampoline_api;
FILE *map_file;
Py_ssize_t persist_after_fork;
+ _PyFrameEvalFunction prev_eval_frame;
+ Py_ssize_t trampoline_refcount;
+ int code_watcher_id;
#else
int _not_used;
#endif
diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2025-12-27-23-57-43.gh-issue-143228.m3EF9E.rst b/Misc/NEWS.d/next/Core_and_Builtins/2025-12-27-23-57-43.gh-issue-143228.m3EF9E.rst
new file mode 100644
index 00000000000..893bc29543d
--- /dev/null
+++ b/Misc/NEWS.d/next/Core_and_Builtins/2025-12-27-23-57-43.gh-issue-143228.m3EF9E.rst
@@ -0,0 +1,4 @@
+Fix use-after-free in perf trampoline when toggling profiling while
+threads are running or during interpreter finalization with daemon threads
+active. The fix uses reference counting to ensure trampolines are not freed
+while any code object could still reference them. Pach by Pablo Galindo
diff --git a/Python/perf_trampoline.c b/Python/perf_trampoline.c
index 4690e7b718f..8feb259a63a 100644
--- a/Python/perf_trampoline.c
+++ b/Python/perf_trampoline.c
@@ -204,6 +204,43 @@ enum perf_trampoline_type {
#define perf_map_file _PyRuntime.ceval.perf.map_file
#define persist_after_fork _PyRuntime.ceval.perf.persist_after_fork
#define perf_trampoline_type _PyRuntime.ceval.perf.perf_trampoline_type
+#define prev_eval_frame _PyRuntime.ceval.perf.prev_eval_frame
+#define trampoline_refcount _PyRuntime.ceval.perf.trampoline_refcount
+#define code_watcher_id _PyRuntime.ceval.perf.code_watcher_id
+
+static void free_code_arenas(void);
+
+static void
+perf_trampoline_reset_state(void)
+{
+ free_code_arenas();
+ if (code_watcher_id >= 0) {
+ PyCode_ClearWatcher(code_watcher_id);
+ code_watcher_id = -1;
+ }
+ extra_code_index = -1;
+}
+
+static int
+perf_trampoline_code_watcher(PyCodeEvent event, PyCodeObject *co)
+{
+ if (event != PY_CODE_EVENT_DESTROY) {
+ return 0;
+ }
+ if (extra_code_index == -1) {
+ return 0;
+ }
+ py_trampoline f = NULL;
+ int ret = _PyCode_GetExtra((PyObject *)co, extra_code_index, (void **)&f);
+ if (ret != 0 || f == NULL) {
+ return 0;
+ }
+ trampoline_refcount--;
+ if (trampoline_refcount == 0) {
+ perf_trampoline_reset_state();
+ }
+ return 0;
+}
static void
perf_map_write_entry(void *state, const void *code_addr,
@@ -405,6 +442,7 @@ py_trampoline_evaluator(PyThreadState *ts, _PyInterpreterFrame *frame,
perf_code_arena->code_size, co);
_PyCode_SetExtra((PyObject *)co, extra_code_index,
(void *)new_trampoline);
+ trampoline_refcount++;
f = new_trampoline;
}
assert(f != NULL);
@@ -428,6 +466,7 @@ int PyUnstable_PerfTrampoline_CompileCode(PyCodeObject *co)
}
trampoline_api.write_state(trampoline_api.state, new_trampoline,
perf_code_arena->code_size, co);
+ trampoline_refcount++;
return _PyCode_SetExtra((PyObject *)co, extra_code_index,
(void *)new_trampoline);
}
@@ -482,6 +521,10 @@ _PyPerfTrampoline_Init(int activate)
{
#ifdef PY_HAVE_PERF_TRAMPOLINE
PyThreadState *tstate = _PyThreadState_GET();
+ if (code_watcher_id == 0) {
+ // Initialize to -1 since 0 is a valid watcher ID
+ code_watcher_id = -1;
+ }
if (tstate->interp->eval_frame &&
tstate->interp->eval_frame != py_trampoline_evaluator) {
PyErr_SetString(PyExc_RuntimeError,
@@ -505,6 +548,13 @@ _PyPerfTrampoline_Init(int activate)
if (new_code_arena() < 0) {
return -1;
}
+ code_watcher_id = PyCode_AddWatcher(perf_trampoline_code_watcher);
+ if (code_watcher_id < 0) {
+ PyErr_FormatUnraisable("Failed to register code watcher for perf trampoline");
+ free_code_arenas();
+ return -1;
+ }
+ trampoline_refcount = 1; // Base refcount held by the system
perf_status = PERF_STATUS_OK;
}
#endif
@@ -526,19 +576,21 @@ _PyPerfTrampoline_Fini(void)
trampoline_api.free_state(trampoline_api.state);
perf_trampoline_type = PERF_TRAMPOLINE_UNSET;
}
- extra_code_index = -1;
+
+ // Prevent new trampolines from being created
perf_status = PERF_STATUS_NO_INIT;
+
+ // Decrement base refcount. If refcount reaches 0, all code objects are already
+ // dead so clean up now. Otherwise, watcher remains active to clean up when last
+ // code object dies; extra_code_index stays valid so watcher can identify them.
+ trampoline_refcount--;
+ if (trampoline_refcount == 0) {
+ perf_trampoline_reset_state();
+ }
#endif
return 0;
}
-void _PyPerfTrampoline_FreeArenas(void) {
-#ifdef PY_HAVE_PERF_TRAMPOLINE
- free_code_arenas();
-#endif
- return;
-}
-
int
PyUnstable_PerfTrampoline_SetPersistAfterFork(int enable){
#ifdef PY_HAVE_PERF_TRAMPOLINE
diff --git a/Python/pylifecycle.c b/Python/pylifecycle.c
index fad69f82b60..9ae5e067023 100644
--- a/Python/pylifecycle.c
+++ b/Python/pylifecycle.c
@@ -1923,7 +1923,6 @@ finalize_interp_clear(PyThreadState *tstate)
_PyArg_Fini();
_Py_ClearFileSystemEncoding();
_PyPerfTrampoline_Fini();
- _PyPerfTrampoline_FreeArenas();
}
finalize_interp_types(tstate->interp);