blob: cbcf55f817435f5e173da494e98a5f3c706a0af2 [file] [log] [blame]
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001#include "Python.h"
Victor Stinnered488662019-05-20 00:14:57 +02002#include "pycore_traceback.h"
Victor Stinnered3b0bc2013-11-23 12:27:24 +01003#include "hashtable.h"
4#include "frameobject.h"
5#include "pythread.h"
6#include "osdefs.h"
7
Serhiy Storchakab451f912017-02-04 12:18:38 +02008#include "clinic/_tracemalloc.c.h"
9/*[clinic input]
10module _tracemalloc
11[clinic start generated code]*/
12/*[clinic end generated code: output=da39a3ee5e6b4b0d input=708a98302fc46e5f]*/
13
Victor Stinnered3b0bc2013-11-23 12:27:24 +010014/* Trace memory blocks allocated by PyMem_RawMalloc() */
15#define TRACE_RAW_MALLOC
16
17/* Forward declaration */
18static void tracemalloc_stop(void);
Victor Stinnered3b0bc2013-11-23 12:27:24 +010019static void* raw_malloc(size_t size);
20static void raw_free(void *ptr);
21
22#ifdef Py_DEBUG
23# define TRACE_DEBUG
24#endif
25
Victor Stinnered3b0bc2013-11-23 12:27:24 +010026/* Protected by the GIL */
27static struct {
Victor Stinnerd8f0d922014-06-02 21:57:10 +020028 PyMemAllocatorEx mem;
29 PyMemAllocatorEx raw;
30 PyMemAllocatorEx obj;
Victor Stinnered3b0bc2013-11-23 12:27:24 +010031} allocators;
32
Victor Stinnered3b0bc2013-11-23 12:27:24 +010033
Antoine Pitroua6a4dc82017-09-07 18:56:24 +020034#if defined(TRACE_RAW_MALLOC)
Victor Stinnered3b0bc2013-11-23 12:27:24 +010035/* This lock is needed because tracemalloc_free() is called without
36 the GIL held from PyMem_RawFree(). It cannot acquire the lock because it
37 would introduce a deadlock in PyThreadState_DeleteCurrent(). */
38static PyThread_type_lock tables_lock;
39# define TABLES_LOCK() PyThread_acquire_lock(tables_lock, 1)
40# define TABLES_UNLOCK() PyThread_release_lock(tables_lock)
41#else
42 /* variables are protected by the GIL */
43# define TABLES_LOCK()
44# define TABLES_UNLOCK()
45#endif
46
Victor Stinnere492ae52016-03-22 12:58:23 +010047
48#define DEFAULT_DOMAIN 0
49
Victor Stinnere492ae52016-03-22 12:58:23 +010050/* Pack the frame_t structure to reduce the memory footprint. */
51typedef struct
52#ifdef __GNUC__
53__attribute__((packed))
54#endif
55{
Benjamin Petersonca470632016-09-06 13:47:26 -070056 uintptr_t ptr;
Victor Stinner5ea4c062017-06-20 17:46:36 +020057 unsigned int domain;
Victor Stinnere492ae52016-03-22 12:58:23 +010058} pointer_t;
59
Victor Stinnered3b0bc2013-11-23 12:27:24 +010060/* Pack the frame_t structure to reduce the memory footprint on 64-bit
Victor Stinnere492ae52016-03-22 12:58:23 +010061 architectures: 12 bytes instead of 16. */
Victor Stinnered3b0bc2013-11-23 12:27:24 +010062typedef struct
63#ifdef __GNUC__
64__attribute__((packed))
Victor Stinnerdd382ef2014-02-01 03:43:58 +010065#elif defined(_MSC_VER)
Segev Finer39243772017-07-25 11:47:43 +030066#pragma pack(push, 4)
Victor Stinnered3b0bc2013-11-23 12:27:24 +010067#endif
68{
Victor Stinner7105e9f2016-03-15 14:28:04 +010069 /* filename cannot be NULL: "<unknown>" is used if the Python frame
70 filename is NULL */
Victor Stinnered3b0bc2013-11-23 12:27:24 +010071 PyObject *filename;
Victor Stinner95283342016-03-15 21:57:02 +010072 unsigned int lineno;
Victor Stinnered3b0bc2013-11-23 12:27:24 +010073} frame_t;
Segev Finer39243772017-07-25 11:47:43 +030074#ifdef _MSC_VER
75#pragma pack(pop)
76#endif
Victor Stinnered3b0bc2013-11-23 12:27:24 +010077
Victor Stinnere492ae52016-03-22 12:58:23 +010078
Victor Stinnered3b0bc2013-11-23 12:27:24 +010079typedef struct {
80 Py_uhash_t hash;
81 int nframe;
82 frame_t frames[1];
83} traceback_t;
84
85#define TRACEBACK_SIZE(NFRAME) \
86 (sizeof(traceback_t) + sizeof(frame_t) * (NFRAME - 1))
Victor Stinnerf28ce602013-11-27 22:27:13 +010087
88#define MAX_NFRAME \
Victor Stinner52aee852014-08-16 15:44:02 +020089 ((INT_MAX - (int)sizeof(traceback_t)) / (int)sizeof(frame_t) + 1)
Victor Stinnered3b0bc2013-11-23 12:27:24 +010090
Victor Stinnere492ae52016-03-22 12:58:23 +010091
Victor Stinnered3b0bc2013-11-23 12:27:24 +010092static PyObject *unknown_filename = NULL;
93static traceback_t tracemalloc_empty_traceback;
94
Victor Stinner7a5be142013-11-26 01:06:02 +010095/* Trace of a memory block */
Victor Stinnered3b0bc2013-11-23 12:27:24 +010096typedef struct {
Victor Stinner7a5be142013-11-26 01:06:02 +010097 /* Size of the memory block in bytes */
Victor Stinnered3b0bc2013-11-23 12:27:24 +010098 size_t size;
Victor Stinner7a5be142013-11-26 01:06:02 +010099
100 /* Traceback where the memory block was allocated */
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100101 traceback_t *traceback;
102} trace_t;
103
Victor Stinnere492ae52016-03-22 12:58:23 +0100104
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100105/* Size in bytes of currently traced memory.
106 Protected by TABLES_LOCK(). */
107static size_t tracemalloc_traced_memory = 0;
108
Victor Stinner3c0481d2013-11-27 21:39:49 +0100109/* Peak size in bytes of traced memory.
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100110 Protected by TABLES_LOCK(). */
Victor Stinner3c0481d2013-11-27 21:39:49 +0100111static size_t tracemalloc_peak_traced_memory = 0;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100112
Serhiy Storchaka56a6d852014-12-01 18:28:43 +0200113/* Hash table used as a set to intern filenames:
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100114 PyObject* => PyObject*.
115 Protected by the GIL */
116static _Py_hashtable_t *tracemalloc_filenames = NULL;
117
Victor Stinnerf28ce602013-11-27 22:27:13 +0100118/* Buffer to store a new traceback in traceback_new().
119 Protected by the GIL. */
120static traceback_t *tracemalloc_traceback = NULL;
121
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100122/* Hash table used as a set to intern tracebacks:
123 traceback_t* => traceback_t*
124 Protected by the GIL */
125static _Py_hashtable_t *tracemalloc_tracebacks = NULL;
126
127/* pointer (void*) => trace (trace_t).
128 Protected by TABLES_LOCK(). */
129static _Py_hashtable_t *tracemalloc_traces = NULL;
130
Victor Stinnere492ae52016-03-22 12:58:23 +0100131
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100132#ifdef TRACE_DEBUG
133static void
134tracemalloc_error(const char *format, ...)
135{
136 va_list ap;
137 fprintf(stderr, "tracemalloc: ");
138 va_start(ap, format);
139 vfprintf(stderr, format, ap);
140 va_end(ap);
141 fprintf(stderr, "\n");
142 fflush(stderr);
143}
144#endif
145
Victor Stinnere492ae52016-03-22 12:58:23 +0100146
Antoine Pitroua6a4dc82017-09-07 18:56:24 +0200147#if defined(TRACE_RAW_MALLOC)
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100148#define REENTRANT_THREADLOCAL
149
Masayuki Yamamoto731e1892017-10-06 19:41:34 +0900150static Py_tss_t tracemalloc_reentrant_key = Py_tss_NEEDS_INIT;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100151
152/* Any non-NULL pointer can be used */
153#define REENTRANT Py_True
154
155static int
156get_reentrant(void)
157{
Victor Stinner4a066472016-03-22 17:45:09 +0100158 void *ptr;
159
Masayuki Yamamoto731e1892017-10-06 19:41:34 +0900160 assert(PyThread_tss_is_created(&tracemalloc_reentrant_key));
161 ptr = PyThread_tss_get(&tracemalloc_reentrant_key);
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100162 if (ptr != NULL) {
163 assert(ptr == REENTRANT);
164 return 1;
165 }
166 else
167 return 0;
168}
169
170static void
171set_reentrant(int reentrant)
172{
Victor Stinner2ead3d22013-11-26 01:08:53 +0100173 assert(reentrant == 0 || reentrant == 1);
Masayuki Yamamoto731e1892017-10-06 19:41:34 +0900174 assert(PyThread_tss_is_created(&tracemalloc_reentrant_key));
Victor Stinner4a066472016-03-22 17:45:09 +0100175
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100176 if (reentrant) {
Victor Stinner0cfc0582016-03-22 17:40:07 +0100177 assert(!get_reentrant());
Masayuki Yamamoto731e1892017-10-06 19:41:34 +0900178 PyThread_tss_set(&tracemalloc_reentrant_key, REENTRANT);
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100179 }
180 else {
Victor Stinner0cfc0582016-03-22 17:40:07 +0100181 assert(get_reentrant());
Masayuki Yamamoto731e1892017-10-06 19:41:34 +0900182 PyThread_tss_set(&tracemalloc_reentrant_key, NULL);
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100183 }
184}
185
186#else
187
Antoine Pitroua6a4dc82017-09-07 18:56:24 +0200188/* TRACE_RAW_MALLOC not defined: variable protected by the GIL */
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100189static int tracemalloc_reentrant = 0;
190
191static int
192get_reentrant(void)
193{
194 return tracemalloc_reentrant;
195}
196
197static void
198set_reentrant(int reentrant)
199{
Victor Stinnerd5871e62016-03-23 00:17:04 +0100200 assert(reentrant != tracemalloc_reentrant);
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100201 tracemalloc_reentrant = reentrant;
202}
203#endif
204
Victor Stinnere492ae52016-03-22 12:58:23 +0100205
Victor Stinner285cf0a2016-03-21 22:00:58 +0100206static Py_uhash_t
Victor Stinner5dacbd42016-03-23 09:52:13 +0100207hashtable_hash_pyobject(_Py_hashtable_t *ht, const void *pkey)
Victor Stinner51b846c2016-03-18 21:52:22 +0100208{
Victor Stinner285cf0a2016-03-21 22:00:58 +0100209 PyObject *obj;
210
Victor Stinner5dacbd42016-03-23 09:52:13 +0100211 _Py_HASHTABLE_READ_KEY(ht, pkey, obj);
Victor Stinner285cf0a2016-03-21 22:00:58 +0100212 return PyObject_Hash(obj);
213}
214
Victor Stinnere492ae52016-03-22 12:58:23 +0100215
Victor Stinner285cf0a2016-03-21 22:00:58 +0100216static int
Victor Stinner5dacbd42016-03-23 09:52:13 +0100217hashtable_compare_unicode(_Py_hashtable_t *ht, const void *pkey,
Victor Stinner285cf0a2016-03-21 22:00:58 +0100218 const _Py_hashtable_entry_t *entry)
219{
Victor Stinnere492ae52016-03-22 12:58:23 +0100220 PyObject *key1, *key2;
Victor Stinner285cf0a2016-03-21 22:00:58 +0100221
Victor Stinner5dacbd42016-03-23 09:52:13 +0100222 _Py_HASHTABLE_READ_KEY(ht, pkey, key1);
223 _Py_HASHTABLE_ENTRY_READ_KEY(ht, entry, key2);
Victor Stinner285cf0a2016-03-21 22:00:58 +0100224
Victor Stinnere492ae52016-03-22 12:58:23 +0100225 if (key1 != NULL && key2 != NULL)
226 return (PyUnicode_Compare(key1, key2) == 0);
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100227 else
Victor Stinnere492ae52016-03-22 12:58:23 +0100228 return key1 == key2;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100229}
230
Victor Stinnere492ae52016-03-22 12:58:23 +0100231
232static Py_uhash_t
Victor Stinner5dacbd42016-03-23 09:52:13 +0100233hashtable_hash_pointer_t(_Py_hashtable_t *ht, const void *pkey)
Victor Stinnere492ae52016-03-22 12:58:23 +0100234{
235 pointer_t ptr;
236 Py_uhash_t hash;
237
Victor Stinner5dacbd42016-03-23 09:52:13 +0100238 _Py_HASHTABLE_READ_KEY(ht, pkey, ptr);
Victor Stinnere492ae52016-03-22 12:58:23 +0100239
240 hash = (Py_uhash_t)_Py_HashPointer((void*)ptr.ptr);
241 hash ^= ptr.domain;
242 return hash;
243}
244
245
doko@ubuntu.combc731502016-05-18 01:06:01 +0200246static int
Victor Stinner5dacbd42016-03-23 09:52:13 +0100247hashtable_compare_pointer_t(_Py_hashtable_t *ht, const void *pkey,
Victor Stinnere492ae52016-03-22 12:58:23 +0100248 const _Py_hashtable_entry_t *entry)
249{
250 pointer_t ptr1, ptr2;
251
Victor Stinner5dacbd42016-03-23 09:52:13 +0100252 _Py_HASHTABLE_READ_KEY(ht, pkey, ptr1);
253 _Py_HASHTABLE_ENTRY_READ_KEY(ht, entry, ptr2);
Victor Stinnere492ae52016-03-22 12:58:23 +0100254
255 /* compare pointer before domain, because pointer is more likely to be
256 different */
257 return (ptr1.ptr == ptr2.ptr && ptr1.domain == ptr2.domain);
258
259}
260
261
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100262static _Py_hashtable_t *
Victor Stinner285cf0a2016-03-21 22:00:58 +0100263hashtable_new(size_t key_size, size_t data_size,
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100264 _Py_hashtable_hash_func hash_func,
265 _Py_hashtable_compare_func compare_func)
266{
Victor Stinnerc9553872016-03-22 12:13:01 +0100267 _Py_hashtable_allocator_t hashtable_alloc = {malloc, free};
Victor Stinner285cf0a2016-03-21 22:00:58 +0100268 return _Py_hashtable_new_full(key_size, data_size, 0,
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100269 hash_func, compare_func,
Victor Stinnerc9553872016-03-22 12:13:01 +0100270 &hashtable_alloc);
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100271}
272
Victor Stinnere492ae52016-03-22 12:58:23 +0100273
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100274static void*
275raw_malloc(size_t size)
276{
277 return allocators.raw.malloc(allocators.raw.ctx, size);
278}
279
280static void
281raw_free(void *ptr)
282{
283 allocators.raw.free(allocators.raw.ctx, ptr);
284}
285
Victor Stinnere492ae52016-03-22 12:58:23 +0100286
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100287static Py_uhash_t
Victor Stinner5dacbd42016-03-23 09:52:13 +0100288hashtable_hash_traceback(_Py_hashtable_t *ht, const void *pkey)
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100289{
Victor Stinnerb32a7ed2016-03-21 23:05:08 +0100290 traceback_t *traceback;
Victor Stinner285cf0a2016-03-21 22:00:58 +0100291
Victor Stinner5dacbd42016-03-23 09:52:13 +0100292 _Py_HASHTABLE_READ_KEY(ht, pkey, traceback);
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100293 return traceback->hash;
294}
295
Victor Stinnere492ae52016-03-22 12:58:23 +0100296
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100297static int
Victor Stinner5dacbd42016-03-23 09:52:13 +0100298hashtable_compare_traceback(_Py_hashtable_t *ht, const void *pkey,
299 const _Py_hashtable_entry_t *entry)
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100300{
Victor Stinner285cf0a2016-03-21 22:00:58 +0100301 traceback_t *traceback1, *traceback2;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100302 const frame_t *frame1, *frame2;
303 int i;
304
Victor Stinner5dacbd42016-03-23 09:52:13 +0100305 _Py_HASHTABLE_READ_KEY(ht, pkey, traceback1);
306 _Py_HASHTABLE_ENTRY_READ_KEY(ht, entry, traceback2);
Victor Stinner285cf0a2016-03-21 22:00:58 +0100307
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100308 if (traceback1->nframe != traceback2->nframe)
309 return 0;
310
311 for (i=0; i < traceback1->nframe; i++) {
312 frame1 = &traceback1->frames[i];
313 frame2 = &traceback2->frames[i];
314
315 if (frame1->lineno != frame2->lineno)
316 return 0;
317
318 if (frame1->filename != frame2->filename) {
319 assert(PyUnicode_Compare(frame1->filename, frame2->filename) != 0);
320 return 0;
321 }
322 }
323 return 1;
324}
325
Victor Stinnere492ae52016-03-22 12:58:23 +0100326
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100327static void
328tracemalloc_get_frame(PyFrameObject *pyframe, frame_t *frame)
329{
330 PyCodeObject *code;
331 PyObject *filename;
332 _Py_hashtable_entry_t *entry;
Victor Stinner95283342016-03-15 21:57:02 +0100333 int lineno;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100334
335 frame->filename = unknown_filename;
Victor Stinner95283342016-03-15 21:57:02 +0100336 lineno = PyFrame_GetLineNumber(pyframe);
337 if (lineno < 0)
338 lineno = 0;
339 frame->lineno = (unsigned int)lineno;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100340
341 code = pyframe->f_code;
342 if (code == NULL) {
343#ifdef TRACE_DEBUG
Victor Stinner4dc74202013-11-26 01:18:52 +0100344 tracemalloc_error("failed to get the code object of the frame");
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100345#endif
346 return;
347 }
348
349 if (code->co_filename == NULL) {
350#ifdef TRACE_DEBUG
351 tracemalloc_error("failed to get the filename of the code object");
352#endif
353 return;
354 }
355
356 filename = code->co_filename;
357 assert(filename != NULL);
358 if (filename == NULL)
359 return;
360
361 if (!PyUnicode_Check(filename)) {
362#ifdef TRACE_DEBUG
Martin Panter6245cb32016-04-15 02:14:19 +0000363 tracemalloc_error("filename is not a unicode string");
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100364#endif
365 return;
366 }
367 if (!PyUnicode_IS_READY(filename)) {
368 /* Don't make a Unicode string ready to avoid reentrant calls
369 to tracemalloc_malloc() or tracemalloc_realloc() */
370#ifdef TRACE_DEBUG
371 tracemalloc_error("filename is not a ready unicode string");
372#endif
373 return;
374 }
375
376 /* intern the filename */
Victor Stinner285cf0a2016-03-21 22:00:58 +0100377 entry = _Py_HASHTABLE_GET_ENTRY(tracemalloc_filenames, filename);
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100378 if (entry != NULL) {
Victor Stinner5dacbd42016-03-23 09:52:13 +0100379 _Py_HASHTABLE_ENTRY_READ_KEY(tracemalloc_filenames, entry, filename);
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100380 }
381 else {
382 /* tracemalloc_filenames is responsible to keep a reference
383 to the filename */
384 Py_INCREF(filename);
Victor Stinner285cf0a2016-03-21 22:00:58 +0100385 if (_Py_HASHTABLE_SET_NODATA(tracemalloc_filenames, filename) < 0) {
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100386 Py_DECREF(filename);
387#ifdef TRACE_DEBUG
388 tracemalloc_error("failed to intern the filename");
389#endif
390 return;
391 }
392 }
393
394 /* the tracemalloc_filenames table keeps a reference to the filename */
395 frame->filename = filename;
396}
397
Victor Stinnere492ae52016-03-22 12:58:23 +0100398
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100399static Py_uhash_t
400traceback_hash(traceback_t *traceback)
401{
402 /* code based on tuplehash() of Objects/tupleobject.c */
Victor Stinner4d8c29c2013-12-16 23:05:13 +0100403 Py_uhash_t x, y; /* Unsigned for defined overflow behavior. */
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100404 int len = traceback->nframe;
405 Py_uhash_t mult = _PyHASH_MULTIPLIER;
406 frame_t *frame;
407
408 x = 0x345678UL;
409 frame = traceback->frames;
410 while (--len >= 0) {
Victor Stinner4d8c29c2013-12-16 23:05:13 +0100411 y = (Py_uhash_t)PyObject_Hash(frame->filename);
412 y ^= (Py_uhash_t)frame->lineno;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100413 frame++;
414
415 x = (x ^ y) * mult;
416 /* the cast might truncate len; that doesn't change hash stability */
Victor Stinner4d8c29c2013-12-16 23:05:13 +0100417 mult += (Py_uhash_t)(82520UL + len + len);
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100418 }
419 x += 97531UL;
420 return x;
421}
422
Victor Stinnere492ae52016-03-22 12:58:23 +0100423
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100424static void
425traceback_get_frames(traceback_t *traceback)
426{
427 PyThreadState *tstate;
428 PyFrameObject *pyframe;
429
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100430 tstate = PyGILState_GetThisThreadState();
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100431 if (tstate == NULL) {
432#ifdef TRACE_DEBUG
433 tracemalloc_error("failed to get the current thread state");
434#endif
435 return;
436 }
437
438 for (pyframe = tstate->frame; pyframe != NULL; pyframe = pyframe->f_back) {
439 tracemalloc_get_frame(pyframe, &traceback->frames[traceback->nframe]);
440 assert(traceback->frames[traceback->nframe].filename != NULL);
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100441 traceback->nframe++;
Victor Stinner9e00e802018-10-25 13:31:16 +0200442 if (traceback->nframe == _Py_tracemalloc_config.max_nframe)
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100443 break;
444 }
445}
446
Victor Stinnere492ae52016-03-22 12:58:23 +0100447
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100448static traceback_t *
449traceback_new(void)
450{
Victor Stinnerf28ce602013-11-27 22:27:13 +0100451 traceback_t *traceback;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100452 _Py_hashtable_entry_t *entry;
453
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100454 assert(PyGILState_Check());
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100455
456 /* get frames */
Victor Stinnerf28ce602013-11-27 22:27:13 +0100457 traceback = tracemalloc_traceback;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100458 traceback->nframe = 0;
459 traceback_get_frames(traceback);
460 if (traceback->nframe == 0)
461 return &tracemalloc_empty_traceback;
462 traceback->hash = traceback_hash(traceback);
463
464 /* intern the traceback */
Victor Stinner285cf0a2016-03-21 22:00:58 +0100465 entry = _Py_HASHTABLE_GET_ENTRY(tracemalloc_tracebacks, traceback);
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100466 if (entry != NULL) {
Victor Stinner5dacbd42016-03-23 09:52:13 +0100467 _Py_HASHTABLE_ENTRY_READ_KEY(tracemalloc_tracebacks, entry, traceback);
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100468 }
469 else {
470 traceback_t *copy;
471 size_t traceback_size;
472
473 traceback_size = TRACEBACK_SIZE(traceback->nframe);
474
475 copy = raw_malloc(traceback_size);
476 if (copy == NULL) {
477#ifdef TRACE_DEBUG
478 tracemalloc_error("failed to intern the traceback: malloc failed");
479#endif
480 return NULL;
481 }
482 memcpy(copy, traceback, traceback_size);
483
Victor Stinner285cf0a2016-03-21 22:00:58 +0100484 if (_Py_HASHTABLE_SET_NODATA(tracemalloc_tracebacks, copy) < 0) {
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100485 raw_free(copy);
486#ifdef TRACE_DEBUG
487 tracemalloc_error("failed to intern the traceback: putdata failed");
488#endif
489 return NULL;
490 }
491 traceback = copy;
492 }
493 return traceback;
494}
495
Victor Stinnere492ae52016-03-22 12:58:23 +0100496
Victor Stinner5e14a382016-03-23 22:03:55 +0100497static int
498tracemalloc_use_domain_cb(_Py_hashtable_t *old_traces,
499 _Py_hashtable_entry_t *entry, void *user_data)
500{
Benjamin Petersonca470632016-09-06 13:47:26 -0700501 uintptr_t ptr;
Victor Stinner5e14a382016-03-23 22:03:55 +0100502 pointer_t key;
503 _Py_hashtable_t *new_traces = (_Py_hashtable_t *)user_data;
504 const void *pdata = _Py_HASHTABLE_ENTRY_PDATA(old_traces, entry);
505
506 _Py_HASHTABLE_ENTRY_READ_KEY(old_traces, entry, ptr);
507 key.ptr = ptr;
508 key.domain = DEFAULT_DOMAIN;
509
510 return _Py_hashtable_set(new_traces,
511 sizeof(key), &key,
512 old_traces->data_size, pdata);
513}
514
515
Benjamin Petersonca470632016-09-06 13:47:26 -0700516/* Convert tracemalloc_traces from compact key (uintptr_t) to pointer_t key.
Victor Stinner5e14a382016-03-23 22:03:55 +0100517 * Return 0 on success, -1 on error. */
518static int
519tracemalloc_use_domain(void)
520{
521 _Py_hashtable_t *new_traces = NULL;
522
Victor Stinner9e00e802018-10-25 13:31:16 +0200523 assert(!_Py_tracemalloc_config.use_domain);
Victor Stinner5e14a382016-03-23 22:03:55 +0100524
525 new_traces = hashtable_new(sizeof(pointer_t),
526 sizeof(trace_t),
527 hashtable_hash_pointer_t,
528 hashtable_compare_pointer_t);
529 if (new_traces == NULL) {
530 return -1;
531 }
532
533 if (_Py_hashtable_foreach(tracemalloc_traces, tracemalloc_use_domain_cb,
534 new_traces) < 0)
535 {
536 _Py_hashtable_destroy(new_traces);
537 return -1;
538 }
539
540 _Py_hashtable_destroy(tracemalloc_traces);
541 tracemalloc_traces = new_traces;
542
Victor Stinner9e00e802018-10-25 13:31:16 +0200543 _Py_tracemalloc_config.use_domain = 1;
Victor Stinner5e14a382016-03-23 22:03:55 +0100544
545 return 0;
546}
547
548
Victor Stinnere492ae52016-03-22 12:58:23 +0100549static void
Victor Stinner5ea4c062017-06-20 17:46:36 +0200550tracemalloc_remove_trace(unsigned int domain, uintptr_t ptr)
Victor Stinnere492ae52016-03-22 12:58:23 +0100551{
552 trace_t trace;
553 int removed;
554
Victor Stinner9e00e802018-10-25 13:31:16 +0200555 assert(_Py_tracemalloc_config.tracing);
Victor Stinner10b73e12016-03-22 13:39:05 +0100556
Victor Stinner9e00e802018-10-25 13:31:16 +0200557 if (_Py_tracemalloc_config.use_domain) {
Victor Stinnere492ae52016-03-22 12:58:23 +0100558 pointer_t key = {ptr, domain};
559 removed = _Py_HASHTABLE_POP(tracemalloc_traces, key, trace);
560 }
561 else {
562 removed = _Py_HASHTABLE_POP(tracemalloc_traces, ptr, trace);
563 }
564 if (!removed) {
565 return;
566 }
567
568 assert(tracemalloc_traced_memory >= trace.size);
569 tracemalloc_traced_memory -= trace.size;
570}
571
572#define REMOVE_TRACE(ptr) \
Benjamin Petersonca470632016-09-06 13:47:26 -0700573 tracemalloc_remove_trace(DEFAULT_DOMAIN, (uintptr_t)(ptr))
Victor Stinnere492ae52016-03-22 12:58:23 +0100574
575
Victor Stinner52968672013-11-24 11:37:15 +0100576static int
Victor Stinner5ea4c062017-06-20 17:46:36 +0200577tracemalloc_add_trace(unsigned int domain, uintptr_t ptr,
Victor Stinner10b73e12016-03-22 13:39:05 +0100578 size_t size)
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100579{
Victor Stinnerca79ccd2016-03-23 09:38:54 +0100580 pointer_t key = {ptr, domain};
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100581 traceback_t *traceback;
582 trace_t trace;
Victor Stinnerca79ccd2016-03-23 09:38:54 +0100583 _Py_hashtable_entry_t* entry;
Victor Stinner52968672013-11-24 11:37:15 +0100584 int res;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100585
Victor Stinner9e00e802018-10-25 13:31:16 +0200586 assert(_Py_tracemalloc_config.tracing);
Victor Stinner10b73e12016-03-22 13:39:05 +0100587
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100588 traceback = traceback_new();
Victor Stinnere492ae52016-03-22 12:58:23 +0100589 if (traceback == NULL) {
Victor Stinner52968672013-11-24 11:37:15 +0100590 return -1;
Victor Stinnere492ae52016-03-22 12:58:23 +0100591 }
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100592
Victor Stinner9e00e802018-10-25 13:31:16 +0200593 if (!_Py_tracemalloc_config.use_domain && domain != DEFAULT_DOMAIN) {
Victor Stinner5e14a382016-03-23 22:03:55 +0100594 /* first trace using a non-zero domain whereas traces use compact
Benjamin Petersonca470632016-09-06 13:47:26 -0700595 (uintptr_t) keys: switch to pointer_t keys. */
Victor Stinner5e14a382016-03-23 22:03:55 +0100596 if (tracemalloc_use_domain() < 0) {
597 return -1;
598 }
599 }
600
Victor Stinner9e00e802018-10-25 13:31:16 +0200601 if (_Py_tracemalloc_config.use_domain) {
Victor Stinnerca79ccd2016-03-23 09:38:54 +0100602 entry = _Py_HASHTABLE_GET_ENTRY(tracemalloc_traces, key);
Victor Stinnere492ae52016-03-22 12:58:23 +0100603 }
604 else {
Victor Stinnerca79ccd2016-03-23 09:38:54 +0100605 entry = _Py_HASHTABLE_GET_ENTRY(tracemalloc_traces, ptr);
Victor Stinnerd606ba72013-11-24 11:28:20 +0100606 }
Victor Stinner52968672013-11-24 11:37:15 +0100607
Victor Stinnerca79ccd2016-03-23 09:38:54 +0100608 if (entry != NULL) {
609 /* the memory block is already tracked */
610 _Py_HASHTABLE_ENTRY_READ_DATA(tracemalloc_traces, entry, trace);
611 assert(tracemalloc_traced_memory >= trace.size);
612 tracemalloc_traced_memory -= trace.size;
613
614 trace.size = size;
615 trace.traceback = traceback;
616 _Py_HASHTABLE_ENTRY_WRITE_DATA(tracemalloc_traces, entry, trace);
617 }
618 else {
619 trace.size = size;
620 trace.traceback = traceback;
621
Victor Stinner9e00e802018-10-25 13:31:16 +0200622 if (_Py_tracemalloc_config.use_domain) {
Victor Stinnerca79ccd2016-03-23 09:38:54 +0100623 res = _Py_HASHTABLE_SET(tracemalloc_traces, key, trace);
624 }
625 else {
626 res = _Py_HASHTABLE_SET(tracemalloc_traces, ptr, trace);
627 }
628 if (res != 0) {
629 return res;
630 }
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100631 }
Victor Stinnere492ae52016-03-22 12:58:23 +0100632
Benjamin Peterson2f8bfef2016-09-07 09:26:18 -0700633 assert(tracemalloc_traced_memory <= SIZE_MAX - size);
Victor Stinnere492ae52016-03-22 12:58:23 +0100634 tracemalloc_traced_memory += size;
635 if (tracemalloc_traced_memory > tracemalloc_peak_traced_memory)
636 tracemalloc_peak_traced_memory = tracemalloc_traced_memory;
637 return 0;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100638}
639
Victor Stinnere492ae52016-03-22 12:58:23 +0100640#define ADD_TRACE(ptr, size) \
Benjamin Petersonca470632016-09-06 13:47:26 -0700641 tracemalloc_add_trace(DEFAULT_DOMAIN, (uintptr_t)(ptr), size)
Victor Stinnere492ae52016-03-22 12:58:23 +0100642
643
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100644static void*
Victor Stinnerdb067af2014-05-02 22:31:14 +0200645tracemalloc_alloc(int use_calloc, void *ctx, size_t nelem, size_t elsize)
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100646{
Victor Stinnerd8f0d922014-06-02 21:57:10 +0200647 PyMemAllocatorEx *alloc = (PyMemAllocatorEx *)ctx;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100648 void *ptr;
649
Benjamin Peterson2f8bfef2016-09-07 09:26:18 -0700650 assert(elsize == 0 || nelem <= SIZE_MAX / elsize);
Victor Stinnerdb067af2014-05-02 22:31:14 +0200651
652 if (use_calloc)
653 ptr = alloc->calloc(alloc->ctx, nelem, elsize);
654 else
655 ptr = alloc->malloc(alloc->ctx, nelem * elsize);
Victor Stinner15116802013-12-04 01:29:35 +0100656 if (ptr == NULL)
657 return NULL;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100658
Victor Stinner88c29872013-12-04 01:47:46 +0100659 TABLES_LOCK();
Victor Stinnere492ae52016-03-22 12:58:23 +0100660 if (ADD_TRACE(ptr, nelem * elsize) < 0) {
Victor Stinner15116802013-12-04 01:29:35 +0100661 /* Failed to allocate a trace for the new memory block */
Victor Stinner88c29872013-12-04 01:47:46 +0100662 TABLES_UNLOCK();
Victor Stinner15116802013-12-04 01:29:35 +0100663 alloc->free(alloc->ctx, ptr);
664 return NULL;
Victor Stinner52968672013-11-24 11:37:15 +0100665 }
Victor Stinner88c29872013-12-04 01:47:46 +0100666 TABLES_UNLOCK();
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100667 return ptr;
668}
669
Victor Stinnere492ae52016-03-22 12:58:23 +0100670
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100671static void*
Victor Stinner15116802013-12-04 01:29:35 +0100672tracemalloc_realloc(void *ctx, void *ptr, size_t new_size)
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100673{
Victor Stinnerd8f0d922014-06-02 21:57:10 +0200674 PyMemAllocatorEx *alloc = (PyMemAllocatorEx *)ctx;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100675 void *ptr2;
676
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100677 ptr2 = alloc->realloc(alloc->ctx, ptr, new_size);
Victor Stinner15116802013-12-04 01:29:35 +0100678 if (ptr2 == NULL)
679 return NULL;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100680
Victor Stinner15116802013-12-04 01:29:35 +0100681 if (ptr != NULL) {
682 /* an existing memory block has been resized */
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100683
Victor Stinner88c29872013-12-04 01:47:46 +0100684 TABLES_LOCK();
Victor Stinner42bcf372016-03-23 09:08:08 +0100685
686 /* tracemalloc_add_trace() updates the trace if there is already
687 a trace at address (domain, ptr2) */
688 if (ptr2 != ptr) {
689 REMOVE_TRACE(ptr);
690 }
Victor Stinner08facd22013-11-24 12:27:59 +0100691
Victor Stinnere492ae52016-03-22 12:58:23 +0100692 if (ADD_TRACE(ptr2, new_size) < 0) {
Victor Stinner15116802013-12-04 01:29:35 +0100693 /* Memory allocation failed. The error cannot be reported to
Raymond Hettinger15f44ab2016-08-30 10:47:49 -0700694 the caller, because realloc() may already have shrunk the
Victor Stinner15116802013-12-04 01:29:35 +0100695 memory block and so removed bytes.
696
Serhiy Storchaka6a7b3a72016-04-17 08:32:47 +0300697 This case is very unlikely: a hash entry has just been
Victor Stinner88c29872013-12-04 01:47:46 +0100698 released, so the hash table should have at least one free entry.
699
700 The GIL and the table lock ensures that only one thread is
701 allocating memory. */
Barry Warsawb2e57942017-09-14 18:13:16 -0700702 Py_UNREACHABLE();
Victor Stinner52968672013-11-24 11:37:15 +0100703 }
Victor Stinner88c29872013-12-04 01:47:46 +0100704 TABLES_UNLOCK();
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100705 }
Victor Stinner15116802013-12-04 01:29:35 +0100706 else {
707 /* new allocation */
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100708
Victor Stinner88c29872013-12-04 01:47:46 +0100709 TABLES_LOCK();
Victor Stinnere492ae52016-03-22 12:58:23 +0100710 if (ADD_TRACE(ptr2, new_size) < 0) {
Victor Stinner15116802013-12-04 01:29:35 +0100711 /* Failed to allocate a trace for the new memory block */
Victor Stinner88c29872013-12-04 01:47:46 +0100712 TABLES_UNLOCK();
Victor Stinner15116802013-12-04 01:29:35 +0100713 alloc->free(alloc->ctx, ptr2);
714 return NULL;
715 }
Victor Stinner88c29872013-12-04 01:47:46 +0100716 TABLES_UNLOCK();
Victor Stinner15116802013-12-04 01:29:35 +0100717 }
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100718 return ptr2;
719}
720
Victor Stinnere492ae52016-03-22 12:58:23 +0100721
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100722static void
723tracemalloc_free(void *ctx, void *ptr)
724{
Victor Stinnerd8f0d922014-06-02 21:57:10 +0200725 PyMemAllocatorEx *alloc = (PyMemAllocatorEx *)ctx;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100726
727 if (ptr == NULL)
728 return;
729
730 /* GIL cannot be locked in PyMem_RawFree() because it would introduce
731 a deadlock in PyThreadState_DeleteCurrent(). */
732
733 alloc->free(alloc->ctx, ptr);
Victor Stinner88c29872013-12-04 01:47:46 +0100734
735 TABLES_LOCK();
Victor Stinnere492ae52016-03-22 12:58:23 +0100736 REMOVE_TRACE(ptr);
Victor Stinner88c29872013-12-04 01:47:46 +0100737 TABLES_UNLOCK();
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100738}
739
Victor Stinnere492ae52016-03-22 12:58:23 +0100740
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100741static void*
Victor Stinnerdb067af2014-05-02 22:31:14 +0200742tracemalloc_alloc_gil(int use_calloc, void *ctx, size_t nelem, size_t elsize)
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100743{
Victor Stinner15116802013-12-04 01:29:35 +0100744 void *ptr;
745
746 if (get_reentrant()) {
Victor Stinnerd8f0d922014-06-02 21:57:10 +0200747 PyMemAllocatorEx *alloc = (PyMemAllocatorEx *)ctx;
Victor Stinnerdb067af2014-05-02 22:31:14 +0200748 if (use_calloc)
749 return alloc->calloc(alloc->ctx, nelem, elsize);
750 else
751 return alloc->malloc(alloc->ctx, nelem * elsize);
Victor Stinner15116802013-12-04 01:29:35 +0100752 }
753
754 /* Ignore reentrant call. PyObjet_Malloc() calls PyMem_Malloc() for
755 allocations larger than 512 bytes, don't trace the same memory
756 allocation twice. */
757 set_reentrant(1);
758
Victor Stinnerdb067af2014-05-02 22:31:14 +0200759 ptr = tracemalloc_alloc(use_calloc, ctx, nelem, elsize);
Victor Stinner15116802013-12-04 01:29:35 +0100760
761 set_reentrant(0);
762 return ptr;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100763}
764
Victor Stinnere492ae52016-03-22 12:58:23 +0100765
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100766static void*
Victor Stinnerdb067af2014-05-02 22:31:14 +0200767tracemalloc_malloc_gil(void *ctx, size_t size)
768{
769 return tracemalloc_alloc_gil(0, ctx, 1, size);
770}
771
Victor Stinnere492ae52016-03-22 12:58:23 +0100772
Victor Stinnerdb067af2014-05-02 22:31:14 +0200773static void*
774tracemalloc_calloc_gil(void *ctx, size_t nelem, size_t elsize)
775{
776 return tracemalloc_alloc_gil(1, ctx, nelem, elsize);
777}
778
Victor Stinnere492ae52016-03-22 12:58:23 +0100779
Victor Stinnerdb067af2014-05-02 22:31:14 +0200780static void*
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100781tracemalloc_realloc_gil(void *ctx, void *ptr, size_t new_size)
782{
Victor Stinner15116802013-12-04 01:29:35 +0100783 void *ptr2;
784
785 if (get_reentrant()) {
786 /* Reentrant call to PyMem_Realloc() and PyMem_RawRealloc().
787 Example: PyMem_RawRealloc() is called internally by pymalloc
788 (_PyObject_Malloc() and _PyObject_Realloc()) to allocate a new
789 arena (new_arena()). */
Victor Stinnerd8f0d922014-06-02 21:57:10 +0200790 PyMemAllocatorEx *alloc = (PyMemAllocatorEx *)ctx;
Victor Stinner15116802013-12-04 01:29:35 +0100791
792 ptr2 = alloc->realloc(alloc->ctx, ptr, new_size);
Victor Stinner88c29872013-12-04 01:47:46 +0100793 if (ptr2 != NULL && ptr != NULL) {
794 TABLES_LOCK();
Victor Stinnere492ae52016-03-22 12:58:23 +0100795 REMOVE_TRACE(ptr);
Victor Stinner88c29872013-12-04 01:47:46 +0100796 TABLES_UNLOCK();
797 }
Victor Stinner15116802013-12-04 01:29:35 +0100798 return ptr2;
799 }
800
801 /* Ignore reentrant call. PyObjet_Realloc() calls PyMem_Realloc() for
802 allocations larger than 512 bytes. Don't trace the same memory
803 allocation twice. */
804 set_reentrant(1);
805
806 ptr2 = tracemalloc_realloc(ctx, ptr, new_size);
807
808 set_reentrant(0);
809 return ptr2;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100810}
811
Victor Stinnere492ae52016-03-22 12:58:23 +0100812
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100813#ifdef TRACE_RAW_MALLOC
814static void*
Victor Stinnerdb067af2014-05-02 22:31:14 +0200815tracemalloc_raw_alloc(int use_calloc, void *ctx, size_t nelem, size_t elsize)
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100816{
Victor Stinner15116802013-12-04 01:29:35 +0100817 PyGILState_STATE gil_state;
Victor Stinner15116802013-12-04 01:29:35 +0100818 void *ptr;
819
820 if (get_reentrant()) {
Victor Stinnerd8f0d922014-06-02 21:57:10 +0200821 PyMemAllocatorEx *alloc = (PyMemAllocatorEx *)ctx;
Victor Stinnerdb067af2014-05-02 22:31:14 +0200822 if (use_calloc)
823 return alloc->calloc(alloc->ctx, nelem, elsize);
824 else
825 return alloc->malloc(alloc->ctx, nelem * elsize);
Victor Stinner15116802013-12-04 01:29:35 +0100826 }
827
828 /* Ignore reentrant call. PyGILState_Ensure() may call PyMem_RawMalloc()
829 indirectly which would call PyGILState_Ensure() if reentrant are not
830 disabled. */
831 set_reentrant(1);
832
Victor Stinner15116802013-12-04 01:29:35 +0100833 gil_state = PyGILState_Ensure();
Victor Stinnerdb067af2014-05-02 22:31:14 +0200834 ptr = tracemalloc_alloc(use_calloc, ctx, nelem, elsize);
Victor Stinner15116802013-12-04 01:29:35 +0100835 PyGILState_Release(gil_state);
Victor Stinner15116802013-12-04 01:29:35 +0100836
837 set_reentrant(0);
838 return ptr;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100839}
840
Victor Stinnere492ae52016-03-22 12:58:23 +0100841
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100842static void*
Victor Stinnerdb067af2014-05-02 22:31:14 +0200843tracemalloc_raw_malloc(void *ctx, size_t size)
844{
845 return tracemalloc_raw_alloc(0, ctx, 1, size);
846}
847
Victor Stinnere492ae52016-03-22 12:58:23 +0100848
Victor Stinnerdb067af2014-05-02 22:31:14 +0200849static void*
850tracemalloc_raw_calloc(void *ctx, size_t nelem, size_t elsize)
851{
852 return tracemalloc_raw_alloc(1, ctx, nelem, elsize);
853}
854
Victor Stinnere492ae52016-03-22 12:58:23 +0100855
Victor Stinnerdb067af2014-05-02 22:31:14 +0200856static void*
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100857tracemalloc_raw_realloc(void *ctx, void *ptr, size_t new_size)
858{
Victor Stinner15116802013-12-04 01:29:35 +0100859 PyGILState_STATE gil_state;
Victor Stinner15116802013-12-04 01:29:35 +0100860 void *ptr2;
861
862 if (get_reentrant()) {
863 /* Reentrant call to PyMem_RawRealloc(). */
Victor Stinnerd8f0d922014-06-02 21:57:10 +0200864 PyMemAllocatorEx *alloc = (PyMemAllocatorEx *)ctx;
Victor Stinner15116802013-12-04 01:29:35 +0100865
866 ptr2 = alloc->realloc(alloc->ctx, ptr, new_size);
Victor Stinner15116802013-12-04 01:29:35 +0100867
Victor Stinner88c29872013-12-04 01:47:46 +0100868 if (ptr2 != NULL && ptr != NULL) {
869 TABLES_LOCK();
Victor Stinnere492ae52016-03-22 12:58:23 +0100870 REMOVE_TRACE(ptr);
Victor Stinner88c29872013-12-04 01:47:46 +0100871 TABLES_UNLOCK();
872 }
Victor Stinner15116802013-12-04 01:29:35 +0100873 return ptr2;
874 }
875
876 /* Ignore reentrant call. PyGILState_Ensure() may call PyMem_RawMalloc()
877 indirectly which would call PyGILState_Ensure() if reentrant calls are
878 not disabled. */
879 set_reentrant(1);
880
Victor Stinner15116802013-12-04 01:29:35 +0100881 gil_state = PyGILState_Ensure();
882 ptr2 = tracemalloc_realloc(ctx, ptr, new_size);
883 PyGILState_Release(gil_state);
Victor Stinner15116802013-12-04 01:29:35 +0100884
885 set_reentrant(0);
886 return ptr2;
887}
888#endif /* TRACE_RAW_MALLOC */
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100889
Victor Stinnere492ae52016-03-22 12:58:23 +0100890
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100891static int
Victor Stinner285cf0a2016-03-21 22:00:58 +0100892tracemalloc_clear_filename(_Py_hashtable_t *ht, _Py_hashtable_entry_t *entry,
893 void *user_data)
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100894{
Victor Stinner285cf0a2016-03-21 22:00:58 +0100895 PyObject *filename;
896
Victor Stinner5dacbd42016-03-23 09:52:13 +0100897 _Py_HASHTABLE_ENTRY_READ_KEY(ht, entry, filename);
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100898 Py_DECREF(filename);
899 return 0;
900}
901
Victor Stinnere492ae52016-03-22 12:58:23 +0100902
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100903static int
Victor Stinner285cf0a2016-03-21 22:00:58 +0100904traceback_free_traceback(_Py_hashtable_t *ht, _Py_hashtable_entry_t *entry,
905 void *user_data)
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100906{
Victor Stinner285cf0a2016-03-21 22:00:58 +0100907 traceback_t *traceback;
908
Victor Stinner5dacbd42016-03-23 09:52:13 +0100909 _Py_HASHTABLE_ENTRY_READ_KEY(ht, entry, traceback);
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100910 raw_free(traceback);
911 return 0;
912}
913
Victor Stinnere492ae52016-03-22 12:58:23 +0100914
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100915/* reentrant flag must be set to call this function and GIL must be held */
916static void
917tracemalloc_clear_traces(void)
918{
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100919 /* The GIL protects variables againt concurrent access */
920 assert(PyGILState_Check());
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100921
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100922 TABLES_LOCK();
923 _Py_hashtable_clear(tracemalloc_traces);
924 tracemalloc_traced_memory = 0;
Victor Stinner3c0481d2013-11-27 21:39:49 +0100925 tracemalloc_peak_traced_memory = 0;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100926 TABLES_UNLOCK();
927
928 _Py_hashtable_foreach(tracemalloc_tracebacks, traceback_free_traceback, NULL);
929 _Py_hashtable_clear(tracemalloc_tracebacks);
930
931 _Py_hashtable_foreach(tracemalloc_filenames, tracemalloc_clear_filename, NULL);
932 _Py_hashtable_clear(tracemalloc_filenames);
933}
934
Victor Stinnere492ae52016-03-22 12:58:23 +0100935
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100936static int
937tracemalloc_init(void)
938{
Victor Stinner9e00e802018-10-25 13:31:16 +0200939 if (_Py_tracemalloc_config.initialized == TRACEMALLOC_FINALIZED) {
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100940 PyErr_SetString(PyExc_RuntimeError,
941 "the tracemalloc module has been unloaded");
942 return -1;
943 }
944
Victor Stinner9e00e802018-10-25 13:31:16 +0200945 if (_Py_tracemalloc_config.initialized == TRACEMALLOC_INITIALIZED)
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100946 return 0;
947
948 PyMem_GetAllocator(PYMEM_DOMAIN_RAW, &allocators.raw);
949
950#ifdef REENTRANT_THREADLOCAL
Masayuki Yamamoto731e1892017-10-06 19:41:34 +0900951 if (PyThread_tss_create(&tracemalloc_reentrant_key) != 0) {
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100952#ifdef MS_WINDOWS
953 PyErr_SetFromWindowsErr(0);
954#else
955 PyErr_SetFromErrno(PyExc_OSError);
956#endif
957 return -1;
958 }
959#endif
960
Antoine Pitroua6a4dc82017-09-07 18:56:24 +0200961#if defined(TRACE_RAW_MALLOC)
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100962 if (tables_lock == NULL) {
963 tables_lock = PyThread_allocate_lock();
964 if (tables_lock == NULL) {
965 PyErr_SetString(PyExc_RuntimeError, "cannot allocate lock");
966 return -1;
967 }
968 }
969#endif
970
Victor Stinner285cf0a2016-03-21 22:00:58 +0100971 tracemalloc_filenames = hashtable_new(sizeof(PyObject *), 0,
972 hashtable_hash_pyobject,
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100973 hashtable_compare_unicode);
974
Victor Stinner285cf0a2016-03-21 22:00:58 +0100975 tracemalloc_tracebacks = hashtable_new(sizeof(traceback_t *), 0,
976 hashtable_hash_traceback,
977 hashtable_compare_traceback);
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100978
Victor Stinner9e00e802018-10-25 13:31:16 +0200979 if (_Py_tracemalloc_config.use_domain) {
Victor Stinnere492ae52016-03-22 12:58:23 +0100980 tracemalloc_traces = hashtable_new(sizeof(pointer_t),
981 sizeof(trace_t),
982 hashtable_hash_pointer_t,
983 hashtable_compare_pointer_t);
984 }
985 else {
Benjamin Petersonca470632016-09-06 13:47:26 -0700986 tracemalloc_traces = hashtable_new(sizeof(uintptr_t),
Victor Stinnere492ae52016-03-22 12:58:23 +0100987 sizeof(trace_t),
988 _Py_hashtable_hash_ptr,
989 _Py_hashtable_compare_direct);
990 }
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100991
992 if (tracemalloc_filenames == NULL || tracemalloc_tracebacks == NULL
Victor Stinner285cf0a2016-03-21 22:00:58 +0100993 || tracemalloc_traces == NULL) {
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100994 PyErr_NoMemory();
995 return -1;
996 }
997
998 unknown_filename = PyUnicode_FromString("<unknown>");
999 if (unknown_filename == NULL)
1000 return -1;
1001 PyUnicode_InternInPlace(&unknown_filename);
1002
1003 tracemalloc_empty_traceback.nframe = 1;
1004 /* borrowed reference */
1005 tracemalloc_empty_traceback.frames[0].filename = unknown_filename;
1006 tracemalloc_empty_traceback.frames[0].lineno = 0;
1007 tracemalloc_empty_traceback.hash = traceback_hash(&tracemalloc_empty_traceback);
1008
Victor Stinner9e00e802018-10-25 13:31:16 +02001009 _Py_tracemalloc_config.initialized = TRACEMALLOC_INITIALIZED;
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001010 return 0;
1011}
1012
Victor Stinnere492ae52016-03-22 12:58:23 +01001013
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001014static void
1015tracemalloc_deinit(void)
1016{
Victor Stinner9e00e802018-10-25 13:31:16 +02001017 if (_Py_tracemalloc_config.initialized != TRACEMALLOC_INITIALIZED)
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001018 return;
Victor Stinner9e00e802018-10-25 13:31:16 +02001019 _Py_tracemalloc_config.initialized = TRACEMALLOC_FINALIZED;
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001020
1021 tracemalloc_stop();
1022
1023 /* destroy hash tables */
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001024 _Py_hashtable_destroy(tracemalloc_tracebacks);
1025 _Py_hashtable_destroy(tracemalloc_filenames);
Victor Stinner285cf0a2016-03-21 22:00:58 +01001026 _Py_hashtable_destroy(tracemalloc_traces);
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001027
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02001028#if defined(TRACE_RAW_MALLOC)
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001029 if (tables_lock != NULL) {
1030 PyThread_free_lock(tables_lock);
1031 tables_lock = NULL;
1032 }
1033#endif
1034
1035#ifdef REENTRANT_THREADLOCAL
Masayuki Yamamoto731e1892017-10-06 19:41:34 +09001036 PyThread_tss_delete(&tracemalloc_reentrant_key);
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001037#endif
1038
1039 Py_XDECREF(unknown_filename);
1040}
1041
Victor Stinnere492ae52016-03-22 12:58:23 +01001042
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001043static int
Victor Stinnerf28ce602013-11-27 22:27:13 +01001044tracemalloc_start(int max_nframe)
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001045{
Victor Stinnerd8f0d922014-06-02 21:57:10 +02001046 PyMemAllocatorEx alloc;
Victor Stinnerf28ce602013-11-27 22:27:13 +01001047 size_t size;
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001048
Victor Stinnera7368ac2017-11-15 18:11:45 -08001049 if (max_nframe < 1 || max_nframe > MAX_NFRAME) {
1050 PyErr_Format(PyExc_ValueError,
1051 "the number of frames must be in range [1; %i]",
1052 (int)MAX_NFRAME);
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001053 return -1;
Victor Stinnera7368ac2017-11-15 18:11:45 -08001054 }
1055
1056 if (tracemalloc_init() < 0) {
1057 return -1;
1058 }
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001059
Victor Stinner9e00e802018-10-25 13:31:16 +02001060 if (_Py_tracemalloc_config.tracing) {
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001061 /* hook already installed: do nothing */
1062 return 0;
1063 }
1064
Victor Stinner52aee852014-08-16 15:44:02 +02001065 assert(1 <= max_nframe && max_nframe <= MAX_NFRAME);
Victor Stinner9e00e802018-10-25 13:31:16 +02001066 _Py_tracemalloc_config.max_nframe = max_nframe;
Victor Stinnerf28ce602013-11-27 22:27:13 +01001067
1068 /* allocate a buffer to store a new traceback */
1069 size = TRACEBACK_SIZE(max_nframe);
1070 assert(tracemalloc_traceback == NULL);
1071 tracemalloc_traceback = raw_malloc(size);
1072 if (tracemalloc_traceback == NULL) {
1073 PyErr_NoMemory();
1074 return -1;
1075 }
1076
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001077#ifdef TRACE_RAW_MALLOC
1078 alloc.malloc = tracemalloc_raw_malloc;
Victor Stinnerdb067af2014-05-02 22:31:14 +02001079 alloc.calloc = tracemalloc_raw_calloc;
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001080 alloc.realloc = tracemalloc_raw_realloc;
1081 alloc.free = tracemalloc_free;
1082
1083 alloc.ctx = &allocators.raw;
1084 PyMem_GetAllocator(PYMEM_DOMAIN_RAW, &allocators.raw);
1085 PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &alloc);
1086#endif
1087
1088 alloc.malloc = tracemalloc_malloc_gil;
Victor Stinnerdb067af2014-05-02 22:31:14 +02001089 alloc.calloc = tracemalloc_calloc_gil;
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001090 alloc.realloc = tracemalloc_realloc_gil;
1091 alloc.free = tracemalloc_free;
1092
1093 alloc.ctx = &allocators.mem;
1094 PyMem_GetAllocator(PYMEM_DOMAIN_MEM, &allocators.mem);
1095 PyMem_SetAllocator(PYMEM_DOMAIN_MEM, &alloc);
1096
1097 alloc.ctx = &allocators.obj;
1098 PyMem_GetAllocator(PYMEM_DOMAIN_OBJ, &allocators.obj);
1099 PyMem_SetAllocator(PYMEM_DOMAIN_OBJ, &alloc);
1100
1101 /* everything is ready: start tracing Python memory allocations */
Victor Stinner9e00e802018-10-25 13:31:16 +02001102 _Py_tracemalloc_config.tracing = 1;
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001103
1104 return 0;
1105}
1106
Victor Stinnere492ae52016-03-22 12:58:23 +01001107
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001108static void
1109tracemalloc_stop(void)
1110{
Victor Stinner9e00e802018-10-25 13:31:16 +02001111 if (!_Py_tracemalloc_config.tracing)
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001112 return;
1113
1114 /* stop tracing Python memory allocations */
Victor Stinner9e00e802018-10-25 13:31:16 +02001115 _Py_tracemalloc_config.tracing = 0;
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001116
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001117 /* unregister the hook on memory allocators */
1118#ifdef TRACE_RAW_MALLOC
1119 PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &allocators.raw);
1120#endif
1121 PyMem_SetAllocator(PYMEM_DOMAIN_MEM, &allocators.mem);
1122 PyMem_SetAllocator(PYMEM_DOMAIN_OBJ, &allocators.obj);
1123
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001124 tracemalloc_clear_traces();
Victor Stinner285cf0a2016-03-21 22:00:58 +01001125
1126 /* release memory */
Victor Stinnerf28ce602013-11-27 22:27:13 +01001127 raw_free(tracemalloc_traceback);
1128 tracemalloc_traceback = NULL;
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001129}
1130
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001131
Victor Stinnere492ae52016-03-22 12:58:23 +01001132
Serhiy Storchakab451f912017-02-04 12:18:38 +02001133/*[clinic input]
1134_tracemalloc.is_tracing
1135
1136Return True if the tracemalloc module is tracing Python memory allocations.
1137[clinic start generated code]*/
1138
1139static PyObject *
1140_tracemalloc_is_tracing_impl(PyObject *module)
Serhiy Storchaka97353842017-02-05 22:58:46 +02001141/*[clinic end generated code: output=2d763b42601cd3ef input=af104b0a00192f63]*/
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001142{
Victor Stinner9e00e802018-10-25 13:31:16 +02001143 return PyBool_FromLong(_Py_tracemalloc_config.tracing);
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001144}
1145
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001146
Serhiy Storchakab451f912017-02-04 12:18:38 +02001147/*[clinic input]
1148_tracemalloc.clear_traces
Victor Stinnere492ae52016-03-22 12:58:23 +01001149
Serhiy Storchakab451f912017-02-04 12:18:38 +02001150Clear traces of memory blocks allocated by Python.
1151[clinic start generated code]*/
1152
1153static PyObject *
1154_tracemalloc_clear_traces_impl(PyObject *module)
1155/*[clinic end generated code: output=a86080ee41b84197 input=0dab5b6c785183a5]*/
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001156{
Victor Stinner9e00e802018-10-25 13:31:16 +02001157 if (!_Py_tracemalloc_config.tracing)
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001158 Py_RETURN_NONE;
1159
1160 set_reentrant(1);
1161 tracemalloc_clear_traces();
1162 set_reentrant(0);
1163
1164 Py_RETURN_NONE;
1165}
1166
Victor Stinnere492ae52016-03-22 12:58:23 +01001167
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001168static PyObject*
1169frame_to_pyobject(frame_t *frame)
1170{
1171 PyObject *frame_obj, *lineno_obj;
1172
1173 frame_obj = PyTuple_New(2);
1174 if (frame_obj == NULL)
1175 return NULL;
1176
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001177 Py_INCREF(frame->filename);
1178 PyTuple_SET_ITEM(frame_obj, 0, frame->filename);
1179
Victor Stinner95283342016-03-15 21:57:02 +01001180 lineno_obj = PyLong_FromUnsignedLong(frame->lineno);
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001181 if (lineno_obj == NULL) {
1182 Py_DECREF(frame_obj);
1183 return NULL;
1184 }
1185 PyTuple_SET_ITEM(frame_obj, 1, lineno_obj);
1186
1187 return frame_obj;
1188}
1189
Victor Stinnere492ae52016-03-22 12:58:23 +01001190
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001191static PyObject*
1192traceback_to_pyobject(traceback_t *traceback, _Py_hashtable_t *intern_table)
1193{
1194 int i;
1195 PyObject *frames, *frame;
1196
1197 if (intern_table != NULL) {
1198 if (_Py_HASHTABLE_GET(intern_table, traceback, frames)) {
1199 Py_INCREF(frames);
1200 return frames;
1201 }
1202 }
1203
1204 frames = PyTuple_New(traceback->nframe);
1205 if (frames == NULL)
1206 return NULL;
1207
1208 for (i=0; i < traceback->nframe; i++) {
1209 frame = frame_to_pyobject(&traceback->frames[i]);
1210 if (frame == NULL) {
1211 Py_DECREF(frames);
1212 return NULL;
1213 }
1214 PyTuple_SET_ITEM(frames, i, frame);
1215 }
1216
1217 if (intern_table != NULL) {
1218 if (_Py_HASHTABLE_SET(intern_table, traceback, frames) < 0) {
1219 Py_DECREF(frames);
1220 PyErr_NoMemory();
1221 return NULL;
1222 }
1223 /* intern_table keeps a new reference to frames */
1224 Py_INCREF(frames);
1225 }
1226 return frames;
1227}
1228
Victor Stinnere492ae52016-03-22 12:58:23 +01001229
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001230static PyObject*
Victor Stinner5ea4c062017-06-20 17:46:36 +02001231trace_to_pyobject(unsigned int domain, trace_t *trace,
Victor Stinnere492ae52016-03-22 12:58:23 +01001232 _Py_hashtable_t *intern_tracebacks)
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001233{
1234 PyObject *trace_obj = NULL;
Victor Stinnere492ae52016-03-22 12:58:23 +01001235 PyObject *obj;
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001236
Victor Stinnere492ae52016-03-22 12:58:23 +01001237 trace_obj = PyTuple_New(3);
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001238 if (trace_obj == NULL)
1239 return NULL;
1240
Victor Stinnere492ae52016-03-22 12:58:23 +01001241 obj = PyLong_FromSize_t(domain);
1242 if (obj == NULL) {
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001243 Py_DECREF(trace_obj);
1244 return NULL;
1245 }
Victor Stinnere492ae52016-03-22 12:58:23 +01001246 PyTuple_SET_ITEM(trace_obj, 0, obj);
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001247
Victor Stinnere492ae52016-03-22 12:58:23 +01001248 obj = PyLong_FromSize_t(trace->size);
1249 if (obj == NULL) {
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001250 Py_DECREF(trace_obj);
1251 return NULL;
1252 }
Victor Stinnere492ae52016-03-22 12:58:23 +01001253 PyTuple_SET_ITEM(trace_obj, 1, obj);
1254
1255 obj = traceback_to_pyobject(trace->traceback, intern_tracebacks);
1256 if (obj == NULL) {
1257 Py_DECREF(trace_obj);
1258 return NULL;
1259 }
1260 PyTuple_SET_ITEM(trace_obj, 2, obj);
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001261
1262 return trace_obj;
1263}
1264
Victor Stinnere492ae52016-03-22 12:58:23 +01001265
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001266typedef struct {
1267 _Py_hashtable_t *traces;
1268 _Py_hashtable_t *tracebacks;
1269 PyObject *list;
1270} get_traces_t;
1271
1272static int
Victor Stinner285cf0a2016-03-21 22:00:58 +01001273tracemalloc_get_traces_fill(_Py_hashtable_t *traces, _Py_hashtable_entry_t *entry,
1274 void *user_data)
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001275{
1276 get_traces_t *get_traces = user_data;
Victor Stinner5ea4c062017-06-20 17:46:36 +02001277 unsigned int domain;
Victor Stinner5dacbd42016-03-23 09:52:13 +01001278 trace_t trace;
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001279 PyObject *tracemalloc_obj;
1280 int res;
1281
Victor Stinner9e00e802018-10-25 13:31:16 +02001282 if (_Py_tracemalloc_config.use_domain) {
Victor Stinnere492ae52016-03-22 12:58:23 +01001283 pointer_t key;
Victor Stinner5dacbd42016-03-23 09:52:13 +01001284 _Py_HASHTABLE_ENTRY_READ_KEY(traces, entry, key);
Victor Stinnere492ae52016-03-22 12:58:23 +01001285 domain = key.domain;
1286 }
1287 else {
1288 domain = DEFAULT_DOMAIN;
1289 }
Victor Stinner5dacbd42016-03-23 09:52:13 +01001290 _Py_HASHTABLE_ENTRY_READ_DATA(traces, entry, trace);
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001291
Victor Stinner5dacbd42016-03-23 09:52:13 +01001292 tracemalloc_obj = trace_to_pyobject(domain, &trace, get_traces->tracebacks);
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001293 if (tracemalloc_obj == NULL)
1294 return 1;
1295
1296 res = PyList_Append(get_traces->list, tracemalloc_obj);
1297 Py_DECREF(tracemalloc_obj);
1298 if (res < 0)
1299 return 1;
1300
1301 return 0;
1302}
1303
Victor Stinnere492ae52016-03-22 12:58:23 +01001304
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001305static int
Victor Stinner285cf0a2016-03-21 22:00:58 +01001306tracemalloc_pyobject_decref_cb(_Py_hashtable_t *tracebacks,
1307 _Py_hashtable_entry_t *entry,
1308 void *user_data)
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001309{
Victor Stinnerc9553872016-03-22 12:13:01 +01001310 PyObject *obj;
Victor Stinnere8c6b2f2016-03-23 09:25:01 +01001311 _Py_HASHTABLE_ENTRY_READ_DATA(tracebacks, entry, obj);
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001312 Py_DECREF(obj);
1313 return 0;
1314}
1315
Victor Stinnere492ae52016-03-22 12:58:23 +01001316
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001317
Serhiy Storchakab451f912017-02-04 12:18:38 +02001318/*[clinic input]
1319_tracemalloc._get_traces
1320
1321Get traces of all memory blocks allocated by Python.
1322
1323Return a list of (size: int, traceback: tuple) tuples.
1324traceback is a tuple of (filename: str, lineno: int) tuples.
1325
1326Return an empty list if the tracemalloc module is disabled.
1327[clinic start generated code]*/
1328
1329static PyObject *
1330_tracemalloc__get_traces_impl(PyObject *module)
1331/*[clinic end generated code: output=e9929876ced4b5cc input=6c7d2230b24255aa]*/
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001332{
1333 get_traces_t get_traces;
1334 int err;
1335
1336 get_traces.traces = NULL;
1337 get_traces.tracebacks = NULL;
1338 get_traces.list = PyList_New(0);
1339 if (get_traces.list == NULL)
1340 goto error;
1341
Victor Stinner9e00e802018-10-25 13:31:16 +02001342 if (!_Py_tracemalloc_config.tracing)
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001343 return get_traces.list;
1344
Victor Stinnerde2f1322013-11-26 00:26:23 +01001345 /* the traceback hash table is used temporarily to intern traceback tuple
1346 of (filename, lineno) tuples */
Victor Stinnerc9553872016-03-22 12:13:01 +01001347 get_traces.tracebacks = hashtable_new(sizeof(traceback_t *),
1348 sizeof(PyObject *),
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001349 _Py_hashtable_hash_ptr,
1350 _Py_hashtable_compare_direct);
1351 if (get_traces.tracebacks == NULL) {
1352 PyErr_NoMemory();
1353 goto error;
1354 }
1355
1356 TABLES_LOCK();
1357 get_traces.traces = _Py_hashtable_copy(tracemalloc_traces);
1358 TABLES_UNLOCK();
1359
1360 if (get_traces.traces == NULL) {
1361 PyErr_NoMemory();
1362 goto error;
1363 }
1364
1365 set_reentrant(1);
1366 err = _Py_hashtable_foreach(get_traces.traces,
1367 tracemalloc_get_traces_fill, &get_traces);
1368 set_reentrant(0);
1369 if (err)
1370 goto error;
1371
1372 goto finally;
1373
1374error:
1375 Py_CLEAR(get_traces.list);
1376
1377finally:
1378 if (get_traces.tracebacks != NULL) {
1379 _Py_hashtable_foreach(get_traces.tracebacks,
Victor Stinner285cf0a2016-03-21 22:00:58 +01001380 tracemalloc_pyobject_decref_cb, NULL);
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001381 _Py_hashtable_destroy(get_traces.tracebacks);
1382 }
Victor Stinnerc9553872016-03-22 12:13:01 +01001383 if (get_traces.traces != NULL) {
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001384 _Py_hashtable_destroy(get_traces.traces);
Victor Stinnerc9553872016-03-22 12:13:01 +01001385 }
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001386
1387 return get_traces.list;
1388}
1389
Victor Stinnere492ae52016-03-22 12:58:23 +01001390
Victor Stinner0611c262016-03-15 22:22:13 +01001391static traceback_t*
Victor Stinner5ea4c062017-06-20 17:46:36 +02001392tracemalloc_get_traceback(unsigned int domain, uintptr_t ptr)
Victor Stinner0611c262016-03-15 22:22:13 +01001393{
1394 trace_t trace;
1395 int found;
1396
Victor Stinner9e00e802018-10-25 13:31:16 +02001397 if (!_Py_tracemalloc_config.tracing)
Victor Stinner0611c262016-03-15 22:22:13 +01001398 return NULL;
1399
1400 TABLES_LOCK();
Victor Stinner9e00e802018-10-25 13:31:16 +02001401 if (_Py_tracemalloc_config.use_domain) {
Victor Stinner10b73e12016-03-22 13:39:05 +01001402 pointer_t key = {ptr, domain};
Victor Stinnere492ae52016-03-22 12:58:23 +01001403 found = _Py_HASHTABLE_GET(tracemalloc_traces, key, trace);
1404 }
1405 else {
1406 found = _Py_HASHTABLE_GET(tracemalloc_traces, ptr, trace);
1407 }
Victor Stinner0611c262016-03-15 22:22:13 +01001408 TABLES_UNLOCK();
1409
1410 if (!found)
1411 return NULL;
1412
1413 return trace.traceback;
1414}
1415
Victor Stinnere492ae52016-03-22 12:58:23 +01001416
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001417
Serhiy Storchakab451f912017-02-04 12:18:38 +02001418/*[clinic input]
1419_tracemalloc._get_object_traceback
1420
1421 obj: object
1422 /
1423
1424Get the traceback where the Python object obj was allocated.
1425
1426Return a tuple of (filename: str, lineno: int) tuples.
1427Return None if the tracemalloc module is disabled or did not
1428trace the allocation of the object.
1429[clinic start generated code]*/
1430
1431static PyObject *
1432_tracemalloc__get_object_traceback(PyObject *module, PyObject *obj)
1433/*[clinic end generated code: output=41ee0553a658b0aa input=29495f1b21c53212]*/
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001434{
1435 PyTypeObject *type;
1436 void *ptr;
Victor Stinner0611c262016-03-15 22:22:13 +01001437 traceback_t *traceback;
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001438
1439 type = Py_TYPE(obj);
Victor Stinner626bff82018-10-25 17:31:10 +02001440 if (PyType_IS_GC(type)) {
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001441 ptr = (void *)((char *)obj - sizeof(PyGC_Head));
Victor Stinner626bff82018-10-25 17:31:10 +02001442 }
1443 else {
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001444 ptr = (void *)obj;
Victor Stinner626bff82018-10-25 17:31:10 +02001445 }
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001446
Benjamin Petersonca470632016-09-06 13:47:26 -07001447 traceback = tracemalloc_get_traceback(DEFAULT_DOMAIN, (uintptr_t)ptr);
Victor Stinner0611c262016-03-15 22:22:13 +01001448 if (traceback == NULL)
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001449 Py_RETURN_NONE;
1450
Victor Stinner0611c262016-03-15 22:22:13 +01001451 return traceback_to_pyobject(traceback, NULL);
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001452}
1453
Victor Stinnere492ae52016-03-22 12:58:23 +01001454
Victor Stinner0611c262016-03-15 22:22:13 +01001455#define PUTS(fd, str) _Py_write_noraise(fd, str, (int)strlen(str))
1456
1457static void
1458_PyMem_DumpFrame(int fd, frame_t * frame)
1459{
1460 PUTS(fd, " File \"");
1461 _Py_DumpASCII(fd, frame->filename);
1462 PUTS(fd, "\", line ");
1463 _Py_DumpDecimal(fd, frame->lineno);
1464 PUTS(fd, "\n");
1465}
1466
1467/* Dump the traceback where a memory block was allocated into file descriptor
1468 fd. The function may block on TABLES_LOCK() but it is unlikely. */
1469void
1470_PyMem_DumpTraceback(int fd, const void *ptr)
1471{
1472 traceback_t *traceback;
1473 int i;
1474
Victor Stinnerf966e532018-11-13 15:14:58 +01001475 if (!_Py_tracemalloc_config.tracing) {
1476 PUTS(fd, "Enable tracemalloc to get the memory block "
1477 "allocation traceback\n\n");
1478 return;
1479 }
1480
Benjamin Petersonca470632016-09-06 13:47:26 -07001481 traceback = tracemalloc_get_traceback(DEFAULT_DOMAIN, (uintptr_t)ptr);
Victor Stinner0611c262016-03-15 22:22:13 +01001482 if (traceback == NULL)
1483 return;
1484
1485 PUTS(fd, "Memory block allocated at (most recent call first):\n");
1486 for (i=0; i < traceback->nframe; i++) {
1487 _PyMem_DumpFrame(fd, &traceback->frames[i]);
1488 }
1489 PUTS(fd, "\n");
1490}
1491
1492#undef PUTS
1493
Victor Stinnere492ae52016-03-22 12:58:23 +01001494
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001495
Serhiy Storchakab451f912017-02-04 12:18:38 +02001496/*[clinic input]
1497_tracemalloc.start
1498
Victor Stinnera7368ac2017-11-15 18:11:45 -08001499 nframe: int = 1
Serhiy Storchakab451f912017-02-04 12:18:38 +02001500 /
1501
1502Start tracing Python memory allocations.
1503
1504Also set the maximum number of frames stored in the traceback of a
1505trace to nframe.
1506[clinic start generated code]*/
1507
1508static PyObject *
Victor Stinnera7368ac2017-11-15 18:11:45 -08001509_tracemalloc_start_impl(PyObject *module, int nframe)
1510/*[clinic end generated code: output=caae05c23c159d3c input=40d849b5b29d1933]*/
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001511{
Victor Stinnera7368ac2017-11-15 18:11:45 -08001512 if (tracemalloc_start(nframe) < 0) {
Victor Stinner3728d6c2013-11-23 12:37:20 +01001513 return NULL;
1514 }
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001515 Py_RETURN_NONE;
1516}
1517
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001518
Serhiy Storchakab451f912017-02-04 12:18:38 +02001519/*[clinic input]
1520_tracemalloc.stop
Victor Stinnere492ae52016-03-22 12:58:23 +01001521
Serhiy Storchakab451f912017-02-04 12:18:38 +02001522Stop tracing Python memory allocations.
1523
1524Also clear traces of memory blocks allocated by Python.
1525[clinic start generated code]*/
1526
1527static PyObject *
1528_tracemalloc_stop_impl(PyObject *module)
1529/*[clinic end generated code: output=c3c42ae03e3955cd input=7478f075e51dae18]*/
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001530{
1531 tracemalloc_stop();
1532 Py_RETURN_NONE;
1533}
1534
Victor Stinnere492ae52016-03-22 12:58:23 +01001535
Serhiy Storchakab451f912017-02-04 12:18:38 +02001536/*[clinic input]
1537_tracemalloc.get_traceback_limit
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001538
Serhiy Storchakab451f912017-02-04 12:18:38 +02001539Get the maximum number of frames stored in the traceback of a trace.
1540
1541By default, a trace of an allocated memory block only stores
1542the most recent frame: the limit is 1.
1543[clinic start generated code]*/
1544
1545static PyObject *
1546_tracemalloc_get_traceback_limit_impl(PyObject *module)
1547/*[clinic end generated code: output=d556d9306ba95567 input=da3cd977fc68ae3b]*/
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001548{
Victor Stinner9e00e802018-10-25 13:31:16 +02001549 return PyLong_FromLong(_Py_tracemalloc_config.max_nframe);
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001550}
1551
Victor Stinnere492ae52016-03-22 12:58:23 +01001552
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001553
Serhiy Storchakab451f912017-02-04 12:18:38 +02001554/*[clinic input]
1555_tracemalloc.get_tracemalloc_memory
1556
1557Get the memory usage in bytes of the tracemalloc module.
1558
1559This memory is used internally to trace memory allocations.
1560[clinic start generated code]*/
1561
1562static PyObject *
1563_tracemalloc_get_tracemalloc_memory_impl(PyObject *module)
1564/*[clinic end generated code: output=e3f14e280a55f5aa input=5d919c0f4d5132ad]*/
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001565{
1566 size_t size;
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001567
1568 size = _Py_hashtable_size(tracemalloc_tracebacks);
1569 size += _Py_hashtable_size(tracemalloc_filenames);
1570
1571 TABLES_LOCK();
1572 size += _Py_hashtable_size(tracemalloc_traces);
1573 TABLES_UNLOCK();
1574
Serhiy Storchakab451f912017-02-04 12:18:38 +02001575 return PyLong_FromSize_t(size);
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001576}
1577
Victor Stinnere492ae52016-03-22 12:58:23 +01001578
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001579
Serhiy Storchakab451f912017-02-04 12:18:38 +02001580/*[clinic input]
1581_tracemalloc.get_traced_memory
1582
1583Get the current size and peak size of memory blocks traced by tracemalloc.
1584
1585Returns a tuple: (current: int, peak: int).
1586[clinic start generated code]*/
1587
1588static PyObject *
1589_tracemalloc_get_traced_memory_impl(PyObject *module)
1590/*[clinic end generated code: output=5b167189adb9e782 input=61ddb5478400ff66]*/
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001591{
Victor Stinner3c0481d2013-11-27 21:39:49 +01001592 Py_ssize_t size, peak_size;
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001593
Victor Stinner9e00e802018-10-25 13:31:16 +02001594 if (!_Py_tracemalloc_config.tracing)
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001595 return Py_BuildValue("ii", 0, 0);
1596
1597 TABLES_LOCK();
1598 size = tracemalloc_traced_memory;
Victor Stinner3c0481d2013-11-27 21:39:49 +01001599 peak_size = tracemalloc_peak_traced_memory;
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001600 TABLES_UNLOCK();
1601
Serhiy Storchakab451f912017-02-04 12:18:38 +02001602 return Py_BuildValue("nn", size, peak_size);
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001603}
1604
Victor Stinnere492ae52016-03-22 12:58:23 +01001605
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001606static PyMethodDef module_methods[] = {
Serhiy Storchakab451f912017-02-04 12:18:38 +02001607 _TRACEMALLOC_IS_TRACING_METHODDEF
1608 _TRACEMALLOC_CLEAR_TRACES_METHODDEF
1609 _TRACEMALLOC__GET_TRACES_METHODDEF
1610 _TRACEMALLOC__GET_OBJECT_TRACEBACK_METHODDEF
1611 _TRACEMALLOC_START_METHODDEF
1612 _TRACEMALLOC_STOP_METHODDEF
1613 _TRACEMALLOC_GET_TRACEBACK_LIMIT_METHODDEF
1614 _TRACEMALLOC_GET_TRACEMALLOC_MEMORY_METHODDEF
1615 _TRACEMALLOC_GET_TRACED_MEMORY_METHODDEF
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001616 /* sentinel */
1617 {NULL, NULL}
1618};
1619
1620PyDoc_STRVAR(module_doc,
1621"Debug module to trace memory blocks allocated by Python.");
1622
1623static struct PyModuleDef module_def = {
1624 PyModuleDef_HEAD_INIT,
1625 "_tracemalloc",
1626 module_doc,
1627 0, /* non-negative size to be able to unload the module */
1628 module_methods,
1629 NULL,
1630};
1631
1632PyMODINIT_FUNC
1633PyInit__tracemalloc(void)
1634{
1635 PyObject *m;
1636 m = PyModule_Create(&module_def);
1637 if (m == NULL)
1638 return NULL;
1639
Miss Islington (bot)daf7a082019-11-20 02:26:48 -08001640 if (tracemalloc_init() < 0) {
1641 Py_DECREF(m);
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001642 return NULL;
Miss Islington (bot)daf7a082019-11-20 02:26:48 -08001643 }
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001644
1645 return m;
1646}
1647
Victor Stinnere492ae52016-03-22 12:58:23 +01001648
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001649int
Victor Stinnera7368ac2017-11-15 18:11:45 -08001650_PyTraceMalloc_Init(int nframe)
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001651{
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001652 assert(PyGILState_Check());
Victor Stinnera7368ac2017-11-15 18:11:45 -08001653 if (nframe == 0) {
1654 return 0;
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001655 }
Victor Stinnerf28ce602013-11-27 22:27:13 +01001656 return tracemalloc_start(nframe);
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001657}
1658
Victor Stinnere492ae52016-03-22 12:58:23 +01001659
Victor Stinnerbe0708f2013-12-01 10:03:26 +01001660void
1661_PyTraceMalloc_Fini(void)
1662{
Victor Stinnerbe0708f2013-12-01 10:03:26 +01001663 assert(PyGILState_Check());
Victor Stinnerbe0708f2013-12-01 10:03:26 +01001664 tracemalloc_deinit();
1665}
Victor Stinner10b73e12016-03-22 13:39:05 +01001666
1667int
Victor Stinner5ea4c062017-06-20 17:46:36 +02001668PyTraceMalloc_Track(unsigned int domain, uintptr_t ptr,
1669 size_t size)
Victor Stinner10b73e12016-03-22 13:39:05 +01001670{
1671 int res;
Victor Stinner10b73e12016-03-22 13:39:05 +01001672 PyGILState_STATE gil_state;
Victor Stinner10b73e12016-03-22 13:39:05 +01001673
Victor Stinner9e00e802018-10-25 13:31:16 +02001674 if (!_Py_tracemalloc_config.tracing) {
Victor Stinner10b73e12016-03-22 13:39:05 +01001675 /* tracemalloc is not tracing: do nothing */
1676 return -2;
1677 }
1678
Victor Stinner10b73e12016-03-22 13:39:05 +01001679 gil_state = PyGILState_Ensure();
Victor Stinner10b73e12016-03-22 13:39:05 +01001680
1681 TABLES_LOCK();
1682 res = tracemalloc_add_trace(domain, ptr, size);
1683 TABLES_UNLOCK();
1684
Victor Stinner10b73e12016-03-22 13:39:05 +01001685 PyGILState_Release(gil_state);
Victor Stinner10b73e12016-03-22 13:39:05 +01001686 return res;
1687}
1688
1689
1690int
Victor Stinner5ea4c062017-06-20 17:46:36 +02001691PyTraceMalloc_Untrack(unsigned int domain, uintptr_t ptr)
Victor Stinner10b73e12016-03-22 13:39:05 +01001692{
Victor Stinner9e00e802018-10-25 13:31:16 +02001693 if (!_Py_tracemalloc_config.tracing) {
Victor Stinner10b73e12016-03-22 13:39:05 +01001694 /* tracemalloc is not tracing: do nothing */
1695 return -2;
1696 }
1697
1698 TABLES_LOCK();
1699 tracemalloc_remove_trace(domain, ptr);
1700 TABLES_UNLOCK();
1701
1702 return 0;
1703}
1704
1705
Victor Stinner9e00e802018-10-25 13:31:16 +02001706/* If the object memory block is already traced, update its trace
1707 with the current Python traceback.
1708
1709 Do nothing if tracemalloc is not tracing memory allocations
1710 or if the object memory block is not already traced. */
1711int
1712_PyTraceMalloc_NewReference(PyObject *op)
1713{
1714 assert(PyGILState_Check());
1715
1716 if (!_Py_tracemalloc_config.tracing) {
1717 /* tracemalloc is not tracing: do nothing */
1718 return -1;
1719 }
1720
1721 uintptr_t ptr;
1722 PyTypeObject *type = Py_TYPE(op);
1723 if (PyType_IS_GC(type)) {
1724 ptr = (uintptr_t)((char *)op - sizeof(PyGC_Head));
1725 }
1726 else {
1727 ptr = (uintptr_t)op;
1728 }
1729
1730 _Py_hashtable_entry_t* entry;
1731 int res = -1;
1732
1733 TABLES_LOCK();
1734 if (_Py_tracemalloc_config.use_domain) {
1735 pointer_t key = {ptr, DEFAULT_DOMAIN};
1736 entry = _Py_HASHTABLE_GET_ENTRY(tracemalloc_traces, key);
1737 }
1738 else {
1739 entry = _Py_HASHTABLE_GET_ENTRY(tracemalloc_traces, ptr);
1740 }
1741
1742 if (entry != NULL) {
1743 /* update the traceback of the memory block */
1744 traceback_t *traceback = traceback_new();
1745 if (traceback != NULL) {
1746 trace_t trace;
1747 _Py_HASHTABLE_ENTRY_READ_DATA(tracemalloc_traces, entry, trace);
1748 trace.traceback = traceback;
1749 _Py_HASHTABLE_ENTRY_WRITE_DATA(tracemalloc_traces, entry, trace);
1750 res = 0;
1751 }
1752 }
1753 /* else: cannot track the object, its memory block size is unknown */
1754 TABLES_UNLOCK();
1755
1756 return res;
1757}
1758
1759
Victor Stinner10b73e12016-03-22 13:39:05 +01001760PyObject*
Victor Stinner5ea4c062017-06-20 17:46:36 +02001761_PyTraceMalloc_GetTraceback(unsigned int domain, uintptr_t ptr)
Victor Stinner10b73e12016-03-22 13:39:05 +01001762{
1763 traceback_t *traceback;
1764
1765 traceback = tracemalloc_get_traceback(domain, ptr);
1766 if (traceback == NULL)
1767 Py_RETURN_NONE;
1768
1769 return traceback_to_pyobject(traceback, NULL);
1770}