blob: ddf6ef4e11dd4fd3dad5e82856bc1c98174e3ba1 [file] [log] [blame]
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001#include "Python.h"
Victor Stinner40e547d2020-02-05 01:11:10 +01002#include "pycore_pymem.h"
Victor Stinnered488662019-05-20 00:14:57 +02003#include "pycore_traceback.h"
Victor Stinnered3b0bc2013-11-23 12:27:24 +01004#include "hashtable.h"
5#include "frameobject.h"
6#include "pythread.h"
7#include "osdefs.h"
8
Serhiy Storchakab451f912017-02-04 12:18:38 +02009#include "clinic/_tracemalloc.c.h"
10/*[clinic input]
11module _tracemalloc
12[clinic start generated code]*/
13/*[clinic end generated code: output=da39a3ee5e6b4b0d input=708a98302fc46e5f]*/
14
Victor Stinnered3b0bc2013-11-23 12:27:24 +010015/* Trace memory blocks allocated by PyMem_RawMalloc() */
16#define TRACE_RAW_MALLOC
17
18/* Forward declaration */
19static void tracemalloc_stop(void);
Victor Stinnered3b0bc2013-11-23 12:27:24 +010020static void* raw_malloc(size_t size);
21static void raw_free(void *ptr);
22
23#ifdef Py_DEBUG
24# define TRACE_DEBUG
25#endif
26
Victor Stinnered3b0bc2013-11-23 12:27:24 +010027/* Protected by the GIL */
28static struct {
Victor Stinnerd8f0d922014-06-02 21:57:10 +020029 PyMemAllocatorEx mem;
30 PyMemAllocatorEx raw;
31 PyMemAllocatorEx obj;
Victor Stinnered3b0bc2013-11-23 12:27:24 +010032} allocators;
33
Victor Stinnered3b0bc2013-11-23 12:27:24 +010034
Antoine Pitroua6a4dc82017-09-07 18:56:24 +020035#if defined(TRACE_RAW_MALLOC)
Victor Stinnered3b0bc2013-11-23 12:27:24 +010036/* This lock is needed because tracemalloc_free() is called without
37 the GIL held from PyMem_RawFree(). It cannot acquire the lock because it
Joannah Nanjekye2bc43cd2019-09-05 13:06:49 -030038 would introduce a deadlock in _PyThreadState_DeleteCurrent(). */
Victor Stinnered3b0bc2013-11-23 12:27:24 +010039static PyThread_type_lock tables_lock;
40# define TABLES_LOCK() PyThread_acquire_lock(tables_lock, 1)
41# define TABLES_UNLOCK() PyThread_release_lock(tables_lock)
42#else
43 /* variables are protected by the GIL */
44# define TABLES_LOCK()
45# define TABLES_UNLOCK()
46#endif
47
Victor Stinnere492ae52016-03-22 12:58:23 +010048
49#define DEFAULT_DOMAIN 0
50
Victor Stinnere492ae52016-03-22 12:58:23 +010051/* Pack the frame_t structure to reduce the memory footprint. */
52typedef struct
53#ifdef __GNUC__
54__attribute__((packed))
55#endif
56{
Benjamin Petersonca470632016-09-06 13:47:26 -070057 uintptr_t ptr;
Victor Stinner5ea4c062017-06-20 17:46:36 +020058 unsigned int domain;
Victor Stinnere492ae52016-03-22 12:58:23 +010059} pointer_t;
60
Victor Stinnered3b0bc2013-11-23 12:27:24 +010061/* Pack the frame_t structure to reduce the memory footprint on 64-bit
Victor Stinnere492ae52016-03-22 12:58:23 +010062 architectures: 12 bytes instead of 16. */
Victor Stinnered3b0bc2013-11-23 12:27:24 +010063typedef struct
64#ifdef __GNUC__
65__attribute__((packed))
Victor Stinnerdd382ef2014-02-01 03:43:58 +010066#elif defined(_MSC_VER)
Segev Finer39243772017-07-25 11:47:43 +030067#pragma pack(push, 4)
Victor Stinnered3b0bc2013-11-23 12:27:24 +010068#endif
69{
Victor Stinner7105e9f2016-03-15 14:28:04 +010070 /* filename cannot be NULL: "<unknown>" is used if the Python frame
71 filename is NULL */
Victor Stinnered3b0bc2013-11-23 12:27:24 +010072 PyObject *filename;
Victor Stinner95283342016-03-15 21:57:02 +010073 unsigned int lineno;
Victor Stinnered3b0bc2013-11-23 12:27:24 +010074} frame_t;
Segev Finer39243772017-07-25 11:47:43 +030075#ifdef _MSC_VER
76#pragma pack(pop)
77#endif
Victor Stinnered3b0bc2013-11-23 12:27:24 +010078
Victor Stinnere492ae52016-03-22 12:58:23 +010079
Victor Stinnered3b0bc2013-11-23 12:27:24 +010080typedef struct {
81 Py_uhash_t hash;
Julien Danjou8d59eb12019-10-15 14:00:16 +020082 /* Number of frames stored */
83 uint16_t nframe;
84 /* Total number of frames the traceback had */
85 uint16_t total_nframe;
Victor Stinnered3b0bc2013-11-23 12:27:24 +010086 frame_t frames[1];
87} traceback_t;
88
89#define TRACEBACK_SIZE(NFRAME) \
90 (sizeof(traceback_t) + sizeof(frame_t) * (NFRAME - 1))
Victor Stinnerf28ce602013-11-27 22:27:13 +010091
Julien Danjou8d59eb12019-10-15 14:00:16 +020092/* The maximum number of frames is either:
93 - The maximum number of frames we can store in `traceback_t.nframe`
94 - The maximum memory size_t we can allocate */
95static const unsigned long MAX_NFRAME = Py_MIN(UINT16_MAX, ((SIZE_MAX - sizeof(traceback_t)) / sizeof(frame_t) + 1));
Victor Stinnered3b0bc2013-11-23 12:27:24 +010096
Victor Stinnere492ae52016-03-22 12:58:23 +010097
Victor Stinnered3b0bc2013-11-23 12:27:24 +010098static PyObject *unknown_filename = NULL;
99static traceback_t tracemalloc_empty_traceback;
100
Victor Stinner7a5be142013-11-26 01:06:02 +0100101/* Trace of a memory block */
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100102typedef struct {
Victor Stinner7a5be142013-11-26 01:06:02 +0100103 /* Size of the memory block in bytes */
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100104 size_t size;
Victor Stinner7a5be142013-11-26 01:06:02 +0100105
106 /* Traceback where the memory block was allocated */
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100107 traceback_t *traceback;
108} trace_t;
109
Victor Stinnere492ae52016-03-22 12:58:23 +0100110
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100111/* Size in bytes of currently traced memory.
112 Protected by TABLES_LOCK(). */
113static size_t tracemalloc_traced_memory = 0;
114
Victor Stinner3c0481d2013-11-27 21:39:49 +0100115/* Peak size in bytes of traced memory.
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100116 Protected by TABLES_LOCK(). */
Victor Stinner3c0481d2013-11-27 21:39:49 +0100117static size_t tracemalloc_peak_traced_memory = 0;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100118
Serhiy Storchaka56a6d852014-12-01 18:28:43 +0200119/* Hash table used as a set to intern filenames:
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100120 PyObject* => PyObject*.
121 Protected by the GIL */
122static _Py_hashtable_t *tracemalloc_filenames = NULL;
123
Victor Stinnerf28ce602013-11-27 22:27:13 +0100124/* Buffer to store a new traceback in traceback_new().
125 Protected by the GIL. */
126static traceback_t *tracemalloc_traceback = NULL;
127
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100128/* Hash table used as a set to intern tracebacks:
129 traceback_t* => traceback_t*
130 Protected by the GIL */
131static _Py_hashtable_t *tracemalloc_tracebacks = NULL;
132
133/* pointer (void*) => trace (trace_t).
134 Protected by TABLES_LOCK(). */
135static _Py_hashtable_t *tracemalloc_traces = NULL;
136
Victor Stinnere492ae52016-03-22 12:58:23 +0100137
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100138#ifdef TRACE_DEBUG
139static void
140tracemalloc_error(const char *format, ...)
141{
142 va_list ap;
143 fprintf(stderr, "tracemalloc: ");
144 va_start(ap, format);
145 vfprintf(stderr, format, ap);
146 va_end(ap);
147 fprintf(stderr, "\n");
148 fflush(stderr);
149}
150#endif
151
Victor Stinnere492ae52016-03-22 12:58:23 +0100152
Antoine Pitroua6a4dc82017-09-07 18:56:24 +0200153#if defined(TRACE_RAW_MALLOC)
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100154#define REENTRANT_THREADLOCAL
155
Masayuki Yamamoto731e1892017-10-06 19:41:34 +0900156static Py_tss_t tracemalloc_reentrant_key = Py_tss_NEEDS_INIT;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100157
158/* Any non-NULL pointer can be used */
159#define REENTRANT Py_True
160
161static int
162get_reentrant(void)
163{
Victor Stinner4a066472016-03-22 17:45:09 +0100164 void *ptr;
165
Masayuki Yamamoto731e1892017-10-06 19:41:34 +0900166 assert(PyThread_tss_is_created(&tracemalloc_reentrant_key));
167 ptr = PyThread_tss_get(&tracemalloc_reentrant_key);
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100168 if (ptr != NULL) {
169 assert(ptr == REENTRANT);
170 return 1;
171 }
172 else
173 return 0;
174}
175
176static void
177set_reentrant(int reentrant)
178{
Victor Stinner2ead3d22013-11-26 01:08:53 +0100179 assert(reentrant == 0 || reentrant == 1);
Masayuki Yamamoto731e1892017-10-06 19:41:34 +0900180 assert(PyThread_tss_is_created(&tracemalloc_reentrant_key));
Victor Stinner4a066472016-03-22 17:45:09 +0100181
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100182 if (reentrant) {
Victor Stinner0cfc0582016-03-22 17:40:07 +0100183 assert(!get_reentrant());
Masayuki Yamamoto731e1892017-10-06 19:41:34 +0900184 PyThread_tss_set(&tracemalloc_reentrant_key, REENTRANT);
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100185 }
186 else {
Victor Stinner0cfc0582016-03-22 17:40:07 +0100187 assert(get_reentrant());
Masayuki Yamamoto731e1892017-10-06 19:41:34 +0900188 PyThread_tss_set(&tracemalloc_reentrant_key, NULL);
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100189 }
190}
191
192#else
193
Antoine Pitroua6a4dc82017-09-07 18:56:24 +0200194/* TRACE_RAW_MALLOC not defined: variable protected by the GIL */
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100195static int tracemalloc_reentrant = 0;
196
197static int
198get_reentrant(void)
199{
200 return tracemalloc_reentrant;
201}
202
203static void
204set_reentrant(int reentrant)
205{
Victor Stinnerd5871e62016-03-23 00:17:04 +0100206 assert(reentrant != tracemalloc_reentrant);
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100207 tracemalloc_reentrant = reentrant;
208}
209#endif
210
Victor Stinnere492ae52016-03-22 12:58:23 +0100211
Victor Stinner285cf0a2016-03-21 22:00:58 +0100212static Py_uhash_t
Victor Stinner5dacbd42016-03-23 09:52:13 +0100213hashtable_hash_pyobject(_Py_hashtable_t *ht, const void *pkey)
Victor Stinner51b846c2016-03-18 21:52:22 +0100214{
Victor Stinner285cf0a2016-03-21 22:00:58 +0100215 PyObject *obj;
216
Victor Stinner5dacbd42016-03-23 09:52:13 +0100217 _Py_HASHTABLE_READ_KEY(ht, pkey, obj);
Victor Stinner285cf0a2016-03-21 22:00:58 +0100218 return PyObject_Hash(obj);
219}
220
Victor Stinnere492ae52016-03-22 12:58:23 +0100221
Victor Stinner285cf0a2016-03-21 22:00:58 +0100222static int
Victor Stinner5dacbd42016-03-23 09:52:13 +0100223hashtable_compare_unicode(_Py_hashtable_t *ht, const void *pkey,
Victor Stinner285cf0a2016-03-21 22:00:58 +0100224 const _Py_hashtable_entry_t *entry)
225{
Victor Stinnere492ae52016-03-22 12:58:23 +0100226 PyObject *key1, *key2;
Victor Stinner285cf0a2016-03-21 22:00:58 +0100227
Victor Stinner5dacbd42016-03-23 09:52:13 +0100228 _Py_HASHTABLE_READ_KEY(ht, pkey, key1);
229 _Py_HASHTABLE_ENTRY_READ_KEY(ht, entry, key2);
Victor Stinner285cf0a2016-03-21 22:00:58 +0100230
Victor Stinnere492ae52016-03-22 12:58:23 +0100231 if (key1 != NULL && key2 != NULL)
232 return (PyUnicode_Compare(key1, key2) == 0);
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100233 else
Victor Stinnere492ae52016-03-22 12:58:23 +0100234 return key1 == key2;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100235}
236
Victor Stinnere492ae52016-03-22 12:58:23 +0100237
238static Py_uhash_t
Victor Stinner5dacbd42016-03-23 09:52:13 +0100239hashtable_hash_pointer_t(_Py_hashtable_t *ht, const void *pkey)
Victor Stinnere492ae52016-03-22 12:58:23 +0100240{
241 pointer_t ptr;
242 Py_uhash_t hash;
243
Victor Stinner5dacbd42016-03-23 09:52:13 +0100244 _Py_HASHTABLE_READ_KEY(ht, pkey, ptr);
Victor Stinnere492ae52016-03-22 12:58:23 +0100245
246 hash = (Py_uhash_t)_Py_HashPointer((void*)ptr.ptr);
247 hash ^= ptr.domain;
248 return hash;
249}
250
251
doko@ubuntu.combc731502016-05-18 01:06:01 +0200252static int
Victor Stinner5dacbd42016-03-23 09:52:13 +0100253hashtable_compare_pointer_t(_Py_hashtable_t *ht, const void *pkey,
Victor Stinnere492ae52016-03-22 12:58:23 +0100254 const _Py_hashtable_entry_t *entry)
255{
256 pointer_t ptr1, ptr2;
257
Victor Stinner5dacbd42016-03-23 09:52:13 +0100258 _Py_HASHTABLE_READ_KEY(ht, pkey, ptr1);
259 _Py_HASHTABLE_ENTRY_READ_KEY(ht, entry, ptr2);
Victor Stinnere492ae52016-03-22 12:58:23 +0100260
261 /* compare pointer before domain, because pointer is more likely to be
262 different */
263 return (ptr1.ptr == ptr2.ptr && ptr1.domain == ptr2.domain);
264
265}
266
267
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100268static _Py_hashtable_t *
Victor Stinner285cf0a2016-03-21 22:00:58 +0100269hashtable_new(size_t key_size, size_t data_size,
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100270 _Py_hashtable_hash_func hash_func,
271 _Py_hashtable_compare_func compare_func)
272{
Victor Stinnerc9553872016-03-22 12:13:01 +0100273 _Py_hashtable_allocator_t hashtable_alloc = {malloc, free};
Victor Stinner285cf0a2016-03-21 22:00:58 +0100274 return _Py_hashtable_new_full(key_size, data_size, 0,
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100275 hash_func, compare_func,
Victor Stinnerc9553872016-03-22 12:13:01 +0100276 &hashtable_alloc);
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100277}
278
Victor Stinnere492ae52016-03-22 12:58:23 +0100279
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100280static void*
281raw_malloc(size_t size)
282{
283 return allocators.raw.malloc(allocators.raw.ctx, size);
284}
285
286static void
287raw_free(void *ptr)
288{
289 allocators.raw.free(allocators.raw.ctx, ptr);
290}
291
Victor Stinnere492ae52016-03-22 12:58:23 +0100292
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100293static Py_uhash_t
Victor Stinner5dacbd42016-03-23 09:52:13 +0100294hashtable_hash_traceback(_Py_hashtable_t *ht, const void *pkey)
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100295{
Victor Stinnerb32a7ed2016-03-21 23:05:08 +0100296 traceback_t *traceback;
Victor Stinner285cf0a2016-03-21 22:00:58 +0100297
Victor Stinner5dacbd42016-03-23 09:52:13 +0100298 _Py_HASHTABLE_READ_KEY(ht, pkey, traceback);
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100299 return traceback->hash;
300}
301
Victor Stinnere492ae52016-03-22 12:58:23 +0100302
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100303static int
Victor Stinner5dacbd42016-03-23 09:52:13 +0100304hashtable_compare_traceback(_Py_hashtable_t *ht, const void *pkey,
305 const _Py_hashtable_entry_t *entry)
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100306{
Victor Stinner285cf0a2016-03-21 22:00:58 +0100307 traceback_t *traceback1, *traceback2;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100308 const frame_t *frame1, *frame2;
309 int i;
310
Victor Stinner5dacbd42016-03-23 09:52:13 +0100311 _Py_HASHTABLE_READ_KEY(ht, pkey, traceback1);
312 _Py_HASHTABLE_ENTRY_READ_KEY(ht, entry, traceback2);
Victor Stinner285cf0a2016-03-21 22:00:58 +0100313
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100314 if (traceback1->nframe != traceback2->nframe)
315 return 0;
316
Julien Danjou8d59eb12019-10-15 14:00:16 +0200317 if (traceback1->total_nframe != traceback2->total_nframe)
318 return 0;
319
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100320 for (i=0; i < traceback1->nframe; i++) {
321 frame1 = &traceback1->frames[i];
322 frame2 = &traceback2->frames[i];
323
324 if (frame1->lineno != frame2->lineno)
325 return 0;
326
327 if (frame1->filename != frame2->filename) {
328 assert(PyUnicode_Compare(frame1->filename, frame2->filename) != 0);
329 return 0;
330 }
331 }
332 return 1;
333}
334
Victor Stinnere492ae52016-03-22 12:58:23 +0100335
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100336static void
337tracemalloc_get_frame(PyFrameObject *pyframe, frame_t *frame)
338{
339 PyCodeObject *code;
340 PyObject *filename;
341 _Py_hashtable_entry_t *entry;
Victor Stinner95283342016-03-15 21:57:02 +0100342 int lineno;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100343
344 frame->filename = unknown_filename;
Victor Stinner95283342016-03-15 21:57:02 +0100345 lineno = PyFrame_GetLineNumber(pyframe);
346 if (lineno < 0)
347 lineno = 0;
348 frame->lineno = (unsigned int)lineno;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100349
350 code = pyframe->f_code;
351 if (code == NULL) {
352#ifdef TRACE_DEBUG
Victor Stinner4dc74202013-11-26 01:18:52 +0100353 tracemalloc_error("failed to get the code object of the frame");
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100354#endif
355 return;
356 }
357
358 if (code->co_filename == NULL) {
359#ifdef TRACE_DEBUG
360 tracemalloc_error("failed to get the filename of the code object");
361#endif
362 return;
363 }
364
365 filename = code->co_filename;
366 assert(filename != NULL);
367 if (filename == NULL)
368 return;
369
370 if (!PyUnicode_Check(filename)) {
371#ifdef TRACE_DEBUG
Martin Panter6245cb32016-04-15 02:14:19 +0000372 tracemalloc_error("filename is not a unicode string");
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100373#endif
374 return;
375 }
376 if (!PyUnicode_IS_READY(filename)) {
377 /* Don't make a Unicode string ready to avoid reentrant calls
378 to tracemalloc_malloc() or tracemalloc_realloc() */
379#ifdef TRACE_DEBUG
380 tracemalloc_error("filename is not a ready unicode string");
381#endif
382 return;
383 }
384
385 /* intern the filename */
Victor Stinner285cf0a2016-03-21 22:00:58 +0100386 entry = _Py_HASHTABLE_GET_ENTRY(tracemalloc_filenames, filename);
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100387 if (entry != NULL) {
Victor Stinner5dacbd42016-03-23 09:52:13 +0100388 _Py_HASHTABLE_ENTRY_READ_KEY(tracemalloc_filenames, entry, filename);
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100389 }
390 else {
391 /* tracemalloc_filenames is responsible to keep a reference
392 to the filename */
393 Py_INCREF(filename);
Victor Stinner285cf0a2016-03-21 22:00:58 +0100394 if (_Py_HASHTABLE_SET_NODATA(tracemalloc_filenames, filename) < 0) {
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100395 Py_DECREF(filename);
396#ifdef TRACE_DEBUG
397 tracemalloc_error("failed to intern the filename");
398#endif
399 return;
400 }
401 }
402
403 /* the tracemalloc_filenames table keeps a reference to the filename */
404 frame->filename = filename;
405}
406
Victor Stinnere492ae52016-03-22 12:58:23 +0100407
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100408static Py_uhash_t
409traceback_hash(traceback_t *traceback)
410{
411 /* code based on tuplehash() of Objects/tupleobject.c */
Victor Stinner4d8c29c2013-12-16 23:05:13 +0100412 Py_uhash_t x, y; /* Unsigned for defined overflow behavior. */
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100413 int len = traceback->nframe;
414 Py_uhash_t mult = _PyHASH_MULTIPLIER;
415 frame_t *frame;
416
417 x = 0x345678UL;
418 frame = traceback->frames;
419 while (--len >= 0) {
Victor Stinner4d8c29c2013-12-16 23:05:13 +0100420 y = (Py_uhash_t)PyObject_Hash(frame->filename);
421 y ^= (Py_uhash_t)frame->lineno;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100422 frame++;
423
424 x = (x ^ y) * mult;
425 /* the cast might truncate len; that doesn't change hash stability */
Victor Stinner4d8c29c2013-12-16 23:05:13 +0100426 mult += (Py_uhash_t)(82520UL + len + len);
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100427 }
Julien Danjou8d59eb12019-10-15 14:00:16 +0200428 x ^= traceback->total_nframe;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100429 x += 97531UL;
430 return x;
431}
432
Victor Stinnere492ae52016-03-22 12:58:23 +0100433
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100434static void
435traceback_get_frames(traceback_t *traceback)
436{
437 PyThreadState *tstate;
438 PyFrameObject *pyframe;
439
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100440 tstate = PyGILState_GetThisThreadState();
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100441 if (tstate == NULL) {
442#ifdef TRACE_DEBUG
443 tracemalloc_error("failed to get the current thread state");
444#endif
445 return;
446 }
447
448 for (pyframe = tstate->frame; pyframe != NULL; pyframe = pyframe->f_back) {
Julien Danjou8d59eb12019-10-15 14:00:16 +0200449 if (traceback->nframe < _Py_tracemalloc_config.max_nframe) {
450 tracemalloc_get_frame(pyframe, &traceback->frames[traceback->nframe]);
451 assert(traceback->frames[traceback->nframe].filename != NULL);
452 traceback->nframe++;
453 }
454 if (traceback->total_nframe < UINT16_MAX)
455 traceback->total_nframe++;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100456 }
457}
458
Victor Stinnere492ae52016-03-22 12:58:23 +0100459
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100460static traceback_t *
461traceback_new(void)
462{
Victor Stinnerf28ce602013-11-27 22:27:13 +0100463 traceback_t *traceback;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100464 _Py_hashtable_entry_t *entry;
465
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100466 assert(PyGILState_Check());
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100467
468 /* get frames */
Victor Stinnerf28ce602013-11-27 22:27:13 +0100469 traceback = tracemalloc_traceback;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100470 traceback->nframe = 0;
Julien Danjou8d59eb12019-10-15 14:00:16 +0200471 traceback->total_nframe = 0;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100472 traceback_get_frames(traceback);
473 if (traceback->nframe == 0)
474 return &tracemalloc_empty_traceback;
475 traceback->hash = traceback_hash(traceback);
476
477 /* intern the traceback */
Victor Stinner285cf0a2016-03-21 22:00:58 +0100478 entry = _Py_HASHTABLE_GET_ENTRY(tracemalloc_tracebacks, traceback);
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100479 if (entry != NULL) {
Victor Stinner5dacbd42016-03-23 09:52:13 +0100480 _Py_HASHTABLE_ENTRY_READ_KEY(tracemalloc_tracebacks, entry, traceback);
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100481 }
482 else {
483 traceback_t *copy;
484 size_t traceback_size;
485
486 traceback_size = TRACEBACK_SIZE(traceback->nframe);
487
488 copy = raw_malloc(traceback_size);
489 if (copy == NULL) {
490#ifdef TRACE_DEBUG
491 tracemalloc_error("failed to intern the traceback: malloc failed");
492#endif
493 return NULL;
494 }
495 memcpy(copy, traceback, traceback_size);
496
Victor Stinner285cf0a2016-03-21 22:00:58 +0100497 if (_Py_HASHTABLE_SET_NODATA(tracemalloc_tracebacks, copy) < 0) {
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100498 raw_free(copy);
499#ifdef TRACE_DEBUG
500 tracemalloc_error("failed to intern the traceback: putdata failed");
501#endif
502 return NULL;
503 }
504 traceback = copy;
505 }
506 return traceback;
507}
508
Victor Stinnere492ae52016-03-22 12:58:23 +0100509
Victor Stinner5e14a382016-03-23 22:03:55 +0100510static int
511tracemalloc_use_domain_cb(_Py_hashtable_t *old_traces,
512 _Py_hashtable_entry_t *entry, void *user_data)
513{
Benjamin Petersonca470632016-09-06 13:47:26 -0700514 uintptr_t ptr;
Victor Stinner5e14a382016-03-23 22:03:55 +0100515 pointer_t key;
516 _Py_hashtable_t *new_traces = (_Py_hashtable_t *)user_data;
517 const void *pdata = _Py_HASHTABLE_ENTRY_PDATA(old_traces, entry);
518
519 _Py_HASHTABLE_ENTRY_READ_KEY(old_traces, entry, ptr);
520 key.ptr = ptr;
521 key.domain = DEFAULT_DOMAIN;
522
523 return _Py_hashtable_set(new_traces,
524 sizeof(key), &key,
525 old_traces->data_size, pdata);
526}
527
528
Benjamin Petersonca470632016-09-06 13:47:26 -0700529/* Convert tracemalloc_traces from compact key (uintptr_t) to pointer_t key.
Victor Stinner5e14a382016-03-23 22:03:55 +0100530 * Return 0 on success, -1 on error. */
531static int
532tracemalloc_use_domain(void)
533{
534 _Py_hashtable_t *new_traces = NULL;
535
Victor Stinner9e00e802018-10-25 13:31:16 +0200536 assert(!_Py_tracemalloc_config.use_domain);
Victor Stinner5e14a382016-03-23 22:03:55 +0100537
538 new_traces = hashtable_new(sizeof(pointer_t),
539 sizeof(trace_t),
540 hashtable_hash_pointer_t,
541 hashtable_compare_pointer_t);
542 if (new_traces == NULL) {
543 return -1;
544 }
545
546 if (_Py_hashtable_foreach(tracemalloc_traces, tracemalloc_use_domain_cb,
547 new_traces) < 0)
548 {
549 _Py_hashtable_destroy(new_traces);
550 return -1;
551 }
552
553 _Py_hashtable_destroy(tracemalloc_traces);
554 tracemalloc_traces = new_traces;
555
Victor Stinner9e00e802018-10-25 13:31:16 +0200556 _Py_tracemalloc_config.use_domain = 1;
Victor Stinner5e14a382016-03-23 22:03:55 +0100557
558 return 0;
559}
560
561
Victor Stinnere492ae52016-03-22 12:58:23 +0100562static void
Victor Stinner5ea4c062017-06-20 17:46:36 +0200563tracemalloc_remove_trace(unsigned int domain, uintptr_t ptr)
Victor Stinnere492ae52016-03-22 12:58:23 +0100564{
565 trace_t trace;
566 int removed;
567
Victor Stinner9e00e802018-10-25 13:31:16 +0200568 assert(_Py_tracemalloc_config.tracing);
Victor Stinner10b73e12016-03-22 13:39:05 +0100569
Victor Stinner9e00e802018-10-25 13:31:16 +0200570 if (_Py_tracemalloc_config.use_domain) {
Victor Stinnere492ae52016-03-22 12:58:23 +0100571 pointer_t key = {ptr, domain};
572 removed = _Py_HASHTABLE_POP(tracemalloc_traces, key, trace);
573 }
574 else {
575 removed = _Py_HASHTABLE_POP(tracemalloc_traces, ptr, trace);
576 }
577 if (!removed) {
578 return;
579 }
580
581 assert(tracemalloc_traced_memory >= trace.size);
582 tracemalloc_traced_memory -= trace.size;
583}
584
585#define REMOVE_TRACE(ptr) \
Benjamin Petersonca470632016-09-06 13:47:26 -0700586 tracemalloc_remove_trace(DEFAULT_DOMAIN, (uintptr_t)(ptr))
Victor Stinnere492ae52016-03-22 12:58:23 +0100587
588
Victor Stinner52968672013-11-24 11:37:15 +0100589static int
Victor Stinner5ea4c062017-06-20 17:46:36 +0200590tracemalloc_add_trace(unsigned int domain, uintptr_t ptr,
Victor Stinner10b73e12016-03-22 13:39:05 +0100591 size_t size)
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100592{
Victor Stinnerca79ccd2016-03-23 09:38:54 +0100593 pointer_t key = {ptr, domain};
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100594 traceback_t *traceback;
595 trace_t trace;
Victor Stinnerca79ccd2016-03-23 09:38:54 +0100596 _Py_hashtable_entry_t* entry;
Victor Stinner52968672013-11-24 11:37:15 +0100597 int res;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100598
Victor Stinner9e00e802018-10-25 13:31:16 +0200599 assert(_Py_tracemalloc_config.tracing);
Victor Stinner10b73e12016-03-22 13:39:05 +0100600
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100601 traceback = traceback_new();
Victor Stinnere492ae52016-03-22 12:58:23 +0100602 if (traceback == NULL) {
Victor Stinner52968672013-11-24 11:37:15 +0100603 return -1;
Victor Stinnere492ae52016-03-22 12:58:23 +0100604 }
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100605
Victor Stinner9e00e802018-10-25 13:31:16 +0200606 if (!_Py_tracemalloc_config.use_domain && domain != DEFAULT_DOMAIN) {
Victor Stinner5e14a382016-03-23 22:03:55 +0100607 /* first trace using a non-zero domain whereas traces use compact
Benjamin Petersonca470632016-09-06 13:47:26 -0700608 (uintptr_t) keys: switch to pointer_t keys. */
Victor Stinner5e14a382016-03-23 22:03:55 +0100609 if (tracemalloc_use_domain() < 0) {
610 return -1;
611 }
612 }
613
Victor Stinner9e00e802018-10-25 13:31:16 +0200614 if (_Py_tracemalloc_config.use_domain) {
Victor Stinnerca79ccd2016-03-23 09:38:54 +0100615 entry = _Py_HASHTABLE_GET_ENTRY(tracemalloc_traces, key);
Victor Stinnere492ae52016-03-22 12:58:23 +0100616 }
617 else {
Victor Stinnerca79ccd2016-03-23 09:38:54 +0100618 entry = _Py_HASHTABLE_GET_ENTRY(tracemalloc_traces, ptr);
Victor Stinnerd606ba72013-11-24 11:28:20 +0100619 }
Victor Stinner52968672013-11-24 11:37:15 +0100620
Victor Stinnerca79ccd2016-03-23 09:38:54 +0100621 if (entry != NULL) {
622 /* the memory block is already tracked */
623 _Py_HASHTABLE_ENTRY_READ_DATA(tracemalloc_traces, entry, trace);
624 assert(tracemalloc_traced_memory >= trace.size);
625 tracemalloc_traced_memory -= trace.size;
626
627 trace.size = size;
628 trace.traceback = traceback;
629 _Py_HASHTABLE_ENTRY_WRITE_DATA(tracemalloc_traces, entry, trace);
630 }
631 else {
632 trace.size = size;
633 trace.traceback = traceback;
634
Victor Stinner9e00e802018-10-25 13:31:16 +0200635 if (_Py_tracemalloc_config.use_domain) {
Victor Stinnerca79ccd2016-03-23 09:38:54 +0100636 res = _Py_HASHTABLE_SET(tracemalloc_traces, key, trace);
637 }
638 else {
639 res = _Py_HASHTABLE_SET(tracemalloc_traces, ptr, trace);
640 }
641 if (res != 0) {
642 return res;
643 }
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100644 }
Victor Stinnere492ae52016-03-22 12:58:23 +0100645
Benjamin Peterson2f8bfef2016-09-07 09:26:18 -0700646 assert(tracemalloc_traced_memory <= SIZE_MAX - size);
Victor Stinnere492ae52016-03-22 12:58:23 +0100647 tracemalloc_traced_memory += size;
648 if (tracemalloc_traced_memory > tracemalloc_peak_traced_memory)
649 tracemalloc_peak_traced_memory = tracemalloc_traced_memory;
650 return 0;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100651}
652
Victor Stinnere492ae52016-03-22 12:58:23 +0100653#define ADD_TRACE(ptr, size) \
Benjamin Petersonca470632016-09-06 13:47:26 -0700654 tracemalloc_add_trace(DEFAULT_DOMAIN, (uintptr_t)(ptr), size)
Victor Stinnere492ae52016-03-22 12:58:23 +0100655
656
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100657static void*
Victor Stinnerdb067af2014-05-02 22:31:14 +0200658tracemalloc_alloc(int use_calloc, void *ctx, size_t nelem, size_t elsize)
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100659{
Victor Stinnerd8f0d922014-06-02 21:57:10 +0200660 PyMemAllocatorEx *alloc = (PyMemAllocatorEx *)ctx;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100661 void *ptr;
662
Benjamin Peterson2f8bfef2016-09-07 09:26:18 -0700663 assert(elsize == 0 || nelem <= SIZE_MAX / elsize);
Victor Stinnerdb067af2014-05-02 22:31:14 +0200664
665 if (use_calloc)
666 ptr = alloc->calloc(alloc->ctx, nelem, elsize);
667 else
668 ptr = alloc->malloc(alloc->ctx, nelem * elsize);
Victor Stinner15116802013-12-04 01:29:35 +0100669 if (ptr == NULL)
670 return NULL;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100671
Victor Stinner88c29872013-12-04 01:47:46 +0100672 TABLES_LOCK();
Victor Stinnere492ae52016-03-22 12:58:23 +0100673 if (ADD_TRACE(ptr, nelem * elsize) < 0) {
Victor Stinner15116802013-12-04 01:29:35 +0100674 /* Failed to allocate a trace for the new memory block */
Victor Stinner88c29872013-12-04 01:47:46 +0100675 TABLES_UNLOCK();
Victor Stinner15116802013-12-04 01:29:35 +0100676 alloc->free(alloc->ctx, ptr);
677 return NULL;
Victor Stinner52968672013-11-24 11:37:15 +0100678 }
Victor Stinner88c29872013-12-04 01:47:46 +0100679 TABLES_UNLOCK();
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100680 return ptr;
681}
682
Victor Stinnere492ae52016-03-22 12:58:23 +0100683
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100684static void*
Victor Stinner15116802013-12-04 01:29:35 +0100685tracemalloc_realloc(void *ctx, void *ptr, size_t new_size)
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100686{
Victor Stinnerd8f0d922014-06-02 21:57:10 +0200687 PyMemAllocatorEx *alloc = (PyMemAllocatorEx *)ctx;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100688 void *ptr2;
689
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100690 ptr2 = alloc->realloc(alloc->ctx, ptr, new_size);
Victor Stinner15116802013-12-04 01:29:35 +0100691 if (ptr2 == NULL)
692 return NULL;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100693
Victor Stinner15116802013-12-04 01:29:35 +0100694 if (ptr != NULL) {
695 /* an existing memory block has been resized */
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100696
Victor Stinner88c29872013-12-04 01:47:46 +0100697 TABLES_LOCK();
Victor Stinner42bcf372016-03-23 09:08:08 +0100698
699 /* tracemalloc_add_trace() updates the trace if there is already
700 a trace at address (domain, ptr2) */
701 if (ptr2 != ptr) {
702 REMOVE_TRACE(ptr);
703 }
Victor Stinner08facd22013-11-24 12:27:59 +0100704
Victor Stinnere492ae52016-03-22 12:58:23 +0100705 if (ADD_TRACE(ptr2, new_size) < 0) {
Victor Stinner15116802013-12-04 01:29:35 +0100706 /* Memory allocation failed. The error cannot be reported to
Raymond Hettinger15f44ab2016-08-30 10:47:49 -0700707 the caller, because realloc() may already have shrunk the
Victor Stinner15116802013-12-04 01:29:35 +0100708 memory block and so removed bytes.
709
Serhiy Storchaka6a7b3a72016-04-17 08:32:47 +0300710 This case is very unlikely: a hash entry has just been
Victor Stinner88c29872013-12-04 01:47:46 +0100711 released, so the hash table should have at least one free entry.
712
713 The GIL and the table lock ensures that only one thread is
714 allocating memory. */
Barry Warsawb2e57942017-09-14 18:13:16 -0700715 Py_UNREACHABLE();
Victor Stinner52968672013-11-24 11:37:15 +0100716 }
Victor Stinner88c29872013-12-04 01:47:46 +0100717 TABLES_UNLOCK();
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100718 }
Victor Stinner15116802013-12-04 01:29:35 +0100719 else {
720 /* new allocation */
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100721
Victor Stinner88c29872013-12-04 01:47:46 +0100722 TABLES_LOCK();
Victor Stinnere492ae52016-03-22 12:58:23 +0100723 if (ADD_TRACE(ptr2, new_size) < 0) {
Victor Stinner15116802013-12-04 01:29:35 +0100724 /* Failed to allocate a trace for the new memory block */
Victor Stinner88c29872013-12-04 01:47:46 +0100725 TABLES_UNLOCK();
Victor Stinner15116802013-12-04 01:29:35 +0100726 alloc->free(alloc->ctx, ptr2);
727 return NULL;
728 }
Victor Stinner88c29872013-12-04 01:47:46 +0100729 TABLES_UNLOCK();
Victor Stinner15116802013-12-04 01:29:35 +0100730 }
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100731 return ptr2;
732}
733
Victor Stinnere492ae52016-03-22 12:58:23 +0100734
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100735static void
736tracemalloc_free(void *ctx, void *ptr)
737{
Victor Stinnerd8f0d922014-06-02 21:57:10 +0200738 PyMemAllocatorEx *alloc = (PyMemAllocatorEx *)ctx;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100739
740 if (ptr == NULL)
741 return;
742
743 /* GIL cannot be locked in PyMem_RawFree() because it would introduce
Joannah Nanjekye2bc43cd2019-09-05 13:06:49 -0300744 a deadlock in _PyThreadState_DeleteCurrent(). */
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100745
746 alloc->free(alloc->ctx, ptr);
Victor Stinner88c29872013-12-04 01:47:46 +0100747
748 TABLES_LOCK();
Victor Stinnere492ae52016-03-22 12:58:23 +0100749 REMOVE_TRACE(ptr);
Victor Stinner88c29872013-12-04 01:47:46 +0100750 TABLES_UNLOCK();
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100751}
752
Victor Stinnere492ae52016-03-22 12:58:23 +0100753
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100754static void*
Victor Stinnerdb067af2014-05-02 22:31:14 +0200755tracemalloc_alloc_gil(int use_calloc, void *ctx, size_t nelem, size_t elsize)
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100756{
Victor Stinner15116802013-12-04 01:29:35 +0100757 void *ptr;
758
759 if (get_reentrant()) {
Victor Stinnerd8f0d922014-06-02 21:57:10 +0200760 PyMemAllocatorEx *alloc = (PyMemAllocatorEx *)ctx;
Victor Stinnerdb067af2014-05-02 22:31:14 +0200761 if (use_calloc)
762 return alloc->calloc(alloc->ctx, nelem, elsize);
763 else
764 return alloc->malloc(alloc->ctx, nelem * elsize);
Victor Stinner15116802013-12-04 01:29:35 +0100765 }
766
767 /* Ignore reentrant call. PyObjet_Malloc() calls PyMem_Malloc() for
768 allocations larger than 512 bytes, don't trace the same memory
769 allocation twice. */
770 set_reentrant(1);
771
Victor Stinnerdb067af2014-05-02 22:31:14 +0200772 ptr = tracemalloc_alloc(use_calloc, ctx, nelem, elsize);
Victor Stinner15116802013-12-04 01:29:35 +0100773
774 set_reentrant(0);
775 return ptr;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100776}
777
Victor Stinnere492ae52016-03-22 12:58:23 +0100778
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100779static void*
Victor Stinnerdb067af2014-05-02 22:31:14 +0200780tracemalloc_malloc_gil(void *ctx, size_t size)
781{
782 return tracemalloc_alloc_gil(0, ctx, 1, size);
783}
784
Victor Stinnere492ae52016-03-22 12:58:23 +0100785
Victor Stinnerdb067af2014-05-02 22:31:14 +0200786static void*
787tracemalloc_calloc_gil(void *ctx, size_t nelem, size_t elsize)
788{
789 return tracemalloc_alloc_gil(1, ctx, nelem, elsize);
790}
791
Victor Stinnere492ae52016-03-22 12:58:23 +0100792
Victor Stinnerdb067af2014-05-02 22:31:14 +0200793static void*
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100794tracemalloc_realloc_gil(void *ctx, void *ptr, size_t new_size)
795{
Victor Stinner15116802013-12-04 01:29:35 +0100796 void *ptr2;
797
798 if (get_reentrant()) {
799 /* Reentrant call to PyMem_Realloc() and PyMem_RawRealloc().
800 Example: PyMem_RawRealloc() is called internally by pymalloc
801 (_PyObject_Malloc() and _PyObject_Realloc()) to allocate a new
802 arena (new_arena()). */
Victor Stinnerd8f0d922014-06-02 21:57:10 +0200803 PyMemAllocatorEx *alloc = (PyMemAllocatorEx *)ctx;
Victor Stinner15116802013-12-04 01:29:35 +0100804
805 ptr2 = alloc->realloc(alloc->ctx, ptr, new_size);
Victor Stinner88c29872013-12-04 01:47:46 +0100806 if (ptr2 != NULL && ptr != NULL) {
807 TABLES_LOCK();
Victor Stinnere492ae52016-03-22 12:58:23 +0100808 REMOVE_TRACE(ptr);
Victor Stinner88c29872013-12-04 01:47:46 +0100809 TABLES_UNLOCK();
810 }
Victor Stinner15116802013-12-04 01:29:35 +0100811 return ptr2;
812 }
813
814 /* Ignore reentrant call. PyObjet_Realloc() calls PyMem_Realloc() for
815 allocations larger than 512 bytes. Don't trace the same memory
816 allocation twice. */
817 set_reentrant(1);
818
819 ptr2 = tracemalloc_realloc(ctx, ptr, new_size);
820
821 set_reentrant(0);
822 return ptr2;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100823}
824
Victor Stinnere492ae52016-03-22 12:58:23 +0100825
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100826#ifdef TRACE_RAW_MALLOC
827static void*
Victor Stinnerdb067af2014-05-02 22:31:14 +0200828tracemalloc_raw_alloc(int use_calloc, void *ctx, size_t nelem, size_t elsize)
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100829{
Victor Stinner15116802013-12-04 01:29:35 +0100830 PyGILState_STATE gil_state;
Victor Stinner15116802013-12-04 01:29:35 +0100831 void *ptr;
832
833 if (get_reentrant()) {
Victor Stinnerd8f0d922014-06-02 21:57:10 +0200834 PyMemAllocatorEx *alloc = (PyMemAllocatorEx *)ctx;
Victor Stinnerdb067af2014-05-02 22:31:14 +0200835 if (use_calloc)
836 return alloc->calloc(alloc->ctx, nelem, elsize);
837 else
838 return alloc->malloc(alloc->ctx, nelem * elsize);
Victor Stinner15116802013-12-04 01:29:35 +0100839 }
840
841 /* Ignore reentrant call. PyGILState_Ensure() may call PyMem_RawMalloc()
842 indirectly which would call PyGILState_Ensure() if reentrant are not
843 disabled. */
844 set_reentrant(1);
845
Victor Stinner15116802013-12-04 01:29:35 +0100846 gil_state = PyGILState_Ensure();
Victor Stinnerdb067af2014-05-02 22:31:14 +0200847 ptr = tracemalloc_alloc(use_calloc, ctx, nelem, elsize);
Victor Stinner15116802013-12-04 01:29:35 +0100848 PyGILState_Release(gil_state);
Victor Stinner15116802013-12-04 01:29:35 +0100849
850 set_reentrant(0);
851 return ptr;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100852}
853
Victor Stinnere492ae52016-03-22 12:58:23 +0100854
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100855static void*
Victor Stinnerdb067af2014-05-02 22:31:14 +0200856tracemalloc_raw_malloc(void *ctx, size_t size)
857{
858 return tracemalloc_raw_alloc(0, ctx, 1, size);
859}
860
Victor Stinnere492ae52016-03-22 12:58:23 +0100861
Victor Stinnerdb067af2014-05-02 22:31:14 +0200862static void*
863tracemalloc_raw_calloc(void *ctx, size_t nelem, size_t elsize)
864{
865 return tracemalloc_raw_alloc(1, ctx, nelem, elsize);
866}
867
Victor Stinnere492ae52016-03-22 12:58:23 +0100868
Victor Stinnerdb067af2014-05-02 22:31:14 +0200869static void*
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100870tracemalloc_raw_realloc(void *ctx, void *ptr, size_t new_size)
871{
Victor Stinner15116802013-12-04 01:29:35 +0100872 PyGILState_STATE gil_state;
Victor Stinner15116802013-12-04 01:29:35 +0100873 void *ptr2;
874
875 if (get_reentrant()) {
876 /* Reentrant call to PyMem_RawRealloc(). */
Victor Stinnerd8f0d922014-06-02 21:57:10 +0200877 PyMemAllocatorEx *alloc = (PyMemAllocatorEx *)ctx;
Victor Stinner15116802013-12-04 01:29:35 +0100878
879 ptr2 = alloc->realloc(alloc->ctx, ptr, new_size);
Victor Stinner15116802013-12-04 01:29:35 +0100880
Victor Stinner88c29872013-12-04 01:47:46 +0100881 if (ptr2 != NULL && ptr != NULL) {
882 TABLES_LOCK();
Victor Stinnere492ae52016-03-22 12:58:23 +0100883 REMOVE_TRACE(ptr);
Victor Stinner88c29872013-12-04 01:47:46 +0100884 TABLES_UNLOCK();
885 }
Victor Stinner15116802013-12-04 01:29:35 +0100886 return ptr2;
887 }
888
889 /* Ignore reentrant call. PyGILState_Ensure() may call PyMem_RawMalloc()
890 indirectly which would call PyGILState_Ensure() if reentrant calls are
891 not disabled. */
892 set_reentrant(1);
893
Victor Stinner15116802013-12-04 01:29:35 +0100894 gil_state = PyGILState_Ensure();
895 ptr2 = tracemalloc_realloc(ctx, ptr, new_size);
896 PyGILState_Release(gil_state);
Victor Stinner15116802013-12-04 01:29:35 +0100897
898 set_reentrant(0);
899 return ptr2;
900}
901#endif /* TRACE_RAW_MALLOC */
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100902
Victor Stinnere492ae52016-03-22 12:58:23 +0100903
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100904static int
Victor Stinner285cf0a2016-03-21 22:00:58 +0100905tracemalloc_clear_filename(_Py_hashtable_t *ht, _Py_hashtable_entry_t *entry,
906 void *user_data)
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100907{
Victor Stinner285cf0a2016-03-21 22:00:58 +0100908 PyObject *filename;
909
Victor Stinner5dacbd42016-03-23 09:52:13 +0100910 _Py_HASHTABLE_ENTRY_READ_KEY(ht, entry, filename);
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100911 Py_DECREF(filename);
912 return 0;
913}
914
Victor Stinnere492ae52016-03-22 12:58:23 +0100915
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100916static int
Victor Stinner285cf0a2016-03-21 22:00:58 +0100917traceback_free_traceback(_Py_hashtable_t *ht, _Py_hashtable_entry_t *entry,
918 void *user_data)
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100919{
Victor Stinner285cf0a2016-03-21 22:00:58 +0100920 traceback_t *traceback;
921
Victor Stinner5dacbd42016-03-23 09:52:13 +0100922 _Py_HASHTABLE_ENTRY_READ_KEY(ht, entry, traceback);
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100923 raw_free(traceback);
924 return 0;
925}
926
Victor Stinnere492ae52016-03-22 12:58:23 +0100927
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100928/* reentrant flag must be set to call this function and GIL must be held */
929static void
930tracemalloc_clear_traces(void)
931{
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100932 /* The GIL protects variables againt concurrent access */
933 assert(PyGILState_Check());
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100934
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100935 TABLES_LOCK();
936 _Py_hashtable_clear(tracemalloc_traces);
937 tracemalloc_traced_memory = 0;
Victor Stinner3c0481d2013-11-27 21:39:49 +0100938 tracemalloc_peak_traced_memory = 0;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100939 TABLES_UNLOCK();
940
941 _Py_hashtable_foreach(tracemalloc_tracebacks, traceback_free_traceback, NULL);
942 _Py_hashtable_clear(tracemalloc_tracebacks);
943
944 _Py_hashtable_foreach(tracemalloc_filenames, tracemalloc_clear_filename, NULL);
945 _Py_hashtable_clear(tracemalloc_filenames);
946}
947
Victor Stinnere492ae52016-03-22 12:58:23 +0100948
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100949static int
950tracemalloc_init(void)
951{
Victor Stinner9e00e802018-10-25 13:31:16 +0200952 if (_Py_tracemalloc_config.initialized == TRACEMALLOC_FINALIZED) {
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100953 PyErr_SetString(PyExc_RuntimeError,
954 "the tracemalloc module has been unloaded");
955 return -1;
956 }
957
Victor Stinner9e00e802018-10-25 13:31:16 +0200958 if (_Py_tracemalloc_config.initialized == TRACEMALLOC_INITIALIZED)
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100959 return 0;
960
961 PyMem_GetAllocator(PYMEM_DOMAIN_RAW, &allocators.raw);
962
963#ifdef REENTRANT_THREADLOCAL
Masayuki Yamamoto731e1892017-10-06 19:41:34 +0900964 if (PyThread_tss_create(&tracemalloc_reentrant_key) != 0) {
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100965#ifdef MS_WINDOWS
966 PyErr_SetFromWindowsErr(0);
967#else
968 PyErr_SetFromErrno(PyExc_OSError);
969#endif
970 return -1;
971 }
972#endif
973
Antoine Pitroua6a4dc82017-09-07 18:56:24 +0200974#if defined(TRACE_RAW_MALLOC)
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100975 if (tables_lock == NULL) {
976 tables_lock = PyThread_allocate_lock();
977 if (tables_lock == NULL) {
978 PyErr_SetString(PyExc_RuntimeError, "cannot allocate lock");
979 return -1;
980 }
981 }
982#endif
983
Victor Stinner285cf0a2016-03-21 22:00:58 +0100984 tracemalloc_filenames = hashtable_new(sizeof(PyObject *), 0,
985 hashtable_hash_pyobject,
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100986 hashtable_compare_unicode);
987
Victor Stinner285cf0a2016-03-21 22:00:58 +0100988 tracemalloc_tracebacks = hashtable_new(sizeof(traceback_t *), 0,
989 hashtable_hash_traceback,
990 hashtable_compare_traceback);
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100991
Victor Stinner9e00e802018-10-25 13:31:16 +0200992 if (_Py_tracemalloc_config.use_domain) {
Victor Stinnere492ae52016-03-22 12:58:23 +0100993 tracemalloc_traces = hashtable_new(sizeof(pointer_t),
994 sizeof(trace_t),
995 hashtable_hash_pointer_t,
996 hashtable_compare_pointer_t);
997 }
998 else {
Benjamin Petersonca470632016-09-06 13:47:26 -0700999 tracemalloc_traces = hashtable_new(sizeof(uintptr_t),
Victor Stinnere492ae52016-03-22 12:58:23 +01001000 sizeof(trace_t),
1001 _Py_hashtable_hash_ptr,
1002 _Py_hashtable_compare_direct);
1003 }
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001004
1005 if (tracemalloc_filenames == NULL || tracemalloc_tracebacks == NULL
Victor Stinner285cf0a2016-03-21 22:00:58 +01001006 || tracemalloc_traces == NULL) {
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001007 PyErr_NoMemory();
1008 return -1;
1009 }
1010
1011 unknown_filename = PyUnicode_FromString("<unknown>");
1012 if (unknown_filename == NULL)
1013 return -1;
1014 PyUnicode_InternInPlace(&unknown_filename);
1015
1016 tracemalloc_empty_traceback.nframe = 1;
Julien Danjou8d59eb12019-10-15 14:00:16 +02001017 tracemalloc_empty_traceback.total_nframe = 1;
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001018 /* borrowed reference */
1019 tracemalloc_empty_traceback.frames[0].filename = unknown_filename;
1020 tracemalloc_empty_traceback.frames[0].lineno = 0;
1021 tracemalloc_empty_traceback.hash = traceback_hash(&tracemalloc_empty_traceback);
1022
Victor Stinner9e00e802018-10-25 13:31:16 +02001023 _Py_tracemalloc_config.initialized = TRACEMALLOC_INITIALIZED;
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001024 return 0;
1025}
1026
Victor Stinnere492ae52016-03-22 12:58:23 +01001027
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001028static void
1029tracemalloc_deinit(void)
1030{
Victor Stinner9e00e802018-10-25 13:31:16 +02001031 if (_Py_tracemalloc_config.initialized != TRACEMALLOC_INITIALIZED)
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001032 return;
Victor Stinner9e00e802018-10-25 13:31:16 +02001033 _Py_tracemalloc_config.initialized = TRACEMALLOC_FINALIZED;
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001034
1035 tracemalloc_stop();
1036
1037 /* destroy hash tables */
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001038 _Py_hashtable_destroy(tracemalloc_tracebacks);
1039 _Py_hashtable_destroy(tracemalloc_filenames);
Victor Stinner285cf0a2016-03-21 22:00:58 +01001040 _Py_hashtable_destroy(tracemalloc_traces);
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001041
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02001042#if defined(TRACE_RAW_MALLOC)
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001043 if (tables_lock != NULL) {
1044 PyThread_free_lock(tables_lock);
1045 tables_lock = NULL;
1046 }
1047#endif
1048
1049#ifdef REENTRANT_THREADLOCAL
Masayuki Yamamoto731e1892017-10-06 19:41:34 +09001050 PyThread_tss_delete(&tracemalloc_reentrant_key);
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001051#endif
1052
1053 Py_XDECREF(unknown_filename);
1054}
1055
Victor Stinnere492ae52016-03-22 12:58:23 +01001056
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001057static int
Victor Stinnerf28ce602013-11-27 22:27:13 +01001058tracemalloc_start(int max_nframe)
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001059{
Victor Stinnerd8f0d922014-06-02 21:57:10 +02001060 PyMemAllocatorEx alloc;
Victor Stinnerf28ce602013-11-27 22:27:13 +01001061 size_t size;
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001062
Julien Danjou8d59eb12019-10-15 14:00:16 +02001063 if (max_nframe < 1 || (unsigned long) max_nframe > MAX_NFRAME) {
Victor Stinnera7368ac2017-11-15 18:11:45 -08001064 PyErr_Format(PyExc_ValueError,
Julien Danjou8d59eb12019-10-15 14:00:16 +02001065 "the number of frames must be in range [1; %lu]",
1066 MAX_NFRAME);
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001067 return -1;
Victor Stinnera7368ac2017-11-15 18:11:45 -08001068 }
1069
1070 if (tracemalloc_init() < 0) {
1071 return -1;
1072 }
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001073
Victor Stinner9e00e802018-10-25 13:31:16 +02001074 if (_Py_tracemalloc_config.tracing) {
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001075 /* hook already installed: do nothing */
1076 return 0;
1077 }
1078
Victor Stinner9e00e802018-10-25 13:31:16 +02001079 _Py_tracemalloc_config.max_nframe = max_nframe;
Victor Stinnerf28ce602013-11-27 22:27:13 +01001080
1081 /* allocate a buffer to store a new traceback */
1082 size = TRACEBACK_SIZE(max_nframe);
1083 assert(tracemalloc_traceback == NULL);
1084 tracemalloc_traceback = raw_malloc(size);
1085 if (tracemalloc_traceback == NULL) {
1086 PyErr_NoMemory();
1087 return -1;
1088 }
1089
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001090#ifdef TRACE_RAW_MALLOC
1091 alloc.malloc = tracemalloc_raw_malloc;
Victor Stinnerdb067af2014-05-02 22:31:14 +02001092 alloc.calloc = tracemalloc_raw_calloc;
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001093 alloc.realloc = tracemalloc_raw_realloc;
1094 alloc.free = tracemalloc_free;
1095
1096 alloc.ctx = &allocators.raw;
1097 PyMem_GetAllocator(PYMEM_DOMAIN_RAW, &allocators.raw);
1098 PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &alloc);
1099#endif
1100
1101 alloc.malloc = tracemalloc_malloc_gil;
Victor Stinnerdb067af2014-05-02 22:31:14 +02001102 alloc.calloc = tracemalloc_calloc_gil;
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001103 alloc.realloc = tracemalloc_realloc_gil;
1104 alloc.free = tracemalloc_free;
1105
1106 alloc.ctx = &allocators.mem;
1107 PyMem_GetAllocator(PYMEM_DOMAIN_MEM, &allocators.mem);
1108 PyMem_SetAllocator(PYMEM_DOMAIN_MEM, &alloc);
1109
1110 alloc.ctx = &allocators.obj;
1111 PyMem_GetAllocator(PYMEM_DOMAIN_OBJ, &allocators.obj);
1112 PyMem_SetAllocator(PYMEM_DOMAIN_OBJ, &alloc);
1113
1114 /* everything is ready: start tracing Python memory allocations */
Victor Stinner9e00e802018-10-25 13:31:16 +02001115 _Py_tracemalloc_config.tracing = 1;
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001116
1117 return 0;
1118}
1119
Victor Stinnere492ae52016-03-22 12:58:23 +01001120
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001121static void
1122tracemalloc_stop(void)
1123{
Victor Stinner9e00e802018-10-25 13:31:16 +02001124 if (!_Py_tracemalloc_config.tracing)
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001125 return;
1126
1127 /* stop tracing Python memory allocations */
Victor Stinner9e00e802018-10-25 13:31:16 +02001128 _Py_tracemalloc_config.tracing = 0;
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001129
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001130 /* unregister the hook on memory allocators */
1131#ifdef TRACE_RAW_MALLOC
1132 PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &allocators.raw);
1133#endif
1134 PyMem_SetAllocator(PYMEM_DOMAIN_MEM, &allocators.mem);
1135 PyMem_SetAllocator(PYMEM_DOMAIN_OBJ, &allocators.obj);
1136
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001137 tracemalloc_clear_traces();
Victor Stinner285cf0a2016-03-21 22:00:58 +01001138
1139 /* release memory */
Victor Stinnerf28ce602013-11-27 22:27:13 +01001140 raw_free(tracemalloc_traceback);
1141 tracemalloc_traceback = NULL;
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001142}
1143
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001144
Victor Stinnere492ae52016-03-22 12:58:23 +01001145
Serhiy Storchakab451f912017-02-04 12:18:38 +02001146/*[clinic input]
1147_tracemalloc.is_tracing
1148
1149Return True if the tracemalloc module is tracing Python memory allocations.
1150[clinic start generated code]*/
1151
1152static PyObject *
1153_tracemalloc_is_tracing_impl(PyObject *module)
Serhiy Storchaka97353842017-02-05 22:58:46 +02001154/*[clinic end generated code: output=2d763b42601cd3ef input=af104b0a00192f63]*/
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001155{
Victor Stinner9e00e802018-10-25 13:31:16 +02001156 return PyBool_FromLong(_Py_tracemalloc_config.tracing);
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001157}
1158
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001159
Serhiy Storchakab451f912017-02-04 12:18:38 +02001160/*[clinic input]
1161_tracemalloc.clear_traces
Victor Stinnere492ae52016-03-22 12:58:23 +01001162
Serhiy Storchakab451f912017-02-04 12:18:38 +02001163Clear traces of memory blocks allocated by Python.
1164[clinic start generated code]*/
1165
1166static PyObject *
1167_tracemalloc_clear_traces_impl(PyObject *module)
1168/*[clinic end generated code: output=a86080ee41b84197 input=0dab5b6c785183a5]*/
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001169{
Victor Stinner9e00e802018-10-25 13:31:16 +02001170 if (!_Py_tracemalloc_config.tracing)
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001171 Py_RETURN_NONE;
1172
1173 set_reentrant(1);
1174 tracemalloc_clear_traces();
1175 set_reentrant(0);
1176
1177 Py_RETURN_NONE;
1178}
1179
Victor Stinnere492ae52016-03-22 12:58:23 +01001180
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001181static PyObject*
1182frame_to_pyobject(frame_t *frame)
1183{
1184 PyObject *frame_obj, *lineno_obj;
1185
1186 frame_obj = PyTuple_New(2);
1187 if (frame_obj == NULL)
1188 return NULL;
1189
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001190 Py_INCREF(frame->filename);
1191 PyTuple_SET_ITEM(frame_obj, 0, frame->filename);
1192
Victor Stinner95283342016-03-15 21:57:02 +01001193 lineno_obj = PyLong_FromUnsignedLong(frame->lineno);
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001194 if (lineno_obj == NULL) {
1195 Py_DECREF(frame_obj);
1196 return NULL;
1197 }
1198 PyTuple_SET_ITEM(frame_obj, 1, lineno_obj);
1199
1200 return frame_obj;
1201}
1202
Victor Stinnere492ae52016-03-22 12:58:23 +01001203
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001204static PyObject*
1205traceback_to_pyobject(traceback_t *traceback, _Py_hashtable_t *intern_table)
1206{
1207 int i;
1208 PyObject *frames, *frame;
1209
1210 if (intern_table != NULL) {
1211 if (_Py_HASHTABLE_GET(intern_table, traceback, frames)) {
1212 Py_INCREF(frames);
1213 return frames;
1214 }
1215 }
1216
1217 frames = PyTuple_New(traceback->nframe);
1218 if (frames == NULL)
1219 return NULL;
1220
1221 for (i=0; i < traceback->nframe; i++) {
1222 frame = frame_to_pyobject(&traceback->frames[i]);
1223 if (frame == NULL) {
1224 Py_DECREF(frames);
1225 return NULL;
1226 }
1227 PyTuple_SET_ITEM(frames, i, frame);
1228 }
1229
1230 if (intern_table != NULL) {
1231 if (_Py_HASHTABLE_SET(intern_table, traceback, frames) < 0) {
1232 Py_DECREF(frames);
1233 PyErr_NoMemory();
1234 return NULL;
1235 }
1236 /* intern_table keeps a new reference to frames */
1237 Py_INCREF(frames);
1238 }
1239 return frames;
1240}
1241
Victor Stinnere492ae52016-03-22 12:58:23 +01001242
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001243static PyObject*
Victor Stinner5ea4c062017-06-20 17:46:36 +02001244trace_to_pyobject(unsigned int domain, trace_t *trace,
Victor Stinnere492ae52016-03-22 12:58:23 +01001245 _Py_hashtable_t *intern_tracebacks)
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001246{
1247 PyObject *trace_obj = NULL;
Victor Stinnere492ae52016-03-22 12:58:23 +01001248 PyObject *obj;
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001249
Julien Danjou8d59eb12019-10-15 14:00:16 +02001250 trace_obj = PyTuple_New(4);
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001251 if (trace_obj == NULL)
1252 return NULL;
1253
Victor Stinnere492ae52016-03-22 12:58:23 +01001254 obj = PyLong_FromSize_t(domain);
1255 if (obj == NULL) {
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001256 Py_DECREF(trace_obj);
1257 return NULL;
1258 }
Victor Stinnere492ae52016-03-22 12:58:23 +01001259 PyTuple_SET_ITEM(trace_obj, 0, obj);
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001260
Victor Stinnere492ae52016-03-22 12:58:23 +01001261 obj = PyLong_FromSize_t(trace->size);
1262 if (obj == NULL) {
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001263 Py_DECREF(trace_obj);
1264 return NULL;
1265 }
Victor Stinnere492ae52016-03-22 12:58:23 +01001266 PyTuple_SET_ITEM(trace_obj, 1, obj);
1267
1268 obj = traceback_to_pyobject(trace->traceback, intern_tracebacks);
1269 if (obj == NULL) {
1270 Py_DECREF(trace_obj);
1271 return NULL;
1272 }
1273 PyTuple_SET_ITEM(trace_obj, 2, obj);
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001274
Julien Danjou8d59eb12019-10-15 14:00:16 +02001275 obj = PyLong_FromUnsignedLong(trace->traceback->total_nframe);
1276 if (obj == NULL) {
1277 Py_DECREF(trace_obj);
1278 return NULL;
1279 }
1280 PyTuple_SET_ITEM(trace_obj, 3, obj);
1281
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001282 return trace_obj;
1283}
1284
Victor Stinnere492ae52016-03-22 12:58:23 +01001285
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001286typedef struct {
1287 _Py_hashtable_t *traces;
1288 _Py_hashtable_t *tracebacks;
1289 PyObject *list;
1290} get_traces_t;
1291
1292static int
Victor Stinner285cf0a2016-03-21 22:00:58 +01001293tracemalloc_get_traces_fill(_Py_hashtable_t *traces, _Py_hashtable_entry_t *entry,
1294 void *user_data)
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001295{
1296 get_traces_t *get_traces = user_data;
Victor Stinner5ea4c062017-06-20 17:46:36 +02001297 unsigned int domain;
Victor Stinner5dacbd42016-03-23 09:52:13 +01001298 trace_t trace;
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001299 PyObject *tracemalloc_obj;
1300 int res;
1301
Victor Stinner9e00e802018-10-25 13:31:16 +02001302 if (_Py_tracemalloc_config.use_domain) {
Victor Stinnere492ae52016-03-22 12:58:23 +01001303 pointer_t key;
Victor Stinner5dacbd42016-03-23 09:52:13 +01001304 _Py_HASHTABLE_ENTRY_READ_KEY(traces, entry, key);
Victor Stinnere492ae52016-03-22 12:58:23 +01001305 domain = key.domain;
1306 }
1307 else {
1308 domain = DEFAULT_DOMAIN;
1309 }
Victor Stinner5dacbd42016-03-23 09:52:13 +01001310 _Py_HASHTABLE_ENTRY_READ_DATA(traces, entry, trace);
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001311
Victor Stinner5dacbd42016-03-23 09:52:13 +01001312 tracemalloc_obj = trace_to_pyobject(domain, &trace, get_traces->tracebacks);
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001313 if (tracemalloc_obj == NULL)
1314 return 1;
1315
1316 res = PyList_Append(get_traces->list, tracemalloc_obj);
1317 Py_DECREF(tracemalloc_obj);
1318 if (res < 0)
1319 return 1;
1320
1321 return 0;
1322}
1323
Victor Stinnere492ae52016-03-22 12:58:23 +01001324
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001325static int
Victor Stinner285cf0a2016-03-21 22:00:58 +01001326tracemalloc_pyobject_decref_cb(_Py_hashtable_t *tracebacks,
1327 _Py_hashtable_entry_t *entry,
1328 void *user_data)
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001329{
Victor Stinnerc9553872016-03-22 12:13:01 +01001330 PyObject *obj;
Victor Stinnere8c6b2f2016-03-23 09:25:01 +01001331 _Py_HASHTABLE_ENTRY_READ_DATA(tracebacks, entry, obj);
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001332 Py_DECREF(obj);
1333 return 0;
1334}
1335
Victor Stinnere492ae52016-03-22 12:58:23 +01001336
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001337
Serhiy Storchakab451f912017-02-04 12:18:38 +02001338/*[clinic input]
1339_tracemalloc._get_traces
1340
1341Get traces of all memory blocks allocated by Python.
1342
1343Return a list of (size: int, traceback: tuple) tuples.
1344traceback is a tuple of (filename: str, lineno: int) tuples.
1345
1346Return an empty list if the tracemalloc module is disabled.
1347[clinic start generated code]*/
1348
1349static PyObject *
1350_tracemalloc__get_traces_impl(PyObject *module)
1351/*[clinic end generated code: output=e9929876ced4b5cc input=6c7d2230b24255aa]*/
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001352{
1353 get_traces_t get_traces;
1354 int err;
1355
1356 get_traces.traces = NULL;
1357 get_traces.tracebacks = NULL;
1358 get_traces.list = PyList_New(0);
1359 if (get_traces.list == NULL)
1360 goto error;
1361
Victor Stinner9e00e802018-10-25 13:31:16 +02001362 if (!_Py_tracemalloc_config.tracing)
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001363 return get_traces.list;
1364
Victor Stinnerde2f1322013-11-26 00:26:23 +01001365 /* the traceback hash table is used temporarily to intern traceback tuple
1366 of (filename, lineno) tuples */
Victor Stinnerc9553872016-03-22 12:13:01 +01001367 get_traces.tracebacks = hashtable_new(sizeof(traceback_t *),
1368 sizeof(PyObject *),
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001369 _Py_hashtable_hash_ptr,
1370 _Py_hashtable_compare_direct);
1371 if (get_traces.tracebacks == NULL) {
1372 PyErr_NoMemory();
1373 goto error;
1374 }
1375
1376 TABLES_LOCK();
1377 get_traces.traces = _Py_hashtable_copy(tracemalloc_traces);
1378 TABLES_UNLOCK();
1379
1380 if (get_traces.traces == NULL) {
1381 PyErr_NoMemory();
1382 goto error;
1383 }
1384
1385 set_reentrant(1);
1386 err = _Py_hashtable_foreach(get_traces.traces,
1387 tracemalloc_get_traces_fill, &get_traces);
1388 set_reentrant(0);
1389 if (err)
1390 goto error;
1391
1392 goto finally;
1393
1394error:
1395 Py_CLEAR(get_traces.list);
1396
1397finally:
1398 if (get_traces.tracebacks != NULL) {
1399 _Py_hashtable_foreach(get_traces.tracebacks,
Victor Stinner285cf0a2016-03-21 22:00:58 +01001400 tracemalloc_pyobject_decref_cb, NULL);
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001401 _Py_hashtable_destroy(get_traces.tracebacks);
1402 }
Victor Stinnerc9553872016-03-22 12:13:01 +01001403 if (get_traces.traces != NULL) {
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001404 _Py_hashtable_destroy(get_traces.traces);
Victor Stinnerc9553872016-03-22 12:13:01 +01001405 }
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001406
1407 return get_traces.list;
1408}
1409
Victor Stinnere492ae52016-03-22 12:58:23 +01001410
Victor Stinner0611c262016-03-15 22:22:13 +01001411static traceback_t*
Victor Stinner5ea4c062017-06-20 17:46:36 +02001412tracemalloc_get_traceback(unsigned int domain, uintptr_t ptr)
Victor Stinner0611c262016-03-15 22:22:13 +01001413{
1414 trace_t trace;
1415 int found;
1416
Victor Stinner9e00e802018-10-25 13:31:16 +02001417 if (!_Py_tracemalloc_config.tracing)
Victor Stinner0611c262016-03-15 22:22:13 +01001418 return NULL;
1419
1420 TABLES_LOCK();
Victor Stinner9e00e802018-10-25 13:31:16 +02001421 if (_Py_tracemalloc_config.use_domain) {
Victor Stinner10b73e12016-03-22 13:39:05 +01001422 pointer_t key = {ptr, domain};
Victor Stinnere492ae52016-03-22 12:58:23 +01001423 found = _Py_HASHTABLE_GET(tracemalloc_traces, key, trace);
1424 }
1425 else {
1426 found = _Py_HASHTABLE_GET(tracemalloc_traces, ptr, trace);
1427 }
Victor Stinner0611c262016-03-15 22:22:13 +01001428 TABLES_UNLOCK();
1429
1430 if (!found)
1431 return NULL;
1432
1433 return trace.traceback;
1434}
1435
Victor Stinnere492ae52016-03-22 12:58:23 +01001436
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001437
Serhiy Storchakab451f912017-02-04 12:18:38 +02001438/*[clinic input]
1439_tracemalloc._get_object_traceback
1440
1441 obj: object
1442 /
1443
1444Get the traceback where the Python object obj was allocated.
1445
1446Return a tuple of (filename: str, lineno: int) tuples.
1447Return None if the tracemalloc module is disabled or did not
1448trace the allocation of the object.
1449[clinic start generated code]*/
1450
1451static PyObject *
1452_tracemalloc__get_object_traceback(PyObject *module, PyObject *obj)
1453/*[clinic end generated code: output=41ee0553a658b0aa input=29495f1b21c53212]*/
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001454{
1455 PyTypeObject *type;
1456 void *ptr;
Victor Stinner0611c262016-03-15 22:22:13 +01001457 traceback_t *traceback;
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001458
1459 type = Py_TYPE(obj);
Victor Stinner626bff82018-10-25 17:31:10 +02001460 if (PyType_IS_GC(type)) {
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001461 ptr = (void *)((char *)obj - sizeof(PyGC_Head));
Victor Stinner626bff82018-10-25 17:31:10 +02001462 }
1463 else {
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001464 ptr = (void *)obj;
Victor Stinner626bff82018-10-25 17:31:10 +02001465 }
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001466
Benjamin Petersonca470632016-09-06 13:47:26 -07001467 traceback = tracemalloc_get_traceback(DEFAULT_DOMAIN, (uintptr_t)ptr);
Victor Stinner0611c262016-03-15 22:22:13 +01001468 if (traceback == NULL)
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001469 Py_RETURN_NONE;
1470
Victor Stinner0611c262016-03-15 22:22:13 +01001471 return traceback_to_pyobject(traceback, NULL);
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001472}
1473
Victor Stinnere492ae52016-03-22 12:58:23 +01001474
Victor Stinner0611c262016-03-15 22:22:13 +01001475#define PUTS(fd, str) _Py_write_noraise(fd, str, (int)strlen(str))
1476
1477static void
1478_PyMem_DumpFrame(int fd, frame_t * frame)
1479{
1480 PUTS(fd, " File \"");
1481 _Py_DumpASCII(fd, frame->filename);
1482 PUTS(fd, "\", line ");
1483 _Py_DumpDecimal(fd, frame->lineno);
1484 PUTS(fd, "\n");
1485}
1486
1487/* Dump the traceback where a memory block was allocated into file descriptor
1488 fd. The function may block on TABLES_LOCK() but it is unlikely. */
1489void
1490_PyMem_DumpTraceback(int fd, const void *ptr)
1491{
1492 traceback_t *traceback;
1493 int i;
1494
Victor Stinnerf966e532018-11-13 15:14:58 +01001495 if (!_Py_tracemalloc_config.tracing) {
1496 PUTS(fd, "Enable tracemalloc to get the memory block "
1497 "allocation traceback\n\n");
1498 return;
1499 }
1500
Benjamin Petersonca470632016-09-06 13:47:26 -07001501 traceback = tracemalloc_get_traceback(DEFAULT_DOMAIN, (uintptr_t)ptr);
Victor Stinner0611c262016-03-15 22:22:13 +01001502 if (traceback == NULL)
1503 return;
1504
1505 PUTS(fd, "Memory block allocated at (most recent call first):\n");
1506 for (i=0; i < traceback->nframe; i++) {
1507 _PyMem_DumpFrame(fd, &traceback->frames[i]);
1508 }
1509 PUTS(fd, "\n");
1510}
1511
1512#undef PUTS
1513
Victor Stinnere492ae52016-03-22 12:58:23 +01001514
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001515
Serhiy Storchakab451f912017-02-04 12:18:38 +02001516/*[clinic input]
1517_tracemalloc.start
1518
Victor Stinnera7368ac2017-11-15 18:11:45 -08001519 nframe: int = 1
Serhiy Storchakab451f912017-02-04 12:18:38 +02001520 /
1521
1522Start tracing Python memory allocations.
1523
1524Also set the maximum number of frames stored in the traceback of a
1525trace to nframe.
1526[clinic start generated code]*/
1527
1528static PyObject *
Victor Stinnera7368ac2017-11-15 18:11:45 -08001529_tracemalloc_start_impl(PyObject *module, int nframe)
1530/*[clinic end generated code: output=caae05c23c159d3c input=40d849b5b29d1933]*/
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001531{
Victor Stinnera7368ac2017-11-15 18:11:45 -08001532 if (tracemalloc_start(nframe) < 0) {
Victor Stinner3728d6c2013-11-23 12:37:20 +01001533 return NULL;
1534 }
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001535 Py_RETURN_NONE;
1536}
1537
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001538
Serhiy Storchakab451f912017-02-04 12:18:38 +02001539/*[clinic input]
1540_tracemalloc.stop
Victor Stinnere492ae52016-03-22 12:58:23 +01001541
Serhiy Storchakab451f912017-02-04 12:18:38 +02001542Stop tracing Python memory allocations.
1543
1544Also clear traces of memory blocks allocated by Python.
1545[clinic start generated code]*/
1546
1547static PyObject *
1548_tracemalloc_stop_impl(PyObject *module)
1549/*[clinic end generated code: output=c3c42ae03e3955cd input=7478f075e51dae18]*/
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001550{
1551 tracemalloc_stop();
1552 Py_RETURN_NONE;
1553}
1554
Victor Stinnere492ae52016-03-22 12:58:23 +01001555
Serhiy Storchakab451f912017-02-04 12:18:38 +02001556/*[clinic input]
1557_tracemalloc.get_traceback_limit
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001558
Serhiy Storchakab451f912017-02-04 12:18:38 +02001559Get the maximum number of frames stored in the traceback of a trace.
1560
1561By default, a trace of an allocated memory block only stores
1562the most recent frame: the limit is 1.
1563[clinic start generated code]*/
1564
1565static PyObject *
1566_tracemalloc_get_traceback_limit_impl(PyObject *module)
1567/*[clinic end generated code: output=d556d9306ba95567 input=da3cd977fc68ae3b]*/
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001568{
Victor Stinner9e00e802018-10-25 13:31:16 +02001569 return PyLong_FromLong(_Py_tracemalloc_config.max_nframe);
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001570}
1571
Victor Stinnere492ae52016-03-22 12:58:23 +01001572
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001573
Serhiy Storchakab451f912017-02-04 12:18:38 +02001574/*[clinic input]
1575_tracemalloc.get_tracemalloc_memory
1576
1577Get the memory usage in bytes of the tracemalloc module.
1578
1579This memory is used internally to trace memory allocations.
1580[clinic start generated code]*/
1581
1582static PyObject *
1583_tracemalloc_get_tracemalloc_memory_impl(PyObject *module)
1584/*[clinic end generated code: output=e3f14e280a55f5aa input=5d919c0f4d5132ad]*/
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001585{
1586 size_t size;
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001587
1588 size = _Py_hashtable_size(tracemalloc_tracebacks);
1589 size += _Py_hashtable_size(tracemalloc_filenames);
1590
1591 TABLES_LOCK();
1592 size += _Py_hashtable_size(tracemalloc_traces);
1593 TABLES_UNLOCK();
1594
Serhiy Storchakab451f912017-02-04 12:18:38 +02001595 return PyLong_FromSize_t(size);
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001596}
1597
Victor Stinnere492ae52016-03-22 12:58:23 +01001598
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001599
Serhiy Storchakab451f912017-02-04 12:18:38 +02001600/*[clinic input]
1601_tracemalloc.get_traced_memory
1602
1603Get the current size and peak size of memory blocks traced by tracemalloc.
1604
1605Returns a tuple: (current: int, peak: int).
1606[clinic start generated code]*/
1607
1608static PyObject *
1609_tracemalloc_get_traced_memory_impl(PyObject *module)
1610/*[clinic end generated code: output=5b167189adb9e782 input=61ddb5478400ff66]*/
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001611{
Victor Stinner3c0481d2013-11-27 21:39:49 +01001612 Py_ssize_t size, peak_size;
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001613
Victor Stinner9e00e802018-10-25 13:31:16 +02001614 if (!_Py_tracemalloc_config.tracing)
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001615 return Py_BuildValue("ii", 0, 0);
1616
1617 TABLES_LOCK();
1618 size = tracemalloc_traced_memory;
Victor Stinner3c0481d2013-11-27 21:39:49 +01001619 peak_size = tracemalloc_peak_traced_memory;
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001620 TABLES_UNLOCK();
1621
Serhiy Storchakab451f912017-02-04 12:18:38 +02001622 return Py_BuildValue("nn", size, peak_size);
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001623}
1624
Victor Stinnere492ae52016-03-22 12:58:23 +01001625
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001626static PyMethodDef module_methods[] = {
Serhiy Storchakab451f912017-02-04 12:18:38 +02001627 _TRACEMALLOC_IS_TRACING_METHODDEF
1628 _TRACEMALLOC_CLEAR_TRACES_METHODDEF
1629 _TRACEMALLOC__GET_TRACES_METHODDEF
1630 _TRACEMALLOC__GET_OBJECT_TRACEBACK_METHODDEF
1631 _TRACEMALLOC_START_METHODDEF
1632 _TRACEMALLOC_STOP_METHODDEF
1633 _TRACEMALLOC_GET_TRACEBACK_LIMIT_METHODDEF
1634 _TRACEMALLOC_GET_TRACEMALLOC_MEMORY_METHODDEF
1635 _TRACEMALLOC_GET_TRACED_MEMORY_METHODDEF
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001636 /* sentinel */
1637 {NULL, NULL}
1638};
1639
1640PyDoc_STRVAR(module_doc,
1641"Debug module to trace memory blocks allocated by Python.");
1642
1643static struct PyModuleDef module_def = {
1644 PyModuleDef_HEAD_INIT,
1645 "_tracemalloc",
1646 module_doc,
1647 0, /* non-negative size to be able to unload the module */
1648 module_methods,
1649 NULL,
1650};
1651
1652PyMODINIT_FUNC
1653PyInit__tracemalloc(void)
1654{
1655 PyObject *m;
1656 m = PyModule_Create(&module_def);
1657 if (m == NULL)
1658 return NULL;
1659
Brandt Bucherd51a3632019-11-20 02:00:31 -08001660 if (tracemalloc_init() < 0) {
1661 Py_DECREF(m);
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001662 return NULL;
Brandt Bucherd51a3632019-11-20 02:00:31 -08001663 }
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001664
1665 return m;
1666}
1667
Victor Stinnere492ae52016-03-22 12:58:23 +01001668
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001669int
Victor Stinnera7368ac2017-11-15 18:11:45 -08001670_PyTraceMalloc_Init(int nframe)
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001671{
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001672 assert(PyGILState_Check());
Victor Stinnera7368ac2017-11-15 18:11:45 -08001673 if (nframe == 0) {
1674 return 0;
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001675 }
Victor Stinnerf28ce602013-11-27 22:27:13 +01001676 return tracemalloc_start(nframe);
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001677}
1678
Victor Stinnere492ae52016-03-22 12:58:23 +01001679
Victor Stinnerbe0708f2013-12-01 10:03:26 +01001680void
1681_PyTraceMalloc_Fini(void)
1682{
Victor Stinnerbe0708f2013-12-01 10:03:26 +01001683 assert(PyGILState_Check());
Victor Stinnerbe0708f2013-12-01 10:03:26 +01001684 tracemalloc_deinit();
1685}
Victor Stinner10b73e12016-03-22 13:39:05 +01001686
1687int
Victor Stinner5ea4c062017-06-20 17:46:36 +02001688PyTraceMalloc_Track(unsigned int domain, uintptr_t ptr,
1689 size_t size)
Victor Stinner10b73e12016-03-22 13:39:05 +01001690{
1691 int res;
Victor Stinner10b73e12016-03-22 13:39:05 +01001692 PyGILState_STATE gil_state;
Victor Stinner10b73e12016-03-22 13:39:05 +01001693
Victor Stinner9e00e802018-10-25 13:31:16 +02001694 if (!_Py_tracemalloc_config.tracing) {
Victor Stinner10b73e12016-03-22 13:39:05 +01001695 /* tracemalloc is not tracing: do nothing */
1696 return -2;
1697 }
1698
Victor Stinner10b73e12016-03-22 13:39:05 +01001699 gil_state = PyGILState_Ensure();
Victor Stinner10b73e12016-03-22 13:39:05 +01001700
1701 TABLES_LOCK();
1702 res = tracemalloc_add_trace(domain, ptr, size);
1703 TABLES_UNLOCK();
1704
Victor Stinner10b73e12016-03-22 13:39:05 +01001705 PyGILState_Release(gil_state);
Victor Stinner10b73e12016-03-22 13:39:05 +01001706 return res;
1707}
1708
1709
1710int
Victor Stinner5ea4c062017-06-20 17:46:36 +02001711PyTraceMalloc_Untrack(unsigned int domain, uintptr_t ptr)
Victor Stinner10b73e12016-03-22 13:39:05 +01001712{
Victor Stinner9e00e802018-10-25 13:31:16 +02001713 if (!_Py_tracemalloc_config.tracing) {
Victor Stinner10b73e12016-03-22 13:39:05 +01001714 /* tracemalloc is not tracing: do nothing */
1715 return -2;
1716 }
1717
1718 TABLES_LOCK();
1719 tracemalloc_remove_trace(domain, ptr);
1720 TABLES_UNLOCK();
1721
1722 return 0;
1723}
1724
1725
Victor Stinner9e00e802018-10-25 13:31:16 +02001726/* If the object memory block is already traced, update its trace
1727 with the current Python traceback.
1728
1729 Do nothing if tracemalloc is not tracing memory allocations
1730 or if the object memory block is not already traced. */
1731int
1732_PyTraceMalloc_NewReference(PyObject *op)
1733{
1734 assert(PyGILState_Check());
1735
1736 if (!_Py_tracemalloc_config.tracing) {
1737 /* tracemalloc is not tracing: do nothing */
1738 return -1;
1739 }
1740
1741 uintptr_t ptr;
1742 PyTypeObject *type = Py_TYPE(op);
1743 if (PyType_IS_GC(type)) {
1744 ptr = (uintptr_t)((char *)op - sizeof(PyGC_Head));
1745 }
1746 else {
1747 ptr = (uintptr_t)op;
1748 }
1749
1750 _Py_hashtable_entry_t* entry;
1751 int res = -1;
1752
1753 TABLES_LOCK();
1754 if (_Py_tracemalloc_config.use_domain) {
1755 pointer_t key = {ptr, DEFAULT_DOMAIN};
1756 entry = _Py_HASHTABLE_GET_ENTRY(tracemalloc_traces, key);
1757 }
1758 else {
1759 entry = _Py_HASHTABLE_GET_ENTRY(tracemalloc_traces, ptr);
1760 }
1761
1762 if (entry != NULL) {
1763 /* update the traceback of the memory block */
1764 traceback_t *traceback = traceback_new();
1765 if (traceback != NULL) {
1766 trace_t trace;
1767 _Py_HASHTABLE_ENTRY_READ_DATA(tracemalloc_traces, entry, trace);
1768 trace.traceback = traceback;
1769 _Py_HASHTABLE_ENTRY_WRITE_DATA(tracemalloc_traces, entry, trace);
1770 res = 0;
1771 }
1772 }
1773 /* else: cannot track the object, its memory block size is unknown */
1774 TABLES_UNLOCK();
1775
1776 return res;
1777}
1778
1779
Victor Stinner10b73e12016-03-22 13:39:05 +01001780PyObject*
Victor Stinner5ea4c062017-06-20 17:46:36 +02001781_PyTraceMalloc_GetTraceback(unsigned int domain, uintptr_t ptr)
Victor Stinner10b73e12016-03-22 13:39:05 +01001782{
1783 traceback_t *traceback;
1784
1785 traceback = tracemalloc_get_traceback(domain, ptr);
1786 if (traceback == NULL)
1787 Py_RETURN_NONE;
1788
1789 return traceback_to_pyobject(traceback, NULL);
1790}