blob: 211c6fbb8bcef8bef928f9b5c5f24eddf7c7eabc [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
Joannah Nanjekye2bc43cd2019-09-05 13:06:49 -030037 would introduce a deadlock in _PyThreadState_DeleteCurrent(). */
Victor Stinnered3b0bc2013-11-23 12:27:24 +010038static 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;
Julien Danjou8d59eb12019-10-15 14:00:16 +020081 /* Number of frames stored */
82 uint16_t nframe;
83 /* Total number of frames the traceback had */
84 uint16_t total_nframe;
Victor Stinnered3b0bc2013-11-23 12:27:24 +010085 frame_t frames[1];
86} traceback_t;
87
88#define TRACEBACK_SIZE(NFRAME) \
89 (sizeof(traceback_t) + sizeof(frame_t) * (NFRAME - 1))
Victor Stinnerf28ce602013-11-27 22:27:13 +010090
Julien Danjou8d59eb12019-10-15 14:00:16 +020091/* The maximum number of frames is either:
92 - The maximum number of frames we can store in `traceback_t.nframe`
93 - The maximum memory size_t we can allocate */
94static 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 +010095
Victor Stinnere492ae52016-03-22 12:58:23 +010096
Victor Stinnered3b0bc2013-11-23 12:27:24 +010097static PyObject *unknown_filename = NULL;
98static traceback_t tracemalloc_empty_traceback;
99
Victor Stinner7a5be142013-11-26 01:06:02 +0100100/* Trace of a memory block */
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100101typedef struct {
Victor Stinner7a5be142013-11-26 01:06:02 +0100102 /* Size of the memory block in bytes */
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100103 size_t size;
Victor Stinner7a5be142013-11-26 01:06:02 +0100104
105 /* Traceback where the memory block was allocated */
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100106 traceback_t *traceback;
107} trace_t;
108
Victor Stinnere492ae52016-03-22 12:58:23 +0100109
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100110/* Size in bytes of currently traced memory.
111 Protected by TABLES_LOCK(). */
112static size_t tracemalloc_traced_memory = 0;
113
Victor Stinner3c0481d2013-11-27 21:39:49 +0100114/* Peak size in bytes of traced memory.
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100115 Protected by TABLES_LOCK(). */
Victor Stinner3c0481d2013-11-27 21:39:49 +0100116static size_t tracemalloc_peak_traced_memory = 0;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100117
Serhiy Storchaka56a6d852014-12-01 18:28:43 +0200118/* Hash table used as a set to intern filenames:
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100119 PyObject* => PyObject*.
120 Protected by the GIL */
121static _Py_hashtable_t *tracemalloc_filenames = NULL;
122
Victor Stinnerf28ce602013-11-27 22:27:13 +0100123/* Buffer to store a new traceback in traceback_new().
124 Protected by the GIL. */
125static traceback_t *tracemalloc_traceback = NULL;
126
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100127/* Hash table used as a set to intern tracebacks:
128 traceback_t* => traceback_t*
129 Protected by the GIL */
130static _Py_hashtable_t *tracemalloc_tracebacks = NULL;
131
132/* pointer (void*) => trace (trace_t).
133 Protected by TABLES_LOCK(). */
134static _Py_hashtable_t *tracemalloc_traces = NULL;
135
Victor Stinnere492ae52016-03-22 12:58:23 +0100136
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100137#ifdef TRACE_DEBUG
138static void
139tracemalloc_error(const char *format, ...)
140{
141 va_list ap;
142 fprintf(stderr, "tracemalloc: ");
143 va_start(ap, format);
144 vfprintf(stderr, format, ap);
145 va_end(ap);
146 fprintf(stderr, "\n");
147 fflush(stderr);
148}
149#endif
150
Victor Stinnere492ae52016-03-22 12:58:23 +0100151
Antoine Pitroua6a4dc82017-09-07 18:56:24 +0200152#if defined(TRACE_RAW_MALLOC)
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100153#define REENTRANT_THREADLOCAL
154
Masayuki Yamamoto731e1892017-10-06 19:41:34 +0900155static Py_tss_t tracemalloc_reentrant_key = Py_tss_NEEDS_INIT;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100156
157/* Any non-NULL pointer can be used */
158#define REENTRANT Py_True
159
160static int
161get_reentrant(void)
162{
Victor Stinner4a066472016-03-22 17:45:09 +0100163 void *ptr;
164
Masayuki Yamamoto731e1892017-10-06 19:41:34 +0900165 assert(PyThread_tss_is_created(&tracemalloc_reentrant_key));
166 ptr = PyThread_tss_get(&tracemalloc_reentrant_key);
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100167 if (ptr != NULL) {
168 assert(ptr == REENTRANT);
169 return 1;
170 }
171 else
172 return 0;
173}
174
175static void
176set_reentrant(int reentrant)
177{
Victor Stinner2ead3d22013-11-26 01:08:53 +0100178 assert(reentrant == 0 || reentrant == 1);
Masayuki Yamamoto731e1892017-10-06 19:41:34 +0900179 assert(PyThread_tss_is_created(&tracemalloc_reentrant_key));
Victor Stinner4a066472016-03-22 17:45:09 +0100180
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100181 if (reentrant) {
Victor Stinner0cfc0582016-03-22 17:40:07 +0100182 assert(!get_reentrant());
Masayuki Yamamoto731e1892017-10-06 19:41:34 +0900183 PyThread_tss_set(&tracemalloc_reentrant_key, REENTRANT);
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100184 }
185 else {
Victor Stinner0cfc0582016-03-22 17:40:07 +0100186 assert(get_reentrant());
Masayuki Yamamoto731e1892017-10-06 19:41:34 +0900187 PyThread_tss_set(&tracemalloc_reentrant_key, NULL);
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100188 }
189}
190
191#else
192
Antoine Pitroua6a4dc82017-09-07 18:56:24 +0200193/* TRACE_RAW_MALLOC not defined: variable protected by the GIL */
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100194static int tracemalloc_reentrant = 0;
195
196static int
197get_reentrant(void)
198{
199 return tracemalloc_reentrant;
200}
201
202static void
203set_reentrant(int reentrant)
204{
Victor Stinnerd5871e62016-03-23 00:17:04 +0100205 assert(reentrant != tracemalloc_reentrant);
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100206 tracemalloc_reentrant = reentrant;
207}
208#endif
209
Victor Stinnere492ae52016-03-22 12:58:23 +0100210
Victor Stinner285cf0a2016-03-21 22:00:58 +0100211static Py_uhash_t
Victor Stinner5dacbd42016-03-23 09:52:13 +0100212hashtable_hash_pyobject(_Py_hashtable_t *ht, const void *pkey)
Victor Stinner51b846c2016-03-18 21:52:22 +0100213{
Victor Stinner285cf0a2016-03-21 22:00:58 +0100214 PyObject *obj;
215
Victor Stinner5dacbd42016-03-23 09:52:13 +0100216 _Py_HASHTABLE_READ_KEY(ht, pkey, obj);
Victor Stinner285cf0a2016-03-21 22:00:58 +0100217 return PyObject_Hash(obj);
218}
219
Victor Stinnere492ae52016-03-22 12:58:23 +0100220
Victor Stinner285cf0a2016-03-21 22:00:58 +0100221static int
Victor Stinner5dacbd42016-03-23 09:52:13 +0100222hashtable_compare_unicode(_Py_hashtable_t *ht, const void *pkey,
Victor Stinner285cf0a2016-03-21 22:00:58 +0100223 const _Py_hashtable_entry_t *entry)
224{
Victor Stinnere492ae52016-03-22 12:58:23 +0100225 PyObject *key1, *key2;
Victor Stinner285cf0a2016-03-21 22:00:58 +0100226
Victor Stinner5dacbd42016-03-23 09:52:13 +0100227 _Py_HASHTABLE_READ_KEY(ht, pkey, key1);
228 _Py_HASHTABLE_ENTRY_READ_KEY(ht, entry, key2);
Victor Stinner285cf0a2016-03-21 22:00:58 +0100229
Victor Stinnere492ae52016-03-22 12:58:23 +0100230 if (key1 != NULL && key2 != NULL)
231 return (PyUnicode_Compare(key1, key2) == 0);
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100232 else
Victor Stinnere492ae52016-03-22 12:58:23 +0100233 return key1 == key2;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100234}
235
Victor Stinnere492ae52016-03-22 12:58:23 +0100236
237static Py_uhash_t
Victor Stinner5dacbd42016-03-23 09:52:13 +0100238hashtable_hash_pointer_t(_Py_hashtable_t *ht, const void *pkey)
Victor Stinnere492ae52016-03-22 12:58:23 +0100239{
240 pointer_t ptr;
241 Py_uhash_t hash;
242
Victor Stinner5dacbd42016-03-23 09:52:13 +0100243 _Py_HASHTABLE_READ_KEY(ht, pkey, ptr);
Victor Stinnere492ae52016-03-22 12:58:23 +0100244
245 hash = (Py_uhash_t)_Py_HashPointer((void*)ptr.ptr);
246 hash ^= ptr.domain;
247 return hash;
248}
249
250
doko@ubuntu.combc731502016-05-18 01:06:01 +0200251static int
Victor Stinner5dacbd42016-03-23 09:52:13 +0100252hashtable_compare_pointer_t(_Py_hashtable_t *ht, const void *pkey,
Victor Stinnere492ae52016-03-22 12:58:23 +0100253 const _Py_hashtable_entry_t *entry)
254{
255 pointer_t ptr1, ptr2;
256
Victor Stinner5dacbd42016-03-23 09:52:13 +0100257 _Py_HASHTABLE_READ_KEY(ht, pkey, ptr1);
258 _Py_HASHTABLE_ENTRY_READ_KEY(ht, entry, ptr2);
Victor Stinnere492ae52016-03-22 12:58:23 +0100259
260 /* compare pointer before domain, because pointer is more likely to be
261 different */
262 return (ptr1.ptr == ptr2.ptr && ptr1.domain == ptr2.domain);
263
264}
265
266
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100267static _Py_hashtable_t *
Victor Stinner285cf0a2016-03-21 22:00:58 +0100268hashtable_new(size_t key_size, size_t data_size,
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100269 _Py_hashtable_hash_func hash_func,
270 _Py_hashtable_compare_func compare_func)
271{
Victor Stinnerc9553872016-03-22 12:13:01 +0100272 _Py_hashtable_allocator_t hashtable_alloc = {malloc, free};
Victor Stinner285cf0a2016-03-21 22:00:58 +0100273 return _Py_hashtable_new_full(key_size, data_size, 0,
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100274 hash_func, compare_func,
Victor Stinnerc9553872016-03-22 12:13:01 +0100275 &hashtable_alloc);
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100276}
277
Victor Stinnere492ae52016-03-22 12:58:23 +0100278
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100279static void*
280raw_malloc(size_t size)
281{
282 return allocators.raw.malloc(allocators.raw.ctx, size);
283}
284
285static void
286raw_free(void *ptr)
287{
288 allocators.raw.free(allocators.raw.ctx, ptr);
289}
290
Victor Stinnere492ae52016-03-22 12:58:23 +0100291
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100292static Py_uhash_t
Victor Stinner5dacbd42016-03-23 09:52:13 +0100293hashtable_hash_traceback(_Py_hashtable_t *ht, const void *pkey)
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100294{
Victor Stinnerb32a7ed2016-03-21 23:05:08 +0100295 traceback_t *traceback;
Victor Stinner285cf0a2016-03-21 22:00:58 +0100296
Victor Stinner5dacbd42016-03-23 09:52:13 +0100297 _Py_HASHTABLE_READ_KEY(ht, pkey, traceback);
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100298 return traceback->hash;
299}
300
Victor Stinnere492ae52016-03-22 12:58:23 +0100301
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100302static int
Victor Stinner5dacbd42016-03-23 09:52:13 +0100303hashtable_compare_traceback(_Py_hashtable_t *ht, const void *pkey,
304 const _Py_hashtable_entry_t *entry)
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100305{
Victor Stinner285cf0a2016-03-21 22:00:58 +0100306 traceback_t *traceback1, *traceback2;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100307 const frame_t *frame1, *frame2;
308 int i;
309
Victor Stinner5dacbd42016-03-23 09:52:13 +0100310 _Py_HASHTABLE_READ_KEY(ht, pkey, traceback1);
311 _Py_HASHTABLE_ENTRY_READ_KEY(ht, entry, traceback2);
Victor Stinner285cf0a2016-03-21 22:00:58 +0100312
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100313 if (traceback1->nframe != traceback2->nframe)
314 return 0;
315
Julien Danjou8d59eb12019-10-15 14:00:16 +0200316 if (traceback1->total_nframe != traceback2->total_nframe)
317 return 0;
318
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100319 for (i=0; i < traceback1->nframe; i++) {
320 frame1 = &traceback1->frames[i];
321 frame2 = &traceback2->frames[i];
322
323 if (frame1->lineno != frame2->lineno)
324 return 0;
325
326 if (frame1->filename != frame2->filename) {
327 assert(PyUnicode_Compare(frame1->filename, frame2->filename) != 0);
328 return 0;
329 }
330 }
331 return 1;
332}
333
Victor Stinnere492ae52016-03-22 12:58:23 +0100334
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100335static void
336tracemalloc_get_frame(PyFrameObject *pyframe, frame_t *frame)
337{
338 PyCodeObject *code;
339 PyObject *filename;
340 _Py_hashtable_entry_t *entry;
Victor Stinner95283342016-03-15 21:57:02 +0100341 int lineno;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100342
343 frame->filename = unknown_filename;
Victor Stinner95283342016-03-15 21:57:02 +0100344 lineno = PyFrame_GetLineNumber(pyframe);
345 if (lineno < 0)
346 lineno = 0;
347 frame->lineno = (unsigned int)lineno;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100348
349 code = pyframe->f_code;
350 if (code == NULL) {
351#ifdef TRACE_DEBUG
Victor Stinner4dc74202013-11-26 01:18:52 +0100352 tracemalloc_error("failed to get the code object of the frame");
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100353#endif
354 return;
355 }
356
357 if (code->co_filename == NULL) {
358#ifdef TRACE_DEBUG
359 tracemalloc_error("failed to get the filename of the code object");
360#endif
361 return;
362 }
363
364 filename = code->co_filename;
365 assert(filename != NULL);
366 if (filename == NULL)
367 return;
368
369 if (!PyUnicode_Check(filename)) {
370#ifdef TRACE_DEBUG
Martin Panter6245cb32016-04-15 02:14:19 +0000371 tracemalloc_error("filename is not a unicode string");
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100372#endif
373 return;
374 }
375 if (!PyUnicode_IS_READY(filename)) {
376 /* Don't make a Unicode string ready to avoid reentrant calls
377 to tracemalloc_malloc() or tracemalloc_realloc() */
378#ifdef TRACE_DEBUG
379 tracemalloc_error("filename is not a ready unicode string");
380#endif
381 return;
382 }
383
384 /* intern the filename */
Victor Stinner285cf0a2016-03-21 22:00:58 +0100385 entry = _Py_HASHTABLE_GET_ENTRY(tracemalloc_filenames, filename);
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100386 if (entry != NULL) {
Victor Stinner5dacbd42016-03-23 09:52:13 +0100387 _Py_HASHTABLE_ENTRY_READ_KEY(tracemalloc_filenames, entry, filename);
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100388 }
389 else {
390 /* tracemalloc_filenames is responsible to keep a reference
391 to the filename */
392 Py_INCREF(filename);
Victor Stinner285cf0a2016-03-21 22:00:58 +0100393 if (_Py_HASHTABLE_SET_NODATA(tracemalloc_filenames, filename) < 0) {
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100394 Py_DECREF(filename);
395#ifdef TRACE_DEBUG
396 tracemalloc_error("failed to intern the filename");
397#endif
398 return;
399 }
400 }
401
402 /* the tracemalloc_filenames table keeps a reference to the filename */
403 frame->filename = filename;
404}
405
Victor Stinnere492ae52016-03-22 12:58:23 +0100406
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100407static Py_uhash_t
408traceback_hash(traceback_t *traceback)
409{
410 /* code based on tuplehash() of Objects/tupleobject.c */
Victor Stinner4d8c29c2013-12-16 23:05:13 +0100411 Py_uhash_t x, y; /* Unsigned for defined overflow behavior. */
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100412 int len = traceback->nframe;
413 Py_uhash_t mult = _PyHASH_MULTIPLIER;
414 frame_t *frame;
415
416 x = 0x345678UL;
417 frame = traceback->frames;
418 while (--len >= 0) {
Victor Stinner4d8c29c2013-12-16 23:05:13 +0100419 y = (Py_uhash_t)PyObject_Hash(frame->filename);
420 y ^= (Py_uhash_t)frame->lineno;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100421 frame++;
422
423 x = (x ^ y) * mult;
424 /* the cast might truncate len; that doesn't change hash stability */
Victor Stinner4d8c29c2013-12-16 23:05:13 +0100425 mult += (Py_uhash_t)(82520UL + len + len);
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100426 }
Julien Danjou8d59eb12019-10-15 14:00:16 +0200427 x ^= traceback->total_nframe;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100428 x += 97531UL;
429 return x;
430}
431
Victor Stinnere492ae52016-03-22 12:58:23 +0100432
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100433static void
434traceback_get_frames(traceback_t *traceback)
435{
436 PyThreadState *tstate;
437 PyFrameObject *pyframe;
438
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100439 tstate = PyGILState_GetThisThreadState();
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100440 if (tstate == NULL) {
441#ifdef TRACE_DEBUG
442 tracemalloc_error("failed to get the current thread state");
443#endif
444 return;
445 }
446
447 for (pyframe = tstate->frame; pyframe != NULL; pyframe = pyframe->f_back) {
Julien Danjou8d59eb12019-10-15 14:00:16 +0200448 if (traceback->nframe < _Py_tracemalloc_config.max_nframe) {
449 tracemalloc_get_frame(pyframe, &traceback->frames[traceback->nframe]);
450 assert(traceback->frames[traceback->nframe].filename != NULL);
451 traceback->nframe++;
452 }
453 if (traceback->total_nframe < UINT16_MAX)
454 traceback->total_nframe++;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100455 }
456}
457
Victor Stinnere492ae52016-03-22 12:58:23 +0100458
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100459static traceback_t *
460traceback_new(void)
461{
Victor Stinnerf28ce602013-11-27 22:27:13 +0100462 traceback_t *traceback;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100463 _Py_hashtable_entry_t *entry;
464
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100465 assert(PyGILState_Check());
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100466
467 /* get frames */
Victor Stinnerf28ce602013-11-27 22:27:13 +0100468 traceback = tracemalloc_traceback;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100469 traceback->nframe = 0;
Julien Danjou8d59eb12019-10-15 14:00:16 +0200470 traceback->total_nframe = 0;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100471 traceback_get_frames(traceback);
472 if (traceback->nframe == 0)
473 return &tracemalloc_empty_traceback;
474 traceback->hash = traceback_hash(traceback);
475
476 /* intern the traceback */
Victor Stinner285cf0a2016-03-21 22:00:58 +0100477 entry = _Py_HASHTABLE_GET_ENTRY(tracemalloc_tracebacks, traceback);
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100478 if (entry != NULL) {
Victor Stinner5dacbd42016-03-23 09:52:13 +0100479 _Py_HASHTABLE_ENTRY_READ_KEY(tracemalloc_tracebacks, entry, traceback);
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100480 }
481 else {
482 traceback_t *copy;
483 size_t traceback_size;
484
485 traceback_size = TRACEBACK_SIZE(traceback->nframe);
486
487 copy = raw_malloc(traceback_size);
488 if (copy == NULL) {
489#ifdef TRACE_DEBUG
490 tracemalloc_error("failed to intern the traceback: malloc failed");
491#endif
492 return NULL;
493 }
494 memcpy(copy, traceback, traceback_size);
495
Victor Stinner285cf0a2016-03-21 22:00:58 +0100496 if (_Py_HASHTABLE_SET_NODATA(tracemalloc_tracebacks, copy) < 0) {
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100497 raw_free(copy);
498#ifdef TRACE_DEBUG
499 tracemalloc_error("failed to intern the traceback: putdata failed");
500#endif
501 return NULL;
502 }
503 traceback = copy;
504 }
505 return traceback;
506}
507
Victor Stinnere492ae52016-03-22 12:58:23 +0100508
Victor Stinner5e14a382016-03-23 22:03:55 +0100509static int
510tracemalloc_use_domain_cb(_Py_hashtable_t *old_traces,
511 _Py_hashtable_entry_t *entry, void *user_data)
512{
Benjamin Petersonca470632016-09-06 13:47:26 -0700513 uintptr_t ptr;
Victor Stinner5e14a382016-03-23 22:03:55 +0100514 pointer_t key;
515 _Py_hashtable_t *new_traces = (_Py_hashtable_t *)user_data;
516 const void *pdata = _Py_HASHTABLE_ENTRY_PDATA(old_traces, entry);
517
518 _Py_HASHTABLE_ENTRY_READ_KEY(old_traces, entry, ptr);
519 key.ptr = ptr;
520 key.domain = DEFAULT_DOMAIN;
521
522 return _Py_hashtable_set(new_traces,
523 sizeof(key), &key,
524 old_traces->data_size, pdata);
525}
526
527
Benjamin Petersonca470632016-09-06 13:47:26 -0700528/* Convert tracemalloc_traces from compact key (uintptr_t) to pointer_t key.
Victor Stinner5e14a382016-03-23 22:03:55 +0100529 * Return 0 on success, -1 on error. */
530static int
531tracemalloc_use_domain(void)
532{
533 _Py_hashtable_t *new_traces = NULL;
534
Victor Stinner9e00e802018-10-25 13:31:16 +0200535 assert(!_Py_tracemalloc_config.use_domain);
Victor Stinner5e14a382016-03-23 22:03:55 +0100536
537 new_traces = hashtable_new(sizeof(pointer_t),
538 sizeof(trace_t),
539 hashtable_hash_pointer_t,
540 hashtable_compare_pointer_t);
541 if (new_traces == NULL) {
542 return -1;
543 }
544
545 if (_Py_hashtable_foreach(tracemalloc_traces, tracemalloc_use_domain_cb,
546 new_traces) < 0)
547 {
548 _Py_hashtable_destroy(new_traces);
549 return -1;
550 }
551
552 _Py_hashtable_destroy(tracemalloc_traces);
553 tracemalloc_traces = new_traces;
554
Victor Stinner9e00e802018-10-25 13:31:16 +0200555 _Py_tracemalloc_config.use_domain = 1;
Victor Stinner5e14a382016-03-23 22:03:55 +0100556
557 return 0;
558}
559
560
Victor Stinnere492ae52016-03-22 12:58:23 +0100561static void
Victor Stinner5ea4c062017-06-20 17:46:36 +0200562tracemalloc_remove_trace(unsigned int domain, uintptr_t ptr)
Victor Stinnere492ae52016-03-22 12:58:23 +0100563{
564 trace_t trace;
565 int removed;
566
Victor Stinner9e00e802018-10-25 13:31:16 +0200567 assert(_Py_tracemalloc_config.tracing);
Victor Stinner10b73e12016-03-22 13:39:05 +0100568
Victor Stinner9e00e802018-10-25 13:31:16 +0200569 if (_Py_tracemalloc_config.use_domain) {
Victor Stinnere492ae52016-03-22 12:58:23 +0100570 pointer_t key = {ptr, domain};
571 removed = _Py_HASHTABLE_POP(tracemalloc_traces, key, trace);
572 }
573 else {
574 removed = _Py_HASHTABLE_POP(tracemalloc_traces, ptr, trace);
575 }
576 if (!removed) {
577 return;
578 }
579
580 assert(tracemalloc_traced_memory >= trace.size);
581 tracemalloc_traced_memory -= trace.size;
582}
583
584#define REMOVE_TRACE(ptr) \
Benjamin Petersonca470632016-09-06 13:47:26 -0700585 tracemalloc_remove_trace(DEFAULT_DOMAIN, (uintptr_t)(ptr))
Victor Stinnere492ae52016-03-22 12:58:23 +0100586
587
Victor Stinner52968672013-11-24 11:37:15 +0100588static int
Victor Stinner5ea4c062017-06-20 17:46:36 +0200589tracemalloc_add_trace(unsigned int domain, uintptr_t ptr,
Victor Stinner10b73e12016-03-22 13:39:05 +0100590 size_t size)
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100591{
Victor Stinnerca79ccd2016-03-23 09:38:54 +0100592 pointer_t key = {ptr, domain};
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100593 traceback_t *traceback;
594 trace_t trace;
Victor Stinnerca79ccd2016-03-23 09:38:54 +0100595 _Py_hashtable_entry_t* entry;
Victor Stinner52968672013-11-24 11:37:15 +0100596 int res;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100597
Victor Stinner9e00e802018-10-25 13:31:16 +0200598 assert(_Py_tracemalloc_config.tracing);
Victor Stinner10b73e12016-03-22 13:39:05 +0100599
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100600 traceback = traceback_new();
Victor Stinnere492ae52016-03-22 12:58:23 +0100601 if (traceback == NULL) {
Victor Stinner52968672013-11-24 11:37:15 +0100602 return -1;
Victor Stinnere492ae52016-03-22 12:58:23 +0100603 }
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100604
Victor Stinner9e00e802018-10-25 13:31:16 +0200605 if (!_Py_tracemalloc_config.use_domain && domain != DEFAULT_DOMAIN) {
Victor Stinner5e14a382016-03-23 22:03:55 +0100606 /* first trace using a non-zero domain whereas traces use compact
Benjamin Petersonca470632016-09-06 13:47:26 -0700607 (uintptr_t) keys: switch to pointer_t keys. */
Victor Stinner5e14a382016-03-23 22:03:55 +0100608 if (tracemalloc_use_domain() < 0) {
609 return -1;
610 }
611 }
612
Victor Stinner9e00e802018-10-25 13:31:16 +0200613 if (_Py_tracemalloc_config.use_domain) {
Victor Stinnerca79ccd2016-03-23 09:38:54 +0100614 entry = _Py_HASHTABLE_GET_ENTRY(tracemalloc_traces, key);
Victor Stinnere492ae52016-03-22 12:58:23 +0100615 }
616 else {
Victor Stinnerca79ccd2016-03-23 09:38:54 +0100617 entry = _Py_HASHTABLE_GET_ENTRY(tracemalloc_traces, ptr);
Victor Stinnerd606ba72013-11-24 11:28:20 +0100618 }
Victor Stinner52968672013-11-24 11:37:15 +0100619
Victor Stinnerca79ccd2016-03-23 09:38:54 +0100620 if (entry != NULL) {
621 /* the memory block is already tracked */
622 _Py_HASHTABLE_ENTRY_READ_DATA(tracemalloc_traces, entry, trace);
623 assert(tracemalloc_traced_memory >= trace.size);
624 tracemalloc_traced_memory -= trace.size;
625
626 trace.size = size;
627 trace.traceback = traceback;
628 _Py_HASHTABLE_ENTRY_WRITE_DATA(tracemalloc_traces, entry, trace);
629 }
630 else {
631 trace.size = size;
632 trace.traceback = traceback;
633
Victor Stinner9e00e802018-10-25 13:31:16 +0200634 if (_Py_tracemalloc_config.use_domain) {
Victor Stinnerca79ccd2016-03-23 09:38:54 +0100635 res = _Py_HASHTABLE_SET(tracemalloc_traces, key, trace);
636 }
637 else {
638 res = _Py_HASHTABLE_SET(tracemalloc_traces, ptr, trace);
639 }
640 if (res != 0) {
641 return res;
642 }
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100643 }
Victor Stinnere492ae52016-03-22 12:58:23 +0100644
Benjamin Peterson2f8bfef2016-09-07 09:26:18 -0700645 assert(tracemalloc_traced_memory <= SIZE_MAX - size);
Victor Stinnere492ae52016-03-22 12:58:23 +0100646 tracemalloc_traced_memory += size;
647 if (tracemalloc_traced_memory > tracemalloc_peak_traced_memory)
648 tracemalloc_peak_traced_memory = tracemalloc_traced_memory;
649 return 0;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100650}
651
Victor Stinnere492ae52016-03-22 12:58:23 +0100652#define ADD_TRACE(ptr, size) \
Benjamin Petersonca470632016-09-06 13:47:26 -0700653 tracemalloc_add_trace(DEFAULT_DOMAIN, (uintptr_t)(ptr), size)
Victor Stinnere492ae52016-03-22 12:58:23 +0100654
655
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100656static void*
Victor Stinnerdb067af2014-05-02 22:31:14 +0200657tracemalloc_alloc(int use_calloc, void *ctx, size_t nelem, size_t elsize)
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100658{
Victor Stinnerd8f0d922014-06-02 21:57:10 +0200659 PyMemAllocatorEx *alloc = (PyMemAllocatorEx *)ctx;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100660 void *ptr;
661
Benjamin Peterson2f8bfef2016-09-07 09:26:18 -0700662 assert(elsize == 0 || nelem <= SIZE_MAX / elsize);
Victor Stinnerdb067af2014-05-02 22:31:14 +0200663
664 if (use_calloc)
665 ptr = alloc->calloc(alloc->ctx, nelem, elsize);
666 else
667 ptr = alloc->malloc(alloc->ctx, nelem * elsize);
Victor Stinner15116802013-12-04 01:29:35 +0100668 if (ptr == NULL)
669 return NULL;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100670
Victor Stinner88c29872013-12-04 01:47:46 +0100671 TABLES_LOCK();
Victor Stinnere492ae52016-03-22 12:58:23 +0100672 if (ADD_TRACE(ptr, nelem * elsize) < 0) {
Victor Stinner15116802013-12-04 01:29:35 +0100673 /* Failed to allocate a trace for the new memory block */
Victor Stinner88c29872013-12-04 01:47:46 +0100674 TABLES_UNLOCK();
Victor Stinner15116802013-12-04 01:29:35 +0100675 alloc->free(alloc->ctx, ptr);
676 return NULL;
Victor Stinner52968672013-11-24 11:37:15 +0100677 }
Victor Stinner88c29872013-12-04 01:47:46 +0100678 TABLES_UNLOCK();
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100679 return ptr;
680}
681
Victor Stinnere492ae52016-03-22 12:58:23 +0100682
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100683static void*
Victor Stinner15116802013-12-04 01:29:35 +0100684tracemalloc_realloc(void *ctx, void *ptr, size_t new_size)
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100685{
Victor Stinnerd8f0d922014-06-02 21:57:10 +0200686 PyMemAllocatorEx *alloc = (PyMemAllocatorEx *)ctx;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100687 void *ptr2;
688
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100689 ptr2 = alloc->realloc(alloc->ctx, ptr, new_size);
Victor Stinner15116802013-12-04 01:29:35 +0100690 if (ptr2 == NULL)
691 return NULL;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100692
Victor Stinner15116802013-12-04 01:29:35 +0100693 if (ptr != NULL) {
694 /* an existing memory block has been resized */
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100695
Victor Stinner88c29872013-12-04 01:47:46 +0100696 TABLES_LOCK();
Victor Stinner42bcf372016-03-23 09:08:08 +0100697
698 /* tracemalloc_add_trace() updates the trace if there is already
699 a trace at address (domain, ptr2) */
700 if (ptr2 != ptr) {
701 REMOVE_TRACE(ptr);
702 }
Victor Stinner08facd22013-11-24 12:27:59 +0100703
Victor Stinnere492ae52016-03-22 12:58:23 +0100704 if (ADD_TRACE(ptr2, new_size) < 0) {
Victor Stinner15116802013-12-04 01:29:35 +0100705 /* Memory allocation failed. The error cannot be reported to
Raymond Hettinger15f44ab2016-08-30 10:47:49 -0700706 the caller, because realloc() may already have shrunk the
Victor Stinner15116802013-12-04 01:29:35 +0100707 memory block and so removed bytes.
708
Serhiy Storchaka6a7b3a72016-04-17 08:32:47 +0300709 This case is very unlikely: a hash entry has just been
Victor Stinner88c29872013-12-04 01:47:46 +0100710 released, so the hash table should have at least one free entry.
711
712 The GIL and the table lock ensures that only one thread is
713 allocating memory. */
Barry Warsawb2e57942017-09-14 18:13:16 -0700714 Py_UNREACHABLE();
Victor Stinner52968672013-11-24 11:37:15 +0100715 }
Victor Stinner88c29872013-12-04 01:47:46 +0100716 TABLES_UNLOCK();
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100717 }
Victor Stinner15116802013-12-04 01:29:35 +0100718 else {
719 /* new allocation */
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100720
Victor Stinner88c29872013-12-04 01:47:46 +0100721 TABLES_LOCK();
Victor Stinnere492ae52016-03-22 12:58:23 +0100722 if (ADD_TRACE(ptr2, new_size) < 0) {
Victor Stinner15116802013-12-04 01:29:35 +0100723 /* Failed to allocate a trace for the new memory block */
Victor Stinner88c29872013-12-04 01:47:46 +0100724 TABLES_UNLOCK();
Victor Stinner15116802013-12-04 01:29:35 +0100725 alloc->free(alloc->ctx, ptr2);
726 return NULL;
727 }
Victor Stinner88c29872013-12-04 01:47:46 +0100728 TABLES_UNLOCK();
Victor Stinner15116802013-12-04 01:29:35 +0100729 }
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100730 return ptr2;
731}
732
Victor Stinnere492ae52016-03-22 12:58:23 +0100733
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100734static void
735tracemalloc_free(void *ctx, void *ptr)
736{
Victor Stinnerd8f0d922014-06-02 21:57:10 +0200737 PyMemAllocatorEx *alloc = (PyMemAllocatorEx *)ctx;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100738
739 if (ptr == NULL)
740 return;
741
742 /* GIL cannot be locked in PyMem_RawFree() because it would introduce
Joannah Nanjekye2bc43cd2019-09-05 13:06:49 -0300743 a deadlock in _PyThreadState_DeleteCurrent(). */
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100744
745 alloc->free(alloc->ctx, ptr);
Victor Stinner88c29872013-12-04 01:47:46 +0100746
747 TABLES_LOCK();
Victor Stinnere492ae52016-03-22 12:58:23 +0100748 REMOVE_TRACE(ptr);
Victor Stinner88c29872013-12-04 01:47:46 +0100749 TABLES_UNLOCK();
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100750}
751
Victor Stinnere492ae52016-03-22 12:58:23 +0100752
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100753static void*
Victor Stinnerdb067af2014-05-02 22:31:14 +0200754tracemalloc_alloc_gil(int use_calloc, void *ctx, size_t nelem, size_t elsize)
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100755{
Victor Stinner15116802013-12-04 01:29:35 +0100756 void *ptr;
757
758 if (get_reentrant()) {
Victor Stinnerd8f0d922014-06-02 21:57:10 +0200759 PyMemAllocatorEx *alloc = (PyMemAllocatorEx *)ctx;
Victor Stinnerdb067af2014-05-02 22:31:14 +0200760 if (use_calloc)
761 return alloc->calloc(alloc->ctx, nelem, elsize);
762 else
763 return alloc->malloc(alloc->ctx, nelem * elsize);
Victor Stinner15116802013-12-04 01:29:35 +0100764 }
765
766 /* Ignore reentrant call. PyObjet_Malloc() calls PyMem_Malloc() for
767 allocations larger than 512 bytes, don't trace the same memory
768 allocation twice. */
769 set_reentrant(1);
770
Victor Stinnerdb067af2014-05-02 22:31:14 +0200771 ptr = tracemalloc_alloc(use_calloc, ctx, nelem, elsize);
Victor Stinner15116802013-12-04 01:29:35 +0100772
773 set_reentrant(0);
774 return ptr;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100775}
776
Victor Stinnere492ae52016-03-22 12:58:23 +0100777
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100778static void*
Victor Stinnerdb067af2014-05-02 22:31:14 +0200779tracemalloc_malloc_gil(void *ctx, size_t size)
780{
781 return tracemalloc_alloc_gil(0, ctx, 1, size);
782}
783
Victor Stinnere492ae52016-03-22 12:58:23 +0100784
Victor Stinnerdb067af2014-05-02 22:31:14 +0200785static void*
786tracemalloc_calloc_gil(void *ctx, size_t nelem, size_t elsize)
787{
788 return tracemalloc_alloc_gil(1, ctx, nelem, elsize);
789}
790
Victor Stinnere492ae52016-03-22 12:58:23 +0100791
Victor Stinnerdb067af2014-05-02 22:31:14 +0200792static void*
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100793tracemalloc_realloc_gil(void *ctx, void *ptr, size_t new_size)
794{
Victor Stinner15116802013-12-04 01:29:35 +0100795 void *ptr2;
796
797 if (get_reentrant()) {
798 /* Reentrant call to PyMem_Realloc() and PyMem_RawRealloc().
799 Example: PyMem_RawRealloc() is called internally by pymalloc
800 (_PyObject_Malloc() and _PyObject_Realloc()) to allocate a new
801 arena (new_arena()). */
Victor Stinnerd8f0d922014-06-02 21:57:10 +0200802 PyMemAllocatorEx *alloc = (PyMemAllocatorEx *)ctx;
Victor Stinner15116802013-12-04 01:29:35 +0100803
804 ptr2 = alloc->realloc(alloc->ctx, ptr, new_size);
Victor Stinner88c29872013-12-04 01:47:46 +0100805 if (ptr2 != NULL && ptr != NULL) {
806 TABLES_LOCK();
Victor Stinnere492ae52016-03-22 12:58:23 +0100807 REMOVE_TRACE(ptr);
Victor Stinner88c29872013-12-04 01:47:46 +0100808 TABLES_UNLOCK();
809 }
Victor Stinner15116802013-12-04 01:29:35 +0100810 return ptr2;
811 }
812
813 /* Ignore reentrant call. PyObjet_Realloc() calls PyMem_Realloc() for
814 allocations larger than 512 bytes. Don't trace the same memory
815 allocation twice. */
816 set_reentrant(1);
817
818 ptr2 = tracemalloc_realloc(ctx, ptr, new_size);
819
820 set_reentrant(0);
821 return ptr2;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100822}
823
Victor Stinnere492ae52016-03-22 12:58:23 +0100824
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100825#ifdef TRACE_RAW_MALLOC
826static void*
Victor Stinnerdb067af2014-05-02 22:31:14 +0200827tracemalloc_raw_alloc(int use_calloc, void *ctx, size_t nelem, size_t elsize)
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100828{
Victor Stinner15116802013-12-04 01:29:35 +0100829 PyGILState_STATE gil_state;
Victor Stinner15116802013-12-04 01:29:35 +0100830 void *ptr;
831
832 if (get_reentrant()) {
Victor Stinnerd8f0d922014-06-02 21:57:10 +0200833 PyMemAllocatorEx *alloc = (PyMemAllocatorEx *)ctx;
Victor Stinnerdb067af2014-05-02 22:31:14 +0200834 if (use_calloc)
835 return alloc->calloc(alloc->ctx, nelem, elsize);
836 else
837 return alloc->malloc(alloc->ctx, nelem * elsize);
Victor Stinner15116802013-12-04 01:29:35 +0100838 }
839
840 /* Ignore reentrant call. PyGILState_Ensure() may call PyMem_RawMalloc()
841 indirectly which would call PyGILState_Ensure() if reentrant are not
842 disabled. */
843 set_reentrant(1);
844
Victor Stinner15116802013-12-04 01:29:35 +0100845 gil_state = PyGILState_Ensure();
Victor Stinnerdb067af2014-05-02 22:31:14 +0200846 ptr = tracemalloc_alloc(use_calloc, ctx, nelem, elsize);
Victor Stinner15116802013-12-04 01:29:35 +0100847 PyGILState_Release(gil_state);
Victor Stinner15116802013-12-04 01:29:35 +0100848
849 set_reentrant(0);
850 return ptr;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100851}
852
Victor Stinnere492ae52016-03-22 12:58:23 +0100853
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100854static void*
Victor Stinnerdb067af2014-05-02 22:31:14 +0200855tracemalloc_raw_malloc(void *ctx, size_t size)
856{
857 return tracemalloc_raw_alloc(0, ctx, 1, size);
858}
859
Victor Stinnere492ae52016-03-22 12:58:23 +0100860
Victor Stinnerdb067af2014-05-02 22:31:14 +0200861static void*
862tracemalloc_raw_calloc(void *ctx, size_t nelem, size_t elsize)
863{
864 return tracemalloc_raw_alloc(1, ctx, nelem, elsize);
865}
866
Victor Stinnere492ae52016-03-22 12:58:23 +0100867
Victor Stinnerdb067af2014-05-02 22:31:14 +0200868static void*
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100869tracemalloc_raw_realloc(void *ctx, void *ptr, size_t new_size)
870{
Victor Stinner15116802013-12-04 01:29:35 +0100871 PyGILState_STATE gil_state;
Victor Stinner15116802013-12-04 01:29:35 +0100872 void *ptr2;
873
874 if (get_reentrant()) {
875 /* Reentrant call to PyMem_RawRealloc(). */
Victor Stinnerd8f0d922014-06-02 21:57:10 +0200876 PyMemAllocatorEx *alloc = (PyMemAllocatorEx *)ctx;
Victor Stinner15116802013-12-04 01:29:35 +0100877
878 ptr2 = alloc->realloc(alloc->ctx, ptr, new_size);
Victor Stinner15116802013-12-04 01:29:35 +0100879
Victor Stinner88c29872013-12-04 01:47:46 +0100880 if (ptr2 != NULL && ptr != NULL) {
881 TABLES_LOCK();
Victor Stinnere492ae52016-03-22 12:58:23 +0100882 REMOVE_TRACE(ptr);
Victor Stinner88c29872013-12-04 01:47:46 +0100883 TABLES_UNLOCK();
884 }
Victor Stinner15116802013-12-04 01:29:35 +0100885 return ptr2;
886 }
887
888 /* Ignore reentrant call. PyGILState_Ensure() may call PyMem_RawMalloc()
889 indirectly which would call PyGILState_Ensure() if reentrant calls are
890 not disabled. */
891 set_reentrant(1);
892
Victor Stinner15116802013-12-04 01:29:35 +0100893 gil_state = PyGILState_Ensure();
894 ptr2 = tracemalloc_realloc(ctx, ptr, new_size);
895 PyGILState_Release(gil_state);
Victor Stinner15116802013-12-04 01:29:35 +0100896
897 set_reentrant(0);
898 return ptr2;
899}
900#endif /* TRACE_RAW_MALLOC */
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100901
Victor Stinnere492ae52016-03-22 12:58:23 +0100902
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100903static int
Victor Stinner285cf0a2016-03-21 22:00:58 +0100904tracemalloc_clear_filename(_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 PyObject *filename;
908
Victor Stinner5dacbd42016-03-23 09:52:13 +0100909 _Py_HASHTABLE_ENTRY_READ_KEY(ht, entry, filename);
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100910 Py_DECREF(filename);
911 return 0;
912}
913
Victor Stinnere492ae52016-03-22 12:58:23 +0100914
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100915static int
Victor Stinner285cf0a2016-03-21 22:00:58 +0100916traceback_free_traceback(_Py_hashtable_t *ht, _Py_hashtable_entry_t *entry,
917 void *user_data)
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100918{
Victor Stinner285cf0a2016-03-21 22:00:58 +0100919 traceback_t *traceback;
920
Victor Stinner5dacbd42016-03-23 09:52:13 +0100921 _Py_HASHTABLE_ENTRY_READ_KEY(ht, entry, traceback);
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100922 raw_free(traceback);
923 return 0;
924}
925
Victor Stinnere492ae52016-03-22 12:58:23 +0100926
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100927/* reentrant flag must be set to call this function and GIL must be held */
928static void
929tracemalloc_clear_traces(void)
930{
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100931 /* The GIL protects variables againt concurrent access */
932 assert(PyGILState_Check());
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100933
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100934 TABLES_LOCK();
935 _Py_hashtable_clear(tracemalloc_traces);
936 tracemalloc_traced_memory = 0;
Victor Stinner3c0481d2013-11-27 21:39:49 +0100937 tracemalloc_peak_traced_memory = 0;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100938 TABLES_UNLOCK();
939
940 _Py_hashtable_foreach(tracemalloc_tracebacks, traceback_free_traceback, NULL);
941 _Py_hashtable_clear(tracemalloc_tracebacks);
942
943 _Py_hashtable_foreach(tracemalloc_filenames, tracemalloc_clear_filename, NULL);
944 _Py_hashtable_clear(tracemalloc_filenames);
945}
946
Victor Stinnere492ae52016-03-22 12:58:23 +0100947
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100948static int
949tracemalloc_init(void)
950{
Victor Stinner9e00e802018-10-25 13:31:16 +0200951 if (_Py_tracemalloc_config.initialized == TRACEMALLOC_FINALIZED) {
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100952 PyErr_SetString(PyExc_RuntimeError,
953 "the tracemalloc module has been unloaded");
954 return -1;
955 }
956
Victor Stinner9e00e802018-10-25 13:31:16 +0200957 if (_Py_tracemalloc_config.initialized == TRACEMALLOC_INITIALIZED)
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100958 return 0;
959
960 PyMem_GetAllocator(PYMEM_DOMAIN_RAW, &allocators.raw);
961
962#ifdef REENTRANT_THREADLOCAL
Masayuki Yamamoto731e1892017-10-06 19:41:34 +0900963 if (PyThread_tss_create(&tracemalloc_reentrant_key) != 0) {
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100964#ifdef MS_WINDOWS
965 PyErr_SetFromWindowsErr(0);
966#else
967 PyErr_SetFromErrno(PyExc_OSError);
968#endif
969 return -1;
970 }
971#endif
972
Antoine Pitroua6a4dc82017-09-07 18:56:24 +0200973#if defined(TRACE_RAW_MALLOC)
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100974 if (tables_lock == NULL) {
975 tables_lock = PyThread_allocate_lock();
976 if (tables_lock == NULL) {
977 PyErr_SetString(PyExc_RuntimeError, "cannot allocate lock");
978 return -1;
979 }
980 }
981#endif
982
Victor Stinner285cf0a2016-03-21 22:00:58 +0100983 tracemalloc_filenames = hashtable_new(sizeof(PyObject *), 0,
984 hashtable_hash_pyobject,
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100985 hashtable_compare_unicode);
986
Victor Stinner285cf0a2016-03-21 22:00:58 +0100987 tracemalloc_tracebacks = hashtable_new(sizeof(traceback_t *), 0,
988 hashtable_hash_traceback,
989 hashtable_compare_traceback);
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100990
Victor Stinner9e00e802018-10-25 13:31:16 +0200991 if (_Py_tracemalloc_config.use_domain) {
Victor Stinnere492ae52016-03-22 12:58:23 +0100992 tracemalloc_traces = hashtable_new(sizeof(pointer_t),
993 sizeof(trace_t),
994 hashtable_hash_pointer_t,
995 hashtable_compare_pointer_t);
996 }
997 else {
Benjamin Petersonca470632016-09-06 13:47:26 -0700998 tracemalloc_traces = hashtable_new(sizeof(uintptr_t),
Victor Stinnere492ae52016-03-22 12:58:23 +0100999 sizeof(trace_t),
1000 _Py_hashtable_hash_ptr,
1001 _Py_hashtable_compare_direct);
1002 }
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001003
1004 if (tracemalloc_filenames == NULL || tracemalloc_tracebacks == NULL
Victor Stinner285cf0a2016-03-21 22:00:58 +01001005 || tracemalloc_traces == NULL) {
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001006 PyErr_NoMemory();
1007 return -1;
1008 }
1009
1010 unknown_filename = PyUnicode_FromString("<unknown>");
1011 if (unknown_filename == NULL)
1012 return -1;
1013 PyUnicode_InternInPlace(&unknown_filename);
1014
1015 tracemalloc_empty_traceback.nframe = 1;
Julien Danjou8d59eb12019-10-15 14:00:16 +02001016 tracemalloc_empty_traceback.total_nframe = 1;
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001017 /* borrowed reference */
1018 tracemalloc_empty_traceback.frames[0].filename = unknown_filename;
1019 tracemalloc_empty_traceback.frames[0].lineno = 0;
1020 tracemalloc_empty_traceback.hash = traceback_hash(&tracemalloc_empty_traceback);
1021
Victor Stinner9e00e802018-10-25 13:31:16 +02001022 _Py_tracemalloc_config.initialized = TRACEMALLOC_INITIALIZED;
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001023 return 0;
1024}
1025
Victor Stinnere492ae52016-03-22 12:58:23 +01001026
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001027static void
1028tracemalloc_deinit(void)
1029{
Victor Stinner9e00e802018-10-25 13:31:16 +02001030 if (_Py_tracemalloc_config.initialized != TRACEMALLOC_INITIALIZED)
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001031 return;
Victor Stinner9e00e802018-10-25 13:31:16 +02001032 _Py_tracemalloc_config.initialized = TRACEMALLOC_FINALIZED;
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001033
1034 tracemalloc_stop();
1035
1036 /* destroy hash tables */
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001037 _Py_hashtable_destroy(tracemalloc_tracebacks);
1038 _Py_hashtable_destroy(tracemalloc_filenames);
Victor Stinner285cf0a2016-03-21 22:00:58 +01001039 _Py_hashtable_destroy(tracemalloc_traces);
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001040
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02001041#if defined(TRACE_RAW_MALLOC)
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001042 if (tables_lock != NULL) {
1043 PyThread_free_lock(tables_lock);
1044 tables_lock = NULL;
1045 }
1046#endif
1047
1048#ifdef REENTRANT_THREADLOCAL
Masayuki Yamamoto731e1892017-10-06 19:41:34 +09001049 PyThread_tss_delete(&tracemalloc_reentrant_key);
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001050#endif
1051
1052 Py_XDECREF(unknown_filename);
1053}
1054
Victor Stinnere492ae52016-03-22 12:58:23 +01001055
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001056static int
Victor Stinnerf28ce602013-11-27 22:27:13 +01001057tracemalloc_start(int max_nframe)
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001058{
Victor Stinnerd8f0d922014-06-02 21:57:10 +02001059 PyMemAllocatorEx alloc;
Victor Stinnerf28ce602013-11-27 22:27:13 +01001060 size_t size;
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001061
Julien Danjou8d59eb12019-10-15 14:00:16 +02001062 if (max_nframe < 1 || (unsigned long) max_nframe > MAX_NFRAME) {
Victor Stinnera7368ac2017-11-15 18:11:45 -08001063 PyErr_Format(PyExc_ValueError,
Julien Danjou8d59eb12019-10-15 14:00:16 +02001064 "the number of frames must be in range [1; %lu]",
1065 MAX_NFRAME);
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001066 return -1;
Victor Stinnera7368ac2017-11-15 18:11:45 -08001067 }
1068
1069 if (tracemalloc_init() < 0) {
1070 return -1;
1071 }
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001072
Victor Stinner9e00e802018-10-25 13:31:16 +02001073 if (_Py_tracemalloc_config.tracing) {
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001074 /* hook already installed: do nothing */
1075 return 0;
1076 }
1077
Victor Stinner9e00e802018-10-25 13:31:16 +02001078 _Py_tracemalloc_config.max_nframe = max_nframe;
Victor Stinnerf28ce602013-11-27 22:27:13 +01001079
1080 /* allocate a buffer to store a new traceback */
1081 size = TRACEBACK_SIZE(max_nframe);
1082 assert(tracemalloc_traceback == NULL);
1083 tracemalloc_traceback = raw_malloc(size);
1084 if (tracemalloc_traceback == NULL) {
1085 PyErr_NoMemory();
1086 return -1;
1087 }
1088
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001089#ifdef TRACE_RAW_MALLOC
1090 alloc.malloc = tracemalloc_raw_malloc;
Victor Stinnerdb067af2014-05-02 22:31:14 +02001091 alloc.calloc = tracemalloc_raw_calloc;
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001092 alloc.realloc = tracemalloc_raw_realloc;
1093 alloc.free = tracemalloc_free;
1094
1095 alloc.ctx = &allocators.raw;
1096 PyMem_GetAllocator(PYMEM_DOMAIN_RAW, &allocators.raw);
1097 PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &alloc);
1098#endif
1099
1100 alloc.malloc = tracemalloc_malloc_gil;
Victor Stinnerdb067af2014-05-02 22:31:14 +02001101 alloc.calloc = tracemalloc_calloc_gil;
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001102 alloc.realloc = tracemalloc_realloc_gil;
1103 alloc.free = tracemalloc_free;
1104
1105 alloc.ctx = &allocators.mem;
1106 PyMem_GetAllocator(PYMEM_DOMAIN_MEM, &allocators.mem);
1107 PyMem_SetAllocator(PYMEM_DOMAIN_MEM, &alloc);
1108
1109 alloc.ctx = &allocators.obj;
1110 PyMem_GetAllocator(PYMEM_DOMAIN_OBJ, &allocators.obj);
1111 PyMem_SetAllocator(PYMEM_DOMAIN_OBJ, &alloc);
1112
1113 /* everything is ready: start tracing Python memory allocations */
Victor Stinner9e00e802018-10-25 13:31:16 +02001114 _Py_tracemalloc_config.tracing = 1;
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001115
1116 return 0;
1117}
1118
Victor Stinnere492ae52016-03-22 12:58:23 +01001119
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001120static void
1121tracemalloc_stop(void)
1122{
Victor Stinner9e00e802018-10-25 13:31:16 +02001123 if (!_Py_tracemalloc_config.tracing)
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001124 return;
1125
1126 /* stop tracing Python memory allocations */
Victor Stinner9e00e802018-10-25 13:31:16 +02001127 _Py_tracemalloc_config.tracing = 0;
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001128
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001129 /* unregister the hook on memory allocators */
1130#ifdef TRACE_RAW_MALLOC
1131 PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &allocators.raw);
1132#endif
1133 PyMem_SetAllocator(PYMEM_DOMAIN_MEM, &allocators.mem);
1134 PyMem_SetAllocator(PYMEM_DOMAIN_OBJ, &allocators.obj);
1135
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001136 tracemalloc_clear_traces();
Victor Stinner285cf0a2016-03-21 22:00:58 +01001137
1138 /* release memory */
Victor Stinnerf28ce602013-11-27 22:27:13 +01001139 raw_free(tracemalloc_traceback);
1140 tracemalloc_traceback = NULL;
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001141}
1142
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001143
Victor Stinnere492ae52016-03-22 12:58:23 +01001144
Serhiy Storchakab451f912017-02-04 12:18:38 +02001145/*[clinic input]
1146_tracemalloc.is_tracing
1147
1148Return True if the tracemalloc module is tracing Python memory allocations.
1149[clinic start generated code]*/
1150
1151static PyObject *
1152_tracemalloc_is_tracing_impl(PyObject *module)
Serhiy Storchaka97353842017-02-05 22:58:46 +02001153/*[clinic end generated code: output=2d763b42601cd3ef input=af104b0a00192f63]*/
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001154{
Victor Stinner9e00e802018-10-25 13:31:16 +02001155 return PyBool_FromLong(_Py_tracemalloc_config.tracing);
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001156}
1157
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001158
Serhiy Storchakab451f912017-02-04 12:18:38 +02001159/*[clinic input]
1160_tracemalloc.clear_traces
Victor Stinnere492ae52016-03-22 12:58:23 +01001161
Serhiy Storchakab451f912017-02-04 12:18:38 +02001162Clear traces of memory blocks allocated by Python.
1163[clinic start generated code]*/
1164
1165static PyObject *
1166_tracemalloc_clear_traces_impl(PyObject *module)
1167/*[clinic end generated code: output=a86080ee41b84197 input=0dab5b6c785183a5]*/
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001168{
Victor Stinner9e00e802018-10-25 13:31:16 +02001169 if (!_Py_tracemalloc_config.tracing)
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001170 Py_RETURN_NONE;
1171
1172 set_reentrant(1);
1173 tracemalloc_clear_traces();
1174 set_reentrant(0);
1175
1176 Py_RETURN_NONE;
1177}
1178
Victor Stinnere492ae52016-03-22 12:58:23 +01001179
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001180static PyObject*
1181frame_to_pyobject(frame_t *frame)
1182{
1183 PyObject *frame_obj, *lineno_obj;
1184
1185 frame_obj = PyTuple_New(2);
1186 if (frame_obj == NULL)
1187 return NULL;
1188
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001189 Py_INCREF(frame->filename);
1190 PyTuple_SET_ITEM(frame_obj, 0, frame->filename);
1191
Victor Stinner95283342016-03-15 21:57:02 +01001192 lineno_obj = PyLong_FromUnsignedLong(frame->lineno);
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001193 if (lineno_obj == NULL) {
1194 Py_DECREF(frame_obj);
1195 return NULL;
1196 }
1197 PyTuple_SET_ITEM(frame_obj, 1, lineno_obj);
1198
1199 return frame_obj;
1200}
1201
Victor Stinnere492ae52016-03-22 12:58:23 +01001202
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001203static PyObject*
1204traceback_to_pyobject(traceback_t *traceback, _Py_hashtable_t *intern_table)
1205{
1206 int i;
1207 PyObject *frames, *frame;
1208
1209 if (intern_table != NULL) {
1210 if (_Py_HASHTABLE_GET(intern_table, traceback, frames)) {
1211 Py_INCREF(frames);
1212 return frames;
1213 }
1214 }
1215
1216 frames = PyTuple_New(traceback->nframe);
1217 if (frames == NULL)
1218 return NULL;
1219
1220 for (i=0; i < traceback->nframe; i++) {
1221 frame = frame_to_pyobject(&traceback->frames[i]);
1222 if (frame == NULL) {
1223 Py_DECREF(frames);
1224 return NULL;
1225 }
1226 PyTuple_SET_ITEM(frames, i, frame);
1227 }
1228
1229 if (intern_table != NULL) {
1230 if (_Py_HASHTABLE_SET(intern_table, traceback, frames) < 0) {
1231 Py_DECREF(frames);
1232 PyErr_NoMemory();
1233 return NULL;
1234 }
1235 /* intern_table keeps a new reference to frames */
1236 Py_INCREF(frames);
1237 }
1238 return frames;
1239}
1240
Victor Stinnere492ae52016-03-22 12:58:23 +01001241
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001242static PyObject*
Victor Stinner5ea4c062017-06-20 17:46:36 +02001243trace_to_pyobject(unsigned int domain, trace_t *trace,
Victor Stinnere492ae52016-03-22 12:58:23 +01001244 _Py_hashtable_t *intern_tracebacks)
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001245{
1246 PyObject *trace_obj = NULL;
Victor Stinnere492ae52016-03-22 12:58:23 +01001247 PyObject *obj;
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001248
Julien Danjou8d59eb12019-10-15 14:00:16 +02001249 trace_obj = PyTuple_New(4);
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001250 if (trace_obj == NULL)
1251 return NULL;
1252
Victor Stinnere492ae52016-03-22 12:58:23 +01001253 obj = PyLong_FromSize_t(domain);
1254 if (obj == NULL) {
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001255 Py_DECREF(trace_obj);
1256 return NULL;
1257 }
Victor Stinnere492ae52016-03-22 12:58:23 +01001258 PyTuple_SET_ITEM(trace_obj, 0, obj);
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001259
Victor Stinnere492ae52016-03-22 12:58:23 +01001260 obj = PyLong_FromSize_t(trace->size);
1261 if (obj == NULL) {
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001262 Py_DECREF(trace_obj);
1263 return NULL;
1264 }
Victor Stinnere492ae52016-03-22 12:58:23 +01001265 PyTuple_SET_ITEM(trace_obj, 1, obj);
1266
1267 obj = traceback_to_pyobject(trace->traceback, intern_tracebacks);
1268 if (obj == NULL) {
1269 Py_DECREF(trace_obj);
1270 return NULL;
1271 }
1272 PyTuple_SET_ITEM(trace_obj, 2, obj);
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001273
Julien Danjou8d59eb12019-10-15 14:00:16 +02001274 obj = PyLong_FromUnsignedLong(trace->traceback->total_nframe);
1275 if (obj == NULL) {
1276 Py_DECREF(trace_obj);
1277 return NULL;
1278 }
1279 PyTuple_SET_ITEM(trace_obj, 3, obj);
1280
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001281 return trace_obj;
1282}
1283
Victor Stinnere492ae52016-03-22 12:58:23 +01001284
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001285typedef struct {
1286 _Py_hashtable_t *traces;
1287 _Py_hashtable_t *tracebacks;
1288 PyObject *list;
1289} get_traces_t;
1290
1291static int
Victor Stinner285cf0a2016-03-21 22:00:58 +01001292tracemalloc_get_traces_fill(_Py_hashtable_t *traces, _Py_hashtable_entry_t *entry,
1293 void *user_data)
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001294{
1295 get_traces_t *get_traces = user_data;
Victor Stinner5ea4c062017-06-20 17:46:36 +02001296 unsigned int domain;
Victor Stinner5dacbd42016-03-23 09:52:13 +01001297 trace_t trace;
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001298 PyObject *tracemalloc_obj;
1299 int res;
1300
Victor Stinner9e00e802018-10-25 13:31:16 +02001301 if (_Py_tracemalloc_config.use_domain) {
Victor Stinnere492ae52016-03-22 12:58:23 +01001302 pointer_t key;
Victor Stinner5dacbd42016-03-23 09:52:13 +01001303 _Py_HASHTABLE_ENTRY_READ_KEY(traces, entry, key);
Victor Stinnere492ae52016-03-22 12:58:23 +01001304 domain = key.domain;
1305 }
1306 else {
1307 domain = DEFAULT_DOMAIN;
1308 }
Victor Stinner5dacbd42016-03-23 09:52:13 +01001309 _Py_HASHTABLE_ENTRY_READ_DATA(traces, entry, trace);
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001310
Victor Stinner5dacbd42016-03-23 09:52:13 +01001311 tracemalloc_obj = trace_to_pyobject(domain, &trace, get_traces->tracebacks);
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001312 if (tracemalloc_obj == NULL)
1313 return 1;
1314
1315 res = PyList_Append(get_traces->list, tracemalloc_obj);
1316 Py_DECREF(tracemalloc_obj);
1317 if (res < 0)
1318 return 1;
1319
1320 return 0;
1321}
1322
Victor Stinnere492ae52016-03-22 12:58:23 +01001323
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001324static int
Victor Stinner285cf0a2016-03-21 22:00:58 +01001325tracemalloc_pyobject_decref_cb(_Py_hashtable_t *tracebacks,
1326 _Py_hashtable_entry_t *entry,
1327 void *user_data)
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001328{
Victor Stinnerc9553872016-03-22 12:13:01 +01001329 PyObject *obj;
Victor Stinnere8c6b2f2016-03-23 09:25:01 +01001330 _Py_HASHTABLE_ENTRY_READ_DATA(tracebacks, entry, obj);
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001331 Py_DECREF(obj);
1332 return 0;
1333}
1334
Victor Stinnere492ae52016-03-22 12:58:23 +01001335
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001336
Serhiy Storchakab451f912017-02-04 12:18:38 +02001337/*[clinic input]
1338_tracemalloc._get_traces
1339
1340Get traces of all memory blocks allocated by Python.
1341
1342Return a list of (size: int, traceback: tuple) tuples.
1343traceback is a tuple of (filename: str, lineno: int) tuples.
1344
1345Return an empty list if the tracemalloc module is disabled.
1346[clinic start generated code]*/
1347
1348static PyObject *
1349_tracemalloc__get_traces_impl(PyObject *module)
1350/*[clinic end generated code: output=e9929876ced4b5cc input=6c7d2230b24255aa]*/
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001351{
1352 get_traces_t get_traces;
1353 int err;
1354
1355 get_traces.traces = NULL;
1356 get_traces.tracebacks = NULL;
1357 get_traces.list = PyList_New(0);
1358 if (get_traces.list == NULL)
1359 goto error;
1360
Victor Stinner9e00e802018-10-25 13:31:16 +02001361 if (!_Py_tracemalloc_config.tracing)
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001362 return get_traces.list;
1363
Victor Stinnerde2f1322013-11-26 00:26:23 +01001364 /* the traceback hash table is used temporarily to intern traceback tuple
1365 of (filename, lineno) tuples */
Victor Stinnerc9553872016-03-22 12:13:01 +01001366 get_traces.tracebacks = hashtable_new(sizeof(traceback_t *),
1367 sizeof(PyObject *),
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001368 _Py_hashtable_hash_ptr,
1369 _Py_hashtable_compare_direct);
1370 if (get_traces.tracebacks == NULL) {
1371 PyErr_NoMemory();
1372 goto error;
1373 }
1374
1375 TABLES_LOCK();
1376 get_traces.traces = _Py_hashtable_copy(tracemalloc_traces);
1377 TABLES_UNLOCK();
1378
1379 if (get_traces.traces == NULL) {
1380 PyErr_NoMemory();
1381 goto error;
1382 }
1383
1384 set_reentrant(1);
1385 err = _Py_hashtable_foreach(get_traces.traces,
1386 tracemalloc_get_traces_fill, &get_traces);
1387 set_reentrant(0);
1388 if (err)
1389 goto error;
1390
1391 goto finally;
1392
1393error:
1394 Py_CLEAR(get_traces.list);
1395
1396finally:
1397 if (get_traces.tracebacks != NULL) {
1398 _Py_hashtable_foreach(get_traces.tracebacks,
Victor Stinner285cf0a2016-03-21 22:00:58 +01001399 tracemalloc_pyobject_decref_cb, NULL);
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001400 _Py_hashtable_destroy(get_traces.tracebacks);
1401 }
Victor Stinnerc9553872016-03-22 12:13:01 +01001402 if (get_traces.traces != NULL) {
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001403 _Py_hashtable_destroy(get_traces.traces);
Victor Stinnerc9553872016-03-22 12:13:01 +01001404 }
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001405
1406 return get_traces.list;
1407}
1408
Victor Stinnere492ae52016-03-22 12:58:23 +01001409
Victor Stinner0611c262016-03-15 22:22:13 +01001410static traceback_t*
Victor Stinner5ea4c062017-06-20 17:46:36 +02001411tracemalloc_get_traceback(unsigned int domain, uintptr_t ptr)
Victor Stinner0611c262016-03-15 22:22:13 +01001412{
1413 trace_t trace;
1414 int found;
1415
Victor Stinner9e00e802018-10-25 13:31:16 +02001416 if (!_Py_tracemalloc_config.tracing)
Victor Stinner0611c262016-03-15 22:22:13 +01001417 return NULL;
1418
1419 TABLES_LOCK();
Victor Stinner9e00e802018-10-25 13:31:16 +02001420 if (_Py_tracemalloc_config.use_domain) {
Victor Stinner10b73e12016-03-22 13:39:05 +01001421 pointer_t key = {ptr, domain};
Victor Stinnere492ae52016-03-22 12:58:23 +01001422 found = _Py_HASHTABLE_GET(tracemalloc_traces, key, trace);
1423 }
1424 else {
1425 found = _Py_HASHTABLE_GET(tracemalloc_traces, ptr, trace);
1426 }
Victor Stinner0611c262016-03-15 22:22:13 +01001427 TABLES_UNLOCK();
1428
1429 if (!found)
1430 return NULL;
1431
1432 return trace.traceback;
1433}
1434
Victor Stinnere492ae52016-03-22 12:58:23 +01001435
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001436
Serhiy Storchakab451f912017-02-04 12:18:38 +02001437/*[clinic input]
1438_tracemalloc._get_object_traceback
1439
1440 obj: object
1441 /
1442
1443Get the traceback where the Python object obj was allocated.
1444
1445Return a tuple of (filename: str, lineno: int) tuples.
1446Return None if the tracemalloc module is disabled or did not
1447trace the allocation of the object.
1448[clinic start generated code]*/
1449
1450static PyObject *
1451_tracemalloc__get_object_traceback(PyObject *module, PyObject *obj)
1452/*[clinic end generated code: output=41ee0553a658b0aa input=29495f1b21c53212]*/
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001453{
1454 PyTypeObject *type;
1455 void *ptr;
Victor Stinner0611c262016-03-15 22:22:13 +01001456 traceback_t *traceback;
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001457
1458 type = Py_TYPE(obj);
Victor Stinner626bff82018-10-25 17:31:10 +02001459 if (PyType_IS_GC(type)) {
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001460 ptr = (void *)((char *)obj - sizeof(PyGC_Head));
Victor Stinner626bff82018-10-25 17:31:10 +02001461 }
1462 else {
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001463 ptr = (void *)obj;
Victor Stinner626bff82018-10-25 17:31:10 +02001464 }
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001465
Benjamin Petersonca470632016-09-06 13:47:26 -07001466 traceback = tracemalloc_get_traceback(DEFAULT_DOMAIN, (uintptr_t)ptr);
Victor Stinner0611c262016-03-15 22:22:13 +01001467 if (traceback == NULL)
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001468 Py_RETURN_NONE;
1469
Victor Stinner0611c262016-03-15 22:22:13 +01001470 return traceback_to_pyobject(traceback, NULL);
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001471}
1472
Victor Stinnere492ae52016-03-22 12:58:23 +01001473
Victor Stinner0611c262016-03-15 22:22:13 +01001474#define PUTS(fd, str) _Py_write_noraise(fd, str, (int)strlen(str))
1475
1476static void
1477_PyMem_DumpFrame(int fd, frame_t * frame)
1478{
1479 PUTS(fd, " File \"");
1480 _Py_DumpASCII(fd, frame->filename);
1481 PUTS(fd, "\", line ");
1482 _Py_DumpDecimal(fd, frame->lineno);
1483 PUTS(fd, "\n");
1484}
1485
1486/* Dump the traceback where a memory block was allocated into file descriptor
1487 fd. The function may block on TABLES_LOCK() but it is unlikely. */
1488void
1489_PyMem_DumpTraceback(int fd, const void *ptr)
1490{
1491 traceback_t *traceback;
1492 int i;
1493
Victor Stinnerf966e532018-11-13 15:14:58 +01001494 if (!_Py_tracemalloc_config.tracing) {
1495 PUTS(fd, "Enable tracemalloc to get the memory block "
1496 "allocation traceback\n\n");
1497 return;
1498 }
1499
Benjamin Petersonca470632016-09-06 13:47:26 -07001500 traceback = tracemalloc_get_traceback(DEFAULT_DOMAIN, (uintptr_t)ptr);
Victor Stinner0611c262016-03-15 22:22:13 +01001501 if (traceback == NULL)
1502 return;
1503
1504 PUTS(fd, "Memory block allocated at (most recent call first):\n");
1505 for (i=0; i < traceback->nframe; i++) {
1506 _PyMem_DumpFrame(fd, &traceback->frames[i]);
1507 }
1508 PUTS(fd, "\n");
1509}
1510
1511#undef PUTS
1512
Victor Stinnere492ae52016-03-22 12:58:23 +01001513
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001514
Serhiy Storchakab451f912017-02-04 12:18:38 +02001515/*[clinic input]
1516_tracemalloc.start
1517
Victor Stinnera7368ac2017-11-15 18:11:45 -08001518 nframe: int = 1
Serhiy Storchakab451f912017-02-04 12:18:38 +02001519 /
1520
1521Start tracing Python memory allocations.
1522
1523Also set the maximum number of frames stored in the traceback of a
1524trace to nframe.
1525[clinic start generated code]*/
1526
1527static PyObject *
Victor Stinnera7368ac2017-11-15 18:11:45 -08001528_tracemalloc_start_impl(PyObject *module, int nframe)
1529/*[clinic end generated code: output=caae05c23c159d3c input=40d849b5b29d1933]*/
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001530{
Victor Stinnera7368ac2017-11-15 18:11:45 -08001531 if (tracemalloc_start(nframe) < 0) {
Victor Stinner3728d6c2013-11-23 12:37:20 +01001532 return NULL;
1533 }
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001534 Py_RETURN_NONE;
1535}
1536
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001537
Serhiy Storchakab451f912017-02-04 12:18:38 +02001538/*[clinic input]
1539_tracemalloc.stop
Victor Stinnere492ae52016-03-22 12:58:23 +01001540
Serhiy Storchakab451f912017-02-04 12:18:38 +02001541Stop tracing Python memory allocations.
1542
1543Also clear traces of memory blocks allocated by Python.
1544[clinic start generated code]*/
1545
1546static PyObject *
1547_tracemalloc_stop_impl(PyObject *module)
1548/*[clinic end generated code: output=c3c42ae03e3955cd input=7478f075e51dae18]*/
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001549{
1550 tracemalloc_stop();
1551 Py_RETURN_NONE;
1552}
1553
Victor Stinnere492ae52016-03-22 12:58:23 +01001554
Serhiy Storchakab451f912017-02-04 12:18:38 +02001555/*[clinic input]
1556_tracemalloc.get_traceback_limit
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001557
Serhiy Storchakab451f912017-02-04 12:18:38 +02001558Get the maximum number of frames stored in the traceback of a trace.
1559
1560By default, a trace of an allocated memory block only stores
1561the most recent frame: the limit is 1.
1562[clinic start generated code]*/
1563
1564static PyObject *
1565_tracemalloc_get_traceback_limit_impl(PyObject *module)
1566/*[clinic end generated code: output=d556d9306ba95567 input=da3cd977fc68ae3b]*/
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001567{
Victor Stinner9e00e802018-10-25 13:31:16 +02001568 return PyLong_FromLong(_Py_tracemalloc_config.max_nframe);
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001569}
1570
Victor Stinnere492ae52016-03-22 12:58:23 +01001571
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001572
Serhiy Storchakab451f912017-02-04 12:18:38 +02001573/*[clinic input]
1574_tracemalloc.get_tracemalloc_memory
1575
1576Get the memory usage in bytes of the tracemalloc module.
1577
1578This memory is used internally to trace memory allocations.
1579[clinic start generated code]*/
1580
1581static PyObject *
1582_tracemalloc_get_tracemalloc_memory_impl(PyObject *module)
1583/*[clinic end generated code: output=e3f14e280a55f5aa input=5d919c0f4d5132ad]*/
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001584{
1585 size_t size;
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001586
1587 size = _Py_hashtable_size(tracemalloc_tracebacks);
1588 size += _Py_hashtable_size(tracemalloc_filenames);
1589
1590 TABLES_LOCK();
1591 size += _Py_hashtable_size(tracemalloc_traces);
1592 TABLES_UNLOCK();
1593
Serhiy Storchakab451f912017-02-04 12:18:38 +02001594 return PyLong_FromSize_t(size);
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001595}
1596
Victor Stinnere492ae52016-03-22 12:58:23 +01001597
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001598
Serhiy Storchakab451f912017-02-04 12:18:38 +02001599/*[clinic input]
1600_tracemalloc.get_traced_memory
1601
1602Get the current size and peak size of memory blocks traced by tracemalloc.
1603
1604Returns a tuple: (current: int, peak: int).
1605[clinic start generated code]*/
1606
1607static PyObject *
1608_tracemalloc_get_traced_memory_impl(PyObject *module)
1609/*[clinic end generated code: output=5b167189adb9e782 input=61ddb5478400ff66]*/
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001610{
Victor Stinner3c0481d2013-11-27 21:39:49 +01001611 Py_ssize_t size, peak_size;
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001612
Victor Stinner9e00e802018-10-25 13:31:16 +02001613 if (!_Py_tracemalloc_config.tracing)
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001614 return Py_BuildValue("ii", 0, 0);
1615
1616 TABLES_LOCK();
1617 size = tracemalloc_traced_memory;
Victor Stinner3c0481d2013-11-27 21:39:49 +01001618 peak_size = tracemalloc_peak_traced_memory;
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001619 TABLES_UNLOCK();
1620
Serhiy Storchakab451f912017-02-04 12:18:38 +02001621 return Py_BuildValue("nn", size, peak_size);
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001622}
1623
Victor Stinnere492ae52016-03-22 12:58:23 +01001624
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001625static PyMethodDef module_methods[] = {
Serhiy Storchakab451f912017-02-04 12:18:38 +02001626 _TRACEMALLOC_IS_TRACING_METHODDEF
1627 _TRACEMALLOC_CLEAR_TRACES_METHODDEF
1628 _TRACEMALLOC__GET_TRACES_METHODDEF
1629 _TRACEMALLOC__GET_OBJECT_TRACEBACK_METHODDEF
1630 _TRACEMALLOC_START_METHODDEF
1631 _TRACEMALLOC_STOP_METHODDEF
1632 _TRACEMALLOC_GET_TRACEBACK_LIMIT_METHODDEF
1633 _TRACEMALLOC_GET_TRACEMALLOC_MEMORY_METHODDEF
1634 _TRACEMALLOC_GET_TRACED_MEMORY_METHODDEF
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001635 /* sentinel */
1636 {NULL, NULL}
1637};
1638
1639PyDoc_STRVAR(module_doc,
1640"Debug module to trace memory blocks allocated by Python.");
1641
1642static struct PyModuleDef module_def = {
1643 PyModuleDef_HEAD_INIT,
1644 "_tracemalloc",
1645 module_doc,
1646 0, /* non-negative size to be able to unload the module */
1647 module_methods,
1648 NULL,
1649};
1650
1651PyMODINIT_FUNC
1652PyInit__tracemalloc(void)
1653{
1654 PyObject *m;
1655 m = PyModule_Create(&module_def);
1656 if (m == NULL)
1657 return NULL;
1658
1659 if (tracemalloc_init() < 0)
1660 return NULL;
1661
1662 return m;
1663}
1664
Victor Stinnere492ae52016-03-22 12:58:23 +01001665
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001666int
Victor Stinnera7368ac2017-11-15 18:11:45 -08001667_PyTraceMalloc_Init(int nframe)
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001668{
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001669 assert(PyGILState_Check());
Victor Stinnera7368ac2017-11-15 18:11:45 -08001670 if (nframe == 0) {
1671 return 0;
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001672 }
Victor Stinnerf28ce602013-11-27 22:27:13 +01001673 return tracemalloc_start(nframe);
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001674}
1675
Victor Stinnere492ae52016-03-22 12:58:23 +01001676
Victor Stinnerbe0708f2013-12-01 10:03:26 +01001677void
1678_PyTraceMalloc_Fini(void)
1679{
Victor Stinnerbe0708f2013-12-01 10:03:26 +01001680 assert(PyGILState_Check());
Victor Stinnerbe0708f2013-12-01 10:03:26 +01001681 tracemalloc_deinit();
1682}
Victor Stinner10b73e12016-03-22 13:39:05 +01001683
1684int
Victor Stinner5ea4c062017-06-20 17:46:36 +02001685PyTraceMalloc_Track(unsigned int domain, uintptr_t ptr,
1686 size_t size)
Victor Stinner10b73e12016-03-22 13:39:05 +01001687{
1688 int res;
Victor Stinner10b73e12016-03-22 13:39:05 +01001689 PyGILState_STATE gil_state;
Victor Stinner10b73e12016-03-22 13:39:05 +01001690
Victor Stinner9e00e802018-10-25 13:31:16 +02001691 if (!_Py_tracemalloc_config.tracing) {
Victor Stinner10b73e12016-03-22 13:39:05 +01001692 /* tracemalloc is not tracing: do nothing */
1693 return -2;
1694 }
1695
Victor Stinner10b73e12016-03-22 13:39:05 +01001696 gil_state = PyGILState_Ensure();
Victor Stinner10b73e12016-03-22 13:39:05 +01001697
1698 TABLES_LOCK();
1699 res = tracemalloc_add_trace(domain, ptr, size);
1700 TABLES_UNLOCK();
1701
Victor Stinner10b73e12016-03-22 13:39:05 +01001702 PyGILState_Release(gil_state);
Victor Stinner10b73e12016-03-22 13:39:05 +01001703 return res;
1704}
1705
1706
1707int
Victor Stinner5ea4c062017-06-20 17:46:36 +02001708PyTraceMalloc_Untrack(unsigned int domain, uintptr_t ptr)
Victor Stinner10b73e12016-03-22 13:39:05 +01001709{
Victor Stinner9e00e802018-10-25 13:31:16 +02001710 if (!_Py_tracemalloc_config.tracing) {
Victor Stinner10b73e12016-03-22 13:39:05 +01001711 /* tracemalloc is not tracing: do nothing */
1712 return -2;
1713 }
1714
1715 TABLES_LOCK();
1716 tracemalloc_remove_trace(domain, ptr);
1717 TABLES_UNLOCK();
1718
1719 return 0;
1720}
1721
1722
Victor Stinner9e00e802018-10-25 13:31:16 +02001723/* If the object memory block is already traced, update its trace
1724 with the current Python traceback.
1725
1726 Do nothing if tracemalloc is not tracing memory allocations
1727 or if the object memory block is not already traced. */
1728int
1729_PyTraceMalloc_NewReference(PyObject *op)
1730{
1731 assert(PyGILState_Check());
1732
1733 if (!_Py_tracemalloc_config.tracing) {
1734 /* tracemalloc is not tracing: do nothing */
1735 return -1;
1736 }
1737
1738 uintptr_t ptr;
1739 PyTypeObject *type = Py_TYPE(op);
1740 if (PyType_IS_GC(type)) {
1741 ptr = (uintptr_t)((char *)op - sizeof(PyGC_Head));
1742 }
1743 else {
1744 ptr = (uintptr_t)op;
1745 }
1746
1747 _Py_hashtable_entry_t* entry;
1748 int res = -1;
1749
1750 TABLES_LOCK();
1751 if (_Py_tracemalloc_config.use_domain) {
1752 pointer_t key = {ptr, DEFAULT_DOMAIN};
1753 entry = _Py_HASHTABLE_GET_ENTRY(tracemalloc_traces, key);
1754 }
1755 else {
1756 entry = _Py_HASHTABLE_GET_ENTRY(tracemalloc_traces, ptr);
1757 }
1758
1759 if (entry != NULL) {
1760 /* update the traceback of the memory block */
1761 traceback_t *traceback = traceback_new();
1762 if (traceback != NULL) {
1763 trace_t trace;
1764 _Py_HASHTABLE_ENTRY_READ_DATA(tracemalloc_traces, entry, trace);
1765 trace.traceback = traceback;
1766 _Py_HASHTABLE_ENTRY_WRITE_DATA(tracemalloc_traces, entry, trace);
1767 res = 0;
1768 }
1769 }
1770 /* else: cannot track the object, its memory block size is unknown */
1771 TABLES_UNLOCK();
1772
1773 return res;
1774}
1775
1776
Victor Stinner10b73e12016-03-22 13:39:05 +01001777PyObject*
Victor Stinner5ea4c062017-06-20 17:46:36 +02001778_PyTraceMalloc_GetTraceback(unsigned int domain, uintptr_t ptr)
Victor Stinner10b73e12016-03-22 13:39:05 +01001779{
1780 traceback_t *traceback;
1781
1782 traceback = tracemalloc_get_traceback(domain, ptr);
1783 if (traceback == NULL)
1784 Py_RETURN_NONE;
1785
1786 return traceback_to_pyobject(traceback, NULL);
1787}