@@ -122,7 +122,7 @@ static traceback_t *tracemalloc_traceback = NULL;
122
122
Protected by the GIL */
123
123
static _Py_hashtable_t * tracemalloc_tracebacks = NULL ;
124
124
125
- /* pointer (void*) => trace (trace_t).
125
+ /* pointer (void*) => trace (trace_t* ).
126
126
Protected by TABLES_LOCK(). */
127
127
static _Py_hashtable_t * tracemalloc_traces = NULL ;
128
128
@@ -467,13 +467,23 @@ traceback_new(void)
467
467
}
468
468
469
469
470
+ static void
471
+ tracemalloc_destroy_trace_cb (_Py_hashtable_t * traces ,
472
+ _Py_hashtable_entry_t * entry )
473
+ {
474
+ trace_t * trace ;
475
+ _Py_HASHTABLE_ENTRY_READ_DATA (traces , entry , trace );
476
+ raw_free (trace );
477
+ }
478
+
479
+
470
480
static _Py_hashtable_t *
471
481
tracemalloc_create_traces_table (void )
472
482
{
473
- return hashtable_new (sizeof (trace_t ),
483
+ return hashtable_new (sizeof (trace_t * ),
474
484
_Py_hashtable_hash_ptr ,
475
485
_Py_hashtable_compare_direct ,
476
- NULL );
486
+ tracemalloc_destroy_trace_cb );
477
487
}
478
488
479
489
@@ -528,12 +538,13 @@ tracemalloc_remove_trace(unsigned int domain, uintptr_t ptr)
528
538
return ;
529
539
}
530
540
531
- trace_t trace ;
541
+ trace_t * trace ;
532
542
if (!_Py_HASHTABLE_POP (traces , TO_PTR (ptr ), trace )) {
533
543
return ;
534
544
}
535
- assert (tracemalloc_traced_memory >= trace .size );
536
- tracemalloc_traced_memory -= trace .size ;
545
+ assert (tracemalloc_traced_memory >= trace -> size );
546
+ tracemalloc_traced_memory -= trace -> size ;
547
+ raw_free (trace );
537
548
}
538
549
539
550
#define REMOVE_TRACE (ptr ) \
@@ -565,23 +576,27 @@ tracemalloc_add_trace(unsigned int domain, uintptr_t ptr,
565
576
}
566
577
567
578
_Py_hashtable_entry_t * entry = _Py_HASHTABLE_GET_ENTRY (traces , ptr );
568
- trace_t trace ;
569
579
if (entry != NULL ) {
570
580
/* the memory block is already tracked */
581
+ trace_t * trace ;
571
582
_Py_HASHTABLE_ENTRY_READ_DATA (traces , entry , trace );
572
- assert (tracemalloc_traced_memory >= trace . size );
573
- tracemalloc_traced_memory -= trace . size ;
583
+ assert (tracemalloc_traced_memory >= trace -> size );
584
+ tracemalloc_traced_memory -= trace -> size ;
574
585
575
- trace .size = size ;
576
- trace .traceback = traceback ;
577
- _Py_HASHTABLE_ENTRY_WRITE_DATA (traces , entry , trace );
586
+ trace -> size = size ;
587
+ trace -> traceback = traceback ;
578
588
}
579
589
else {
580
- trace .size = size ;
581
- trace .traceback = traceback ;
590
+ trace_t * trace = raw_malloc (sizeof (trace_t ));
591
+ if (trace == NULL ) {
592
+ return -1 ;
593
+ }
594
+ trace -> size = size ;
595
+ trace -> traceback = traceback ;
582
596
583
597
int res = _Py_HASHTABLE_SET (traces , TO_PTR (ptr ), trace );
584
598
if (res != 0 ) {
599
+ raw_free (trace );
585
600
return res ;
586
601
}
587
602
}
@@ -1225,38 +1240,100 @@ typedef struct {
1225
1240
unsigned int domain ;
1226
1241
} get_traces_t ;
1227
1242
1243
+
1228
1244
static int
1229
- tracemalloc_get_traces_copy_domain (_Py_hashtable_t * domains ,
1230
- _Py_hashtable_entry_t * entry ,
1231
- void * user_data )
1245
+ tracemalloc_copy_trace (_Py_hashtable_t * traces ,
1246
+ _Py_hashtable_entry_t * entry ,
1247
+ void * traces2_raw )
1232
1248
{
1233
- get_traces_t * get_traces = user_data ;
1249
+ _Py_hashtable_t * traces2 = (_Py_hashtable_t * )traces2_raw ;
1250
+
1251
+ trace_t * trace ;
1252
+ _Py_HASHTABLE_ENTRY_READ_DATA (traces , entry , trace );
1253
+
1254
+ trace_t * trace2 = raw_malloc (sizeof (trace_t ));
1255
+ if (traces2 == NULL ) {
1256
+ return -1 ;
1257
+ }
1258
+ * trace2 = * trace ;
1259
+ if (_Py_HASHTABLE_SET (traces2 , entry -> key , trace2 ) < 0 ) {
1260
+ raw_free (trace2 );
1261
+ return -1 ;
1262
+ }
1263
+ return 0 ;
1264
+ }
1265
+
1266
+
1267
+ static _Py_hashtable_t *
1268
+ tracemalloc_copy_traces (_Py_hashtable_t * traces )
1269
+ {
1270
+ _Py_hashtable_t * traces2 = tracemalloc_create_traces_table ();
1271
+ if (traces2 == NULL ) {
1272
+ return NULL ;
1273
+ }
1274
+
1275
+ int err = _Py_hashtable_foreach (traces ,
1276
+ tracemalloc_copy_trace ,
1277
+ traces2 );
1278
+ if (err ) {
1279
+ _Py_hashtable_destroy (traces2 );
1280
+ return NULL ;
1281
+ }
1282
+ return traces2 ;
1283
+ }
1284
+
1285
+
1286
+ static int
1287
+ tracemalloc_copy_domain (_Py_hashtable_t * domains ,
1288
+ _Py_hashtable_entry_t * entry ,
1289
+ void * domains2_raw )
1290
+ {
1291
+ _Py_hashtable_t * domains2 = (_Py_hashtable_t * )domains2_raw ;
1234
1292
1235
1293
unsigned int domain = (unsigned int )FROM_PTR (entry -> key );
1236
1294
_Py_hashtable_t * traces ;
1237
1295
_Py_HASHTABLE_ENTRY_READ_DATA (domains , entry , traces );
1238
1296
1239
- _Py_hashtable_t * traces2 = _Py_hashtable_copy (traces );
1240
- if (_Py_HASHTABLE_SET (get_traces -> domains , TO_PTR (domain ), traces2 ) < 0 ) {
1297
+ _Py_hashtable_t * traces2 = tracemalloc_copy_traces (traces );
1298
+ if (_Py_HASHTABLE_SET (domains2 , TO_PTR (domain ), traces2 ) < 0 ) {
1241
1299
_Py_hashtable_destroy (traces2 );
1242
1300
return -1 ;
1243
1301
}
1244
1302
return 0 ;
1245
1303
}
1246
1304
1247
1305
1306
+ static _Py_hashtable_t *
1307
+ tracemalloc_copy_domains (_Py_hashtable_t * domains )
1308
+ {
1309
+ _Py_hashtable_t * domains2 = tracemalloc_create_domains_table ();
1310
+ if (domains2 == NULL ) {
1311
+ return NULL ;
1312
+ }
1313
+
1314
+ int err = _Py_hashtable_foreach (domains ,
1315
+ tracemalloc_copy_domain ,
1316
+ domains2 );
1317
+ if (err ) {
1318
+ _Py_hashtable_destroy (domains2 );
1319
+ return NULL ;
1320
+ }
1321
+ return domains2 ;
1322
+ }
1323
+
1324
+
1248
1325
static int
1249
1326
tracemalloc_get_traces_fill (_Py_hashtable_t * traces , _Py_hashtable_entry_t * entry ,
1250
1327
void * user_data )
1251
1328
{
1252
1329
get_traces_t * get_traces = user_data ;
1253
- trace_t trace ;
1330
+ trace_t * trace ;
1254
1331
PyObject * tracemalloc_obj ;
1255
1332
int res ;
1256
1333
1257
1334
_Py_HASHTABLE_ENTRY_READ_DATA (traces , entry , trace );
1258
1335
1259
- tracemalloc_obj = trace_to_pyobject (get_traces -> domain , & trace , get_traces -> tracebacks );
1336
+ tracemalloc_obj = trace_to_pyobject (get_traces -> domain , trace , get_traces -> tracebacks );
1260
1337
if (tracemalloc_obj == NULL )
1261
1338
return 1 ;
1262
1339
@@ -1335,37 +1412,34 @@ _tracemalloc__get_traces_impl(PyObject *module)
1335
1412
goto no_memory ;
1336
1413
}
1337
1414
1338
- get_traces .domains = tracemalloc_create_domains_table ();
1339
- if (get_traces .domains == NULL ) {
1340
- goto no_memory ;
1341
- }
1342
-
1343
- int err ;
1344
-
1345
1415
// Copy all traces so tracemalloc_get_traces_fill() doesn't have to disable
1346
1416
// temporarily tracemalloc which would impact other threads and so would
1347
1417
// miss allocations while get_traces() is called.
1348
1418
TABLES_LOCK ();
1349
- get_traces .traces = _Py_hashtable_copy (tracemalloc_traces );
1350
- err = _Py_hashtable_foreach (tracemalloc_domains ,
1351
- tracemalloc_get_traces_copy_domain ,
1352
- & get_traces );
1419
+ get_traces .traces = tracemalloc_copy_traces (tracemalloc_traces );
1353
1420
TABLES_UNLOCK ();
1354
1421
1355
1422
if (get_traces .traces == NULL ) {
1356
1423
goto no_memory ;
1357
1424
}
1358
- if (err ) {
1425
+
1426
+ TABLES_LOCK ();
1427
+ get_traces .domains = tracemalloc_copy_domains (tracemalloc_domains );
1428
+ TABLES_UNLOCK ();
1429
+
1430
+ if (get_traces .domains == NULL ) {
1359
1431
goto no_memory ;
1360
1432
}
1361
1433
1362
1434
// Convert traces to a list of tuples
1363
1435
set_reentrant (1 );
1364
- err = _Py_hashtable_foreach (get_traces .traces ,
1365
- tracemalloc_get_traces_fill , & get_traces );
1436
+ int err = _Py_hashtable_foreach (get_traces .traces ,
1437
+ tracemalloc_get_traces_fill ,
1438
+ & get_traces );
1366
1439
if (!err ) {
1367
1440
err = _Py_hashtable_foreach (get_traces .domains ,
1368
- tracemalloc_get_traces_domain , & get_traces );
1441
+ tracemalloc_get_traces_domain ,
1442
+ & get_traces );
1369
1443
}
1370
1444
set_reentrant (0 );
1371
1445
if (err ) {
@@ -1398,7 +1472,7 @@ _tracemalloc__get_traces_impl(PyObject *module)
1398
1472
static traceback_t *
1399
1473
tracemalloc_get_traceback (unsigned int domain , uintptr_t ptr )
1400
1474
{
1401
- trace_t trace ;
1475
+ trace_t * trace ;
1402
1476
int found ;
1403
1477
1404
1478
if (!_Py_tracemalloc_config .tracing )
@@ -1414,10 +1488,11 @@ tracemalloc_get_traceback(unsigned int domain, uintptr_t ptr)
1414
1488
}
1415
1489
TABLES_UNLOCK ();
1416
1490
1417
- if (!found )
1491
+ if (!found ) {
1418
1492
return NULL ;
1493
+ }
1419
1494
1420
- return trace . traceback ;
1495
+ return trace -> traceback ;
1421
1496
}
1422
1497
1423
1498
@@ -1758,10 +1833,9 @@ _PyTraceMalloc_NewReference(PyObject *op)
1758
1833
/* update the traceback of the memory block */
1759
1834
traceback_t * traceback = traceback_new ();
1760
1835
if (traceback != NULL ) {
1761
- trace_t trace ;
1836
+ trace_t * trace ;
1762
1837
_Py_HASHTABLE_ENTRY_READ_DATA (tracemalloc_traces , entry , trace );
1763
- trace .traceback = traceback ;
1764
- _Py_HASHTABLE_ENTRY_WRITE_DATA (tracemalloc_traces , entry , trace );
1838
+ trace -> traceback = traceback ;
1765
1839
res = 0 ;
1766
1840
}
1767
1841
}
0 commit comments