@@ -122,7 +122,7 @@ static traceback_t *tracemalloc_traceback = NULL;
122122 Protected by the GIL */
123123static _Py_hashtable_t * tracemalloc_tracebacks = NULL ;
124124
125- /* pointer (void*) => trace (trace_t).
125+ /* pointer (void*) => trace (trace_t* ).
126126 Protected by TABLES_LOCK(). */
127127static _Py_hashtable_t * tracemalloc_traces = NULL ;
128128
@@ -467,13 +467,23 @@ traceback_new(void)
467467}
468468
469469
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+
470480static _Py_hashtable_t *
471481tracemalloc_create_traces_table (void )
472482{
473- return hashtable_new (sizeof (trace_t ),
483+ return hashtable_new (sizeof (trace_t * ),
474484 _Py_hashtable_hash_ptr ,
475485 _Py_hashtable_compare_direct ,
476- NULL );
486+ tracemalloc_destroy_trace_cb );
477487}
478488
479489
@@ -528,12 +538,13 @@ tracemalloc_remove_trace(unsigned int domain, uintptr_t ptr)
528538 return ;
529539 }
530540
531- trace_t trace ;
541+ trace_t * trace ;
532542 if (!_Py_HASHTABLE_POP (traces , TO_PTR (ptr ), trace )) {
533543 return ;
534544 }
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 );
537548}
538549
539550#define REMOVE_TRACE (ptr ) \
@@ -565,23 +576,27 @@ tracemalloc_add_trace(unsigned int domain, uintptr_t ptr,
565576 }
566577
567578 _Py_hashtable_entry_t * entry = _Py_HASHTABLE_GET_ENTRY (traces , ptr );
568- trace_t trace ;
569579 if (entry != NULL ) {
570580 /* the memory block is already tracked */
581+ trace_t * trace ;
571582 _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 ;
574585
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 ;
578588 }
579589 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 ;
582596
583597 int res = _Py_HASHTABLE_SET (traces , TO_PTR (ptr ), trace );
584598 if (res != 0 ) {
599+ raw_free (trace );
585600 return res ;
586601 }
587602 }
@@ -1225,38 +1240,100 @@ typedef struct {
12251240 unsigned int domain ;
12261241} get_traces_t ;
12271242
1243+
12281244static 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 )
12321248{
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 ;
12341292
12351293 unsigned int domain = (unsigned int )FROM_PTR (entry -> key );
12361294 _Py_hashtable_t * traces ;
12371295 _Py_HASHTABLE_ENTRY_READ_DATA (domains , entry , traces );
12381296
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 ) {
12411299 _Py_hashtable_destroy (traces2 );
12421300 return -1 ;
12431301 }
12441302 return 0 ;
12451303}
12461304
12471305
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+
12481325static int
12491326tracemalloc_get_traces_fill (_Py_hashtable_t * traces , _Py_hashtable_entry_t * entry ,
12501327 void * user_data )
12511328{
12521329 get_traces_t * get_traces = user_data ;
1253- trace_t trace ;
1330+ trace_t * trace ;
12541331 PyObject * tracemalloc_obj ;
12551332 int res ;
12561333
12571334 _Py_HASHTABLE_ENTRY_READ_DATA (traces , entry , trace );
12581335
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 );
12601337 if (tracemalloc_obj == NULL )
12611338 return 1 ;
12621339
@@ -1335,37 +1412,34 @@ _tracemalloc__get_traces_impl(PyObject *module)
13351412 goto no_memory ;
13361413 }
13371414
1338- get_traces .domains = tracemalloc_create_domains_table ();
1339- if (get_traces .domains == NULL ) {
1340- goto no_memory ;
1341- }
1342-
1343- int err ;
1344-
13451415 // Copy all traces so tracemalloc_get_traces_fill() doesn't have to disable
13461416 // temporarily tracemalloc which would impact other threads and so would
13471417 // miss allocations while get_traces() is called.
13481418 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 );
13531420 TABLES_UNLOCK ();
13541421
13551422 if (get_traces .traces == NULL ) {
13561423 goto no_memory ;
13571424 }
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 ) {
13591431 goto no_memory ;
13601432 }
13611433
13621434 // Convert traces to a list of tuples
13631435 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 );
13661439 if (!err ) {
13671440 err = _Py_hashtable_foreach (get_traces .domains ,
1368- tracemalloc_get_traces_domain , & get_traces );
1441+ tracemalloc_get_traces_domain ,
1442+ & get_traces );
13691443 }
13701444 set_reentrant (0 );
13711445 if (err ) {
@@ -1398,7 +1472,7 @@ _tracemalloc__get_traces_impl(PyObject *module)
13981472static traceback_t *
13991473tracemalloc_get_traceback (unsigned int domain , uintptr_t ptr )
14001474{
1401- trace_t trace ;
1475+ trace_t * trace ;
14021476 int found ;
14031477
14041478 if (!_Py_tracemalloc_config .tracing )
@@ -1414,10 +1488,11 @@ tracemalloc_get_traceback(unsigned int domain, uintptr_t ptr)
14141488 }
14151489 TABLES_UNLOCK ();
14161490
1417- if (!found )
1491+ if (!found ) {
14181492 return NULL ;
1493+ }
14191494
1420- return trace . traceback ;
1495+ return trace -> traceback ;
14211496}
14221497
14231498
@@ -1758,10 +1833,9 @@ _PyTraceMalloc_NewReference(PyObject *op)
17581833 /* update the traceback of the memory block */
17591834 traceback_t * traceback = traceback_new ();
17601835 if (traceback != NULL ) {
1761- trace_t trace ;
1836+ trace_t * trace ;
17621837 _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 ;
17651839 res = 0 ;
17661840 }
17671841 }
0 commit comments