blob: af2a2fa4d52f24f5b7f227e08be3b381b077bc5c [file] [log] [blame]
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001#include "Python.h"
2#include "hashtable.h"
3#include "frameobject.h"
4#include "pythread.h"
5#include "osdefs.h"
6
Serhiy Storchakab451f912017-02-04 12:18:38 +02007#include "clinic/_tracemalloc.c.h"
8/*[clinic input]
9module _tracemalloc
10[clinic start generated code]*/
11/*[clinic end generated code: output=da39a3ee5e6b4b0d input=708a98302fc46e5f]*/
12
Victor Stinnered3b0bc2013-11-23 12:27:24 +010013/* Trace memory blocks allocated by PyMem_RawMalloc() */
14#define TRACE_RAW_MALLOC
15
16/* Forward declaration */
17static void tracemalloc_stop(void);
Victor Stinnered3b0bc2013-11-23 12:27:24 +010018static void* raw_malloc(size_t size);
19static void raw_free(void *ptr);
20
21#ifdef Py_DEBUG
22# define TRACE_DEBUG
23#endif
24
Victor Stinnered3b0bc2013-11-23 12:27:24 +010025/* Protected by the GIL */
26static struct {
Victor Stinnerd8f0d922014-06-02 21:57:10 +020027 PyMemAllocatorEx mem;
28 PyMemAllocatorEx raw;
29 PyMemAllocatorEx obj;
Victor Stinnered3b0bc2013-11-23 12:27:24 +010030} allocators;
31
Victor Stinnered3b0bc2013-11-23 12:27:24 +010032static struct {
33 /* Module initialized?
34 Variable protected by the GIL */
35 enum {
36 TRACEMALLOC_NOT_INITIALIZED,
37 TRACEMALLOC_INITIALIZED,
38 TRACEMALLOC_FINALIZED
39 } initialized;
40
Victor Stinnered3b0bc2013-11-23 12:27:24 +010041 /* Is tracemalloc tracing memory allocations?
42 Variable protected by the GIL */
43 int tracing;
44
45 /* limit of the number of frames in a traceback, 1 by default.
46 Variable protected by the GIL. */
47 int max_nframe;
Victor Stinnere492ae52016-03-22 12:58:23 +010048
49 /* use domain in trace key?
50 Variable protected by the GIL. */
51 int use_domain;
Victor Stinner5e14a382016-03-23 22:03:55 +010052} tracemalloc_config = {TRACEMALLOC_NOT_INITIALIZED, 0, 1, 0};
Victor Stinnered3b0bc2013-11-23 12:27:24 +010053
Antoine Pitroua6a4dc82017-09-07 18:56:24 +020054#if defined(TRACE_RAW_MALLOC)
Victor Stinnered3b0bc2013-11-23 12:27:24 +010055/* This lock is needed because tracemalloc_free() is called without
56 the GIL held from PyMem_RawFree(). It cannot acquire the lock because it
57 would introduce a deadlock in PyThreadState_DeleteCurrent(). */
58static PyThread_type_lock tables_lock;
59# define TABLES_LOCK() PyThread_acquire_lock(tables_lock, 1)
60# define TABLES_UNLOCK() PyThread_release_lock(tables_lock)
61#else
62 /* variables are protected by the GIL */
63# define TABLES_LOCK()
64# define TABLES_UNLOCK()
65#endif
66
Victor Stinnere492ae52016-03-22 12:58:23 +010067
68#define DEFAULT_DOMAIN 0
69
Victor Stinnere492ae52016-03-22 12:58:23 +010070/* Pack the frame_t structure to reduce the memory footprint. */
71typedef struct
72#ifdef __GNUC__
73__attribute__((packed))
74#endif
75{
Benjamin Petersonca470632016-09-06 13:47:26 -070076 uintptr_t ptr;
Victor Stinner5ea4c062017-06-20 17:46:36 +020077 unsigned int domain;
Victor Stinnere492ae52016-03-22 12:58:23 +010078} pointer_t;
79
Victor Stinnered3b0bc2013-11-23 12:27:24 +010080/* Pack the frame_t structure to reduce the memory footprint on 64-bit
Victor Stinnere492ae52016-03-22 12:58:23 +010081 architectures: 12 bytes instead of 16. */
Victor Stinnered3b0bc2013-11-23 12:27:24 +010082typedef struct
83#ifdef __GNUC__
84__attribute__((packed))
Victor Stinnerdd382ef2014-02-01 03:43:58 +010085#elif defined(_MSC_VER)
Segev Finer39243772017-07-25 11:47:43 +030086#pragma pack(push, 4)
Victor Stinnered3b0bc2013-11-23 12:27:24 +010087#endif
88{
Victor Stinner7105e9f2016-03-15 14:28:04 +010089 /* filename cannot be NULL: "<unknown>" is used if the Python frame
90 filename is NULL */
Victor Stinnered3b0bc2013-11-23 12:27:24 +010091 PyObject *filename;
Victor Stinner95283342016-03-15 21:57:02 +010092 unsigned int lineno;
Victor Stinnered3b0bc2013-11-23 12:27:24 +010093} frame_t;
Segev Finer39243772017-07-25 11:47:43 +030094#ifdef _MSC_VER
95#pragma pack(pop)
96#endif
Victor Stinnered3b0bc2013-11-23 12:27:24 +010097
Victor Stinnere492ae52016-03-22 12:58:23 +010098
Victor Stinnered3b0bc2013-11-23 12:27:24 +010099typedef struct {
100 Py_uhash_t hash;
101 int nframe;
102 frame_t frames[1];
103} traceback_t;
104
105#define TRACEBACK_SIZE(NFRAME) \
106 (sizeof(traceback_t) + sizeof(frame_t) * (NFRAME - 1))
Victor Stinnerf28ce602013-11-27 22:27:13 +0100107
108#define MAX_NFRAME \
Victor Stinner52aee852014-08-16 15:44:02 +0200109 ((INT_MAX - (int)sizeof(traceback_t)) / (int)sizeof(frame_t) + 1)
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100110
Victor Stinnere492ae52016-03-22 12:58:23 +0100111
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100112static PyObject *unknown_filename = NULL;
113static traceback_t tracemalloc_empty_traceback;
114
Victor Stinner7a5be142013-11-26 01:06:02 +0100115/* Trace of a memory block */
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100116typedef struct {
Victor Stinner7a5be142013-11-26 01:06:02 +0100117 /* Size of the memory block in bytes */
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100118 size_t size;
Victor Stinner7a5be142013-11-26 01:06:02 +0100119
120 /* Traceback where the memory block was allocated */
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100121 traceback_t *traceback;
122} trace_t;
123
Victor Stinnere492ae52016-03-22 12:58:23 +0100124
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100125/* Size in bytes of currently traced memory.
126 Protected by TABLES_LOCK(). */
127static size_t tracemalloc_traced_memory = 0;
128
Victor Stinner3c0481d2013-11-27 21:39:49 +0100129/* Peak size in bytes of traced memory.
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100130 Protected by TABLES_LOCK(). */
Victor Stinner3c0481d2013-11-27 21:39:49 +0100131static size_t tracemalloc_peak_traced_memory = 0;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100132
Serhiy Storchaka56a6d852014-12-01 18:28:43 +0200133/* Hash table used as a set to intern filenames:
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100134 PyObject* => PyObject*.
135 Protected by the GIL */
136static _Py_hashtable_t *tracemalloc_filenames = NULL;
137
Victor Stinnerf28ce602013-11-27 22:27:13 +0100138/* Buffer to store a new traceback in traceback_new().
139 Protected by the GIL. */
140static traceback_t *tracemalloc_traceback = NULL;
141
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100142/* Hash table used as a set to intern tracebacks:
143 traceback_t* => traceback_t*
144 Protected by the GIL */
145static _Py_hashtable_t *tracemalloc_tracebacks = NULL;
146
147/* pointer (void*) => trace (trace_t).
148 Protected by TABLES_LOCK(). */
149static _Py_hashtable_t *tracemalloc_traces = NULL;
150
Victor Stinnere492ae52016-03-22 12:58:23 +0100151
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100152#ifdef TRACE_DEBUG
153static void
154tracemalloc_error(const char *format, ...)
155{
156 va_list ap;
157 fprintf(stderr, "tracemalloc: ");
158 va_start(ap, format);
159 vfprintf(stderr, format, ap);
160 va_end(ap);
161 fprintf(stderr, "\n");
162 fflush(stderr);
163}
164#endif
165
Victor Stinnere492ae52016-03-22 12:58:23 +0100166
Antoine Pitroua6a4dc82017-09-07 18:56:24 +0200167#if defined(TRACE_RAW_MALLOC)
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100168#define REENTRANT_THREADLOCAL
169
Masayuki Yamamoto731e1892017-10-06 19:41:34 +0900170static Py_tss_t tracemalloc_reentrant_key = Py_tss_NEEDS_INIT;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100171
172/* Any non-NULL pointer can be used */
173#define REENTRANT Py_True
174
175static int
176get_reentrant(void)
177{
Victor Stinner4a066472016-03-22 17:45:09 +0100178 void *ptr;
179
Masayuki Yamamoto731e1892017-10-06 19:41:34 +0900180 assert(PyThread_tss_is_created(&tracemalloc_reentrant_key));
181 ptr = PyThread_tss_get(&tracemalloc_reentrant_key);
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100182 if (ptr != NULL) {
183 assert(ptr == REENTRANT);
184 return 1;
185 }
186 else
187 return 0;
188}
189
190static void
191set_reentrant(int reentrant)
192{
Victor Stinner2ead3d22013-11-26 01:08:53 +0100193 assert(reentrant == 0 || reentrant == 1);
Masayuki Yamamoto731e1892017-10-06 19:41:34 +0900194 assert(PyThread_tss_is_created(&tracemalloc_reentrant_key));
Victor Stinner4a066472016-03-22 17:45:09 +0100195
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100196 if (reentrant) {
Victor Stinner0cfc0582016-03-22 17:40:07 +0100197 assert(!get_reentrant());
Masayuki Yamamoto731e1892017-10-06 19:41:34 +0900198 PyThread_tss_set(&tracemalloc_reentrant_key, REENTRANT);
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100199 }
200 else {
Victor Stinner0cfc0582016-03-22 17:40:07 +0100201 assert(get_reentrant());
Masayuki Yamamoto731e1892017-10-06 19:41:34 +0900202 PyThread_tss_set(&tracemalloc_reentrant_key, NULL);
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100203 }
204}
205
206#else
207
Antoine Pitroua6a4dc82017-09-07 18:56:24 +0200208/* TRACE_RAW_MALLOC not defined: variable protected by the GIL */
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100209static int tracemalloc_reentrant = 0;
210
211static int
212get_reentrant(void)
213{
214 return tracemalloc_reentrant;
215}
216
217static void
218set_reentrant(int reentrant)
219{
Victor Stinnerd5871e62016-03-23 00:17:04 +0100220 assert(reentrant != tracemalloc_reentrant);
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100221 tracemalloc_reentrant = reentrant;
222}
223#endif
224
Victor Stinnere492ae52016-03-22 12:58:23 +0100225
Victor Stinner285cf0a2016-03-21 22:00:58 +0100226static Py_uhash_t
Victor Stinner5dacbd42016-03-23 09:52:13 +0100227hashtable_hash_pyobject(_Py_hashtable_t *ht, const void *pkey)
Victor Stinner51b846c2016-03-18 21:52:22 +0100228{
Victor Stinner285cf0a2016-03-21 22:00:58 +0100229 PyObject *obj;
230
Victor Stinner5dacbd42016-03-23 09:52:13 +0100231 _Py_HASHTABLE_READ_KEY(ht, pkey, obj);
Victor Stinner285cf0a2016-03-21 22:00:58 +0100232 return PyObject_Hash(obj);
233}
234
Victor Stinnere492ae52016-03-22 12:58:23 +0100235
Victor Stinner285cf0a2016-03-21 22:00:58 +0100236static int
Victor Stinner5dacbd42016-03-23 09:52:13 +0100237hashtable_compare_unicode(_Py_hashtable_t *ht, const void *pkey,
Victor Stinner285cf0a2016-03-21 22:00:58 +0100238 const _Py_hashtable_entry_t *entry)
239{
Victor Stinnere492ae52016-03-22 12:58:23 +0100240 PyObject *key1, *key2;
Victor Stinner285cf0a2016-03-21 22:00:58 +0100241
Victor Stinner5dacbd42016-03-23 09:52:13 +0100242 _Py_HASHTABLE_READ_KEY(ht, pkey, key1);
243 _Py_HASHTABLE_ENTRY_READ_KEY(ht, entry, key2);
Victor Stinner285cf0a2016-03-21 22:00:58 +0100244
Victor Stinnere492ae52016-03-22 12:58:23 +0100245 if (key1 != NULL && key2 != NULL)
246 return (PyUnicode_Compare(key1, key2) == 0);
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100247 else
Victor Stinnere492ae52016-03-22 12:58:23 +0100248 return key1 == key2;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100249}
250
Victor Stinnere492ae52016-03-22 12:58:23 +0100251
252static Py_uhash_t
Victor Stinner5dacbd42016-03-23 09:52:13 +0100253hashtable_hash_pointer_t(_Py_hashtable_t *ht, const void *pkey)
Victor Stinnere492ae52016-03-22 12:58:23 +0100254{
255 pointer_t ptr;
256 Py_uhash_t hash;
257
Victor Stinner5dacbd42016-03-23 09:52:13 +0100258 _Py_HASHTABLE_READ_KEY(ht, pkey, ptr);
Victor Stinnere492ae52016-03-22 12:58:23 +0100259
260 hash = (Py_uhash_t)_Py_HashPointer((void*)ptr.ptr);
261 hash ^= ptr.domain;
262 return hash;
263}
264
265
doko@ubuntu.combc731502016-05-18 01:06:01 +0200266static int
Victor Stinner5dacbd42016-03-23 09:52:13 +0100267hashtable_compare_pointer_t(_Py_hashtable_t *ht, const void *pkey,
Victor Stinnere492ae52016-03-22 12:58:23 +0100268 const _Py_hashtable_entry_t *entry)
269{
270 pointer_t ptr1, ptr2;
271
Victor Stinner5dacbd42016-03-23 09:52:13 +0100272 _Py_HASHTABLE_READ_KEY(ht, pkey, ptr1);
273 _Py_HASHTABLE_ENTRY_READ_KEY(ht, entry, ptr2);
Victor Stinnere492ae52016-03-22 12:58:23 +0100274
275 /* compare pointer before domain, because pointer is more likely to be
276 different */
277 return (ptr1.ptr == ptr2.ptr && ptr1.domain == ptr2.domain);
278
279}
280
281
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100282static _Py_hashtable_t *
Victor Stinner285cf0a2016-03-21 22:00:58 +0100283hashtable_new(size_t key_size, size_t data_size,
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100284 _Py_hashtable_hash_func hash_func,
285 _Py_hashtable_compare_func compare_func)
286{
Victor Stinnerc9553872016-03-22 12:13:01 +0100287 _Py_hashtable_allocator_t hashtable_alloc = {malloc, free};
Victor Stinner285cf0a2016-03-21 22:00:58 +0100288 return _Py_hashtable_new_full(key_size, data_size, 0,
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100289 hash_func, compare_func,
Victor Stinnerc9553872016-03-22 12:13:01 +0100290 &hashtable_alloc);
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100291}
292
Victor Stinnere492ae52016-03-22 12:58:23 +0100293
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100294static void*
295raw_malloc(size_t size)
296{
297 return allocators.raw.malloc(allocators.raw.ctx, size);
298}
299
300static void
301raw_free(void *ptr)
302{
303 allocators.raw.free(allocators.raw.ctx, ptr);
304}
305
Victor Stinnere492ae52016-03-22 12:58:23 +0100306
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100307static Py_uhash_t
Victor Stinner5dacbd42016-03-23 09:52:13 +0100308hashtable_hash_traceback(_Py_hashtable_t *ht, const void *pkey)
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100309{
Victor Stinnerb32a7ed2016-03-21 23:05:08 +0100310 traceback_t *traceback;
Victor Stinner285cf0a2016-03-21 22:00:58 +0100311
Victor Stinner5dacbd42016-03-23 09:52:13 +0100312 _Py_HASHTABLE_READ_KEY(ht, pkey, traceback);
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100313 return traceback->hash;
314}
315
Victor Stinnere492ae52016-03-22 12:58:23 +0100316
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100317static int
Victor Stinner5dacbd42016-03-23 09:52:13 +0100318hashtable_compare_traceback(_Py_hashtable_t *ht, const void *pkey,
319 const _Py_hashtable_entry_t *entry)
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100320{
Victor Stinner285cf0a2016-03-21 22:00:58 +0100321 traceback_t *traceback1, *traceback2;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100322 const frame_t *frame1, *frame2;
323 int i;
324
Victor Stinner5dacbd42016-03-23 09:52:13 +0100325 _Py_HASHTABLE_READ_KEY(ht, pkey, traceback1);
326 _Py_HASHTABLE_ENTRY_READ_KEY(ht, entry, traceback2);
Victor Stinner285cf0a2016-03-21 22:00:58 +0100327
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100328 if (traceback1->nframe != traceback2->nframe)
329 return 0;
330
331 for (i=0; i < traceback1->nframe; i++) {
332 frame1 = &traceback1->frames[i];
333 frame2 = &traceback2->frames[i];
334
335 if (frame1->lineno != frame2->lineno)
336 return 0;
337
338 if (frame1->filename != frame2->filename) {
339 assert(PyUnicode_Compare(frame1->filename, frame2->filename) != 0);
340 return 0;
341 }
342 }
343 return 1;
344}
345
Victor Stinnere492ae52016-03-22 12:58:23 +0100346
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100347static void
348tracemalloc_get_frame(PyFrameObject *pyframe, frame_t *frame)
349{
350 PyCodeObject *code;
351 PyObject *filename;
352 _Py_hashtable_entry_t *entry;
Victor Stinner95283342016-03-15 21:57:02 +0100353 int lineno;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100354
355 frame->filename = unknown_filename;
Victor Stinner95283342016-03-15 21:57:02 +0100356 lineno = PyFrame_GetLineNumber(pyframe);
357 if (lineno < 0)
358 lineno = 0;
359 frame->lineno = (unsigned int)lineno;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100360
361 code = pyframe->f_code;
362 if (code == NULL) {
363#ifdef TRACE_DEBUG
Victor Stinner4dc74202013-11-26 01:18:52 +0100364 tracemalloc_error("failed to get the code object of the frame");
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100365#endif
366 return;
367 }
368
369 if (code->co_filename == NULL) {
370#ifdef TRACE_DEBUG
371 tracemalloc_error("failed to get the filename of the code object");
372#endif
373 return;
374 }
375
376 filename = code->co_filename;
377 assert(filename != NULL);
378 if (filename == NULL)
379 return;
380
381 if (!PyUnicode_Check(filename)) {
382#ifdef TRACE_DEBUG
Martin Panter6245cb32016-04-15 02:14:19 +0000383 tracemalloc_error("filename is not a unicode string");
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100384#endif
385 return;
386 }
387 if (!PyUnicode_IS_READY(filename)) {
388 /* Don't make a Unicode string ready to avoid reentrant calls
389 to tracemalloc_malloc() or tracemalloc_realloc() */
390#ifdef TRACE_DEBUG
391 tracemalloc_error("filename is not a ready unicode string");
392#endif
393 return;
394 }
395
396 /* intern the filename */
Victor Stinner285cf0a2016-03-21 22:00:58 +0100397 entry = _Py_HASHTABLE_GET_ENTRY(tracemalloc_filenames, filename);
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100398 if (entry != NULL) {
Victor Stinner5dacbd42016-03-23 09:52:13 +0100399 _Py_HASHTABLE_ENTRY_READ_KEY(tracemalloc_filenames, entry, filename);
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100400 }
401 else {
402 /* tracemalloc_filenames is responsible to keep a reference
403 to the filename */
404 Py_INCREF(filename);
Victor Stinner285cf0a2016-03-21 22:00:58 +0100405 if (_Py_HASHTABLE_SET_NODATA(tracemalloc_filenames, filename) < 0) {
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100406 Py_DECREF(filename);
407#ifdef TRACE_DEBUG
408 tracemalloc_error("failed to intern the filename");
409#endif
410 return;
411 }
412 }
413
414 /* the tracemalloc_filenames table keeps a reference to the filename */
415 frame->filename = filename;
416}
417
Victor Stinnere492ae52016-03-22 12:58:23 +0100418
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100419static Py_uhash_t
420traceback_hash(traceback_t *traceback)
421{
422 /* code based on tuplehash() of Objects/tupleobject.c */
Victor Stinner4d8c29c2013-12-16 23:05:13 +0100423 Py_uhash_t x, y; /* Unsigned for defined overflow behavior. */
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100424 int len = traceback->nframe;
425 Py_uhash_t mult = _PyHASH_MULTIPLIER;
426 frame_t *frame;
427
428 x = 0x345678UL;
429 frame = traceback->frames;
430 while (--len >= 0) {
Victor Stinner4d8c29c2013-12-16 23:05:13 +0100431 y = (Py_uhash_t)PyObject_Hash(frame->filename);
432 y ^= (Py_uhash_t)frame->lineno;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100433 frame++;
434
435 x = (x ^ y) * mult;
436 /* the cast might truncate len; that doesn't change hash stability */
Victor Stinner4d8c29c2013-12-16 23:05:13 +0100437 mult += (Py_uhash_t)(82520UL + len + len);
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100438 }
439 x += 97531UL;
440 return x;
441}
442
Victor Stinnere492ae52016-03-22 12:58:23 +0100443
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100444static void
445traceback_get_frames(traceback_t *traceback)
446{
447 PyThreadState *tstate;
448 PyFrameObject *pyframe;
449
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100450 tstate = PyGILState_GetThisThreadState();
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100451 if (tstate == NULL) {
452#ifdef TRACE_DEBUG
453 tracemalloc_error("failed to get the current thread state");
454#endif
455 return;
456 }
457
458 for (pyframe = tstate->frame; pyframe != NULL; pyframe = pyframe->f_back) {
459 tracemalloc_get_frame(pyframe, &traceback->frames[traceback->nframe]);
460 assert(traceback->frames[traceback->nframe].filename != NULL);
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100461 traceback->nframe++;
462 if (traceback->nframe == tracemalloc_config.max_nframe)
463 break;
464 }
465}
466
Victor Stinnere492ae52016-03-22 12:58:23 +0100467
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100468static traceback_t *
469traceback_new(void)
470{
Victor Stinnerf28ce602013-11-27 22:27:13 +0100471 traceback_t *traceback;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100472 _Py_hashtable_entry_t *entry;
473
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100474 assert(PyGILState_Check());
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100475
476 /* get frames */
Victor Stinnerf28ce602013-11-27 22:27:13 +0100477 traceback = tracemalloc_traceback;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100478 traceback->nframe = 0;
479 traceback_get_frames(traceback);
480 if (traceback->nframe == 0)
481 return &tracemalloc_empty_traceback;
482 traceback->hash = traceback_hash(traceback);
483
484 /* intern the traceback */
Victor Stinner285cf0a2016-03-21 22:00:58 +0100485 entry = _Py_HASHTABLE_GET_ENTRY(tracemalloc_tracebacks, traceback);
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100486 if (entry != NULL) {
Victor Stinner5dacbd42016-03-23 09:52:13 +0100487 _Py_HASHTABLE_ENTRY_READ_KEY(tracemalloc_tracebacks, entry, traceback);
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100488 }
489 else {
490 traceback_t *copy;
491 size_t traceback_size;
492
493 traceback_size = TRACEBACK_SIZE(traceback->nframe);
494
495 copy = raw_malloc(traceback_size);
496 if (copy == NULL) {
497#ifdef TRACE_DEBUG
498 tracemalloc_error("failed to intern the traceback: malloc failed");
499#endif
500 return NULL;
501 }
502 memcpy(copy, traceback, traceback_size);
503
Victor Stinner285cf0a2016-03-21 22:00:58 +0100504 if (_Py_HASHTABLE_SET_NODATA(tracemalloc_tracebacks, copy) < 0) {
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100505 raw_free(copy);
506#ifdef TRACE_DEBUG
507 tracemalloc_error("failed to intern the traceback: putdata failed");
508#endif
509 return NULL;
510 }
511 traceback = copy;
512 }
513 return traceback;
514}
515
Victor Stinnere492ae52016-03-22 12:58:23 +0100516
Victor Stinner5e14a382016-03-23 22:03:55 +0100517static int
518tracemalloc_use_domain_cb(_Py_hashtable_t *old_traces,
519 _Py_hashtable_entry_t *entry, void *user_data)
520{
Benjamin Petersonca470632016-09-06 13:47:26 -0700521 uintptr_t ptr;
Victor Stinner5e14a382016-03-23 22:03:55 +0100522 pointer_t key;
523 _Py_hashtable_t *new_traces = (_Py_hashtable_t *)user_data;
524 const void *pdata = _Py_HASHTABLE_ENTRY_PDATA(old_traces, entry);
525
526 _Py_HASHTABLE_ENTRY_READ_KEY(old_traces, entry, ptr);
527 key.ptr = ptr;
528 key.domain = DEFAULT_DOMAIN;
529
530 return _Py_hashtable_set(new_traces,
531 sizeof(key), &key,
532 old_traces->data_size, pdata);
533}
534
535
Benjamin Petersonca470632016-09-06 13:47:26 -0700536/* Convert tracemalloc_traces from compact key (uintptr_t) to pointer_t key.
Victor Stinner5e14a382016-03-23 22:03:55 +0100537 * Return 0 on success, -1 on error. */
538static int
539tracemalloc_use_domain(void)
540{
541 _Py_hashtable_t *new_traces = NULL;
542
543 assert(!tracemalloc_config.use_domain);
544
545 new_traces = hashtable_new(sizeof(pointer_t),
546 sizeof(trace_t),
547 hashtable_hash_pointer_t,
548 hashtable_compare_pointer_t);
549 if (new_traces == NULL) {
550 return -1;
551 }
552
553 if (_Py_hashtable_foreach(tracemalloc_traces, tracemalloc_use_domain_cb,
554 new_traces) < 0)
555 {
556 _Py_hashtable_destroy(new_traces);
557 return -1;
558 }
559
560 _Py_hashtable_destroy(tracemalloc_traces);
561 tracemalloc_traces = new_traces;
562
563 tracemalloc_config.use_domain = 1;
564
565 return 0;
566}
567
568
Victor Stinnere492ae52016-03-22 12:58:23 +0100569static void
Victor Stinner5ea4c062017-06-20 17:46:36 +0200570tracemalloc_remove_trace(unsigned int domain, uintptr_t ptr)
Victor Stinnere492ae52016-03-22 12:58:23 +0100571{
572 trace_t trace;
573 int removed;
574
Victor Stinner10b73e12016-03-22 13:39:05 +0100575 assert(tracemalloc_config.tracing);
576
Victor Stinnere492ae52016-03-22 12:58:23 +0100577 if (tracemalloc_config.use_domain) {
578 pointer_t key = {ptr, domain};
579 removed = _Py_HASHTABLE_POP(tracemalloc_traces, key, trace);
580 }
581 else {
582 removed = _Py_HASHTABLE_POP(tracemalloc_traces, ptr, trace);
583 }
584 if (!removed) {
585 return;
586 }
587
588 assert(tracemalloc_traced_memory >= trace.size);
589 tracemalloc_traced_memory -= trace.size;
590}
591
592#define REMOVE_TRACE(ptr) \
Benjamin Petersonca470632016-09-06 13:47:26 -0700593 tracemalloc_remove_trace(DEFAULT_DOMAIN, (uintptr_t)(ptr))
Victor Stinnere492ae52016-03-22 12:58:23 +0100594
595
Victor Stinner52968672013-11-24 11:37:15 +0100596static int
Victor Stinner5ea4c062017-06-20 17:46:36 +0200597tracemalloc_add_trace(unsigned int domain, uintptr_t ptr,
Victor Stinner10b73e12016-03-22 13:39:05 +0100598 size_t size)
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100599{
Victor Stinnerca79ccd2016-03-23 09:38:54 +0100600 pointer_t key = {ptr, domain};
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100601 traceback_t *traceback;
602 trace_t trace;
Victor Stinnerca79ccd2016-03-23 09:38:54 +0100603 _Py_hashtable_entry_t* entry;
Victor Stinner52968672013-11-24 11:37:15 +0100604 int res;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100605
Victor Stinner10b73e12016-03-22 13:39:05 +0100606 assert(tracemalloc_config.tracing);
607
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100608 traceback = traceback_new();
Victor Stinnere492ae52016-03-22 12:58:23 +0100609 if (traceback == NULL) {
Victor Stinner52968672013-11-24 11:37:15 +0100610 return -1;
Victor Stinnere492ae52016-03-22 12:58:23 +0100611 }
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100612
Victor Stinner5e14a382016-03-23 22:03:55 +0100613 if (!tracemalloc_config.use_domain && domain != DEFAULT_DOMAIN) {
614 /* first trace using a non-zero domain whereas traces use compact
Benjamin Petersonca470632016-09-06 13:47:26 -0700615 (uintptr_t) keys: switch to pointer_t keys. */
Victor Stinner5e14a382016-03-23 22:03:55 +0100616 if (tracemalloc_use_domain() < 0) {
617 return -1;
618 }
619 }
620
Victor Stinnere492ae52016-03-22 12:58:23 +0100621 if (tracemalloc_config.use_domain) {
Victor Stinnerca79ccd2016-03-23 09:38:54 +0100622 entry = _Py_HASHTABLE_GET_ENTRY(tracemalloc_traces, key);
Victor Stinnere492ae52016-03-22 12:58:23 +0100623 }
624 else {
Victor Stinnerca79ccd2016-03-23 09:38:54 +0100625 entry = _Py_HASHTABLE_GET_ENTRY(tracemalloc_traces, ptr);
Victor Stinnerd606ba72013-11-24 11:28:20 +0100626 }
Victor Stinner52968672013-11-24 11:37:15 +0100627
Victor Stinnerca79ccd2016-03-23 09:38:54 +0100628 if (entry != NULL) {
629 /* the memory block is already tracked */
630 _Py_HASHTABLE_ENTRY_READ_DATA(tracemalloc_traces, entry, trace);
631 assert(tracemalloc_traced_memory >= trace.size);
632 tracemalloc_traced_memory -= trace.size;
633
634 trace.size = size;
635 trace.traceback = traceback;
636 _Py_HASHTABLE_ENTRY_WRITE_DATA(tracemalloc_traces, entry, trace);
637 }
638 else {
639 trace.size = size;
640 trace.traceback = traceback;
641
642 if (tracemalloc_config.use_domain) {
643 res = _Py_HASHTABLE_SET(tracemalloc_traces, key, trace);
644 }
645 else {
646 res = _Py_HASHTABLE_SET(tracemalloc_traces, ptr, trace);
647 }
648 if (res != 0) {
649 return res;
650 }
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100651 }
Victor Stinnere492ae52016-03-22 12:58:23 +0100652
Benjamin Peterson2f8bfef2016-09-07 09:26:18 -0700653 assert(tracemalloc_traced_memory <= SIZE_MAX - size);
Victor Stinnere492ae52016-03-22 12:58:23 +0100654 tracemalloc_traced_memory += size;
655 if (tracemalloc_traced_memory > tracemalloc_peak_traced_memory)
656 tracemalloc_peak_traced_memory = tracemalloc_traced_memory;
657 return 0;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100658}
659
Victor Stinnere492ae52016-03-22 12:58:23 +0100660#define ADD_TRACE(ptr, size) \
Benjamin Petersonca470632016-09-06 13:47:26 -0700661 tracemalloc_add_trace(DEFAULT_DOMAIN, (uintptr_t)(ptr), size)
Victor Stinnere492ae52016-03-22 12:58:23 +0100662
663
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100664static void*
Victor Stinnerdb067af2014-05-02 22:31:14 +0200665tracemalloc_alloc(int use_calloc, void *ctx, size_t nelem, size_t elsize)
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100666{
Victor Stinnerd8f0d922014-06-02 21:57:10 +0200667 PyMemAllocatorEx *alloc = (PyMemAllocatorEx *)ctx;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100668 void *ptr;
669
Benjamin Peterson2f8bfef2016-09-07 09:26:18 -0700670 assert(elsize == 0 || nelem <= SIZE_MAX / elsize);
Victor Stinnerdb067af2014-05-02 22:31:14 +0200671
672 if (use_calloc)
673 ptr = alloc->calloc(alloc->ctx, nelem, elsize);
674 else
675 ptr = alloc->malloc(alloc->ctx, nelem * elsize);
Victor Stinner15116802013-12-04 01:29:35 +0100676 if (ptr == NULL)
677 return NULL;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100678
Victor Stinner88c29872013-12-04 01:47:46 +0100679 TABLES_LOCK();
Victor Stinnere492ae52016-03-22 12:58:23 +0100680 if (ADD_TRACE(ptr, nelem * elsize) < 0) {
Victor Stinner15116802013-12-04 01:29:35 +0100681 /* Failed to allocate a trace for the new memory block */
Victor Stinner88c29872013-12-04 01:47:46 +0100682 TABLES_UNLOCK();
Victor Stinner15116802013-12-04 01:29:35 +0100683 alloc->free(alloc->ctx, ptr);
684 return NULL;
Victor Stinner52968672013-11-24 11:37:15 +0100685 }
Victor Stinner88c29872013-12-04 01:47:46 +0100686 TABLES_UNLOCK();
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100687 return ptr;
688}
689
Victor Stinnere492ae52016-03-22 12:58:23 +0100690
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100691static void*
Victor Stinner15116802013-12-04 01:29:35 +0100692tracemalloc_realloc(void *ctx, void *ptr, size_t new_size)
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100693{
Victor Stinnerd8f0d922014-06-02 21:57:10 +0200694 PyMemAllocatorEx *alloc = (PyMemAllocatorEx *)ctx;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100695 void *ptr2;
696
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100697 ptr2 = alloc->realloc(alloc->ctx, ptr, new_size);
Victor Stinner15116802013-12-04 01:29:35 +0100698 if (ptr2 == NULL)
699 return NULL;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100700
Victor Stinner15116802013-12-04 01:29:35 +0100701 if (ptr != NULL) {
702 /* an existing memory block has been resized */
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100703
Victor Stinner88c29872013-12-04 01:47:46 +0100704 TABLES_LOCK();
Victor Stinner42bcf372016-03-23 09:08:08 +0100705
706 /* tracemalloc_add_trace() updates the trace if there is already
707 a trace at address (domain, ptr2) */
708 if (ptr2 != ptr) {
709 REMOVE_TRACE(ptr);
710 }
Victor Stinner08facd22013-11-24 12:27:59 +0100711
Victor Stinnere492ae52016-03-22 12:58:23 +0100712 if (ADD_TRACE(ptr2, new_size) < 0) {
Victor Stinner15116802013-12-04 01:29:35 +0100713 /* Memory allocation failed. The error cannot be reported to
Raymond Hettinger15f44ab2016-08-30 10:47:49 -0700714 the caller, because realloc() may already have shrunk the
Victor Stinner15116802013-12-04 01:29:35 +0100715 memory block and so removed bytes.
716
Serhiy Storchaka6a7b3a72016-04-17 08:32:47 +0300717 This case is very unlikely: a hash entry has just been
Victor Stinner88c29872013-12-04 01:47:46 +0100718 released, so the hash table should have at least one free entry.
719
720 The GIL and the table lock ensures that only one thread is
721 allocating memory. */
Barry Warsawb2e57942017-09-14 18:13:16 -0700722 Py_UNREACHABLE();
Victor Stinner52968672013-11-24 11:37:15 +0100723 }
Victor Stinner88c29872013-12-04 01:47:46 +0100724 TABLES_UNLOCK();
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100725 }
Victor Stinner15116802013-12-04 01:29:35 +0100726 else {
727 /* new allocation */
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100728
Victor Stinner88c29872013-12-04 01:47:46 +0100729 TABLES_LOCK();
Victor Stinnere492ae52016-03-22 12:58:23 +0100730 if (ADD_TRACE(ptr2, new_size) < 0) {
Victor Stinner15116802013-12-04 01:29:35 +0100731 /* Failed to allocate a trace for the new memory block */
Victor Stinner88c29872013-12-04 01:47:46 +0100732 TABLES_UNLOCK();
Victor Stinner15116802013-12-04 01:29:35 +0100733 alloc->free(alloc->ctx, ptr2);
734 return NULL;
735 }
Victor Stinner88c29872013-12-04 01:47:46 +0100736 TABLES_UNLOCK();
Victor Stinner15116802013-12-04 01:29:35 +0100737 }
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100738 return ptr2;
739}
740
Victor Stinnere492ae52016-03-22 12:58:23 +0100741
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100742static void
743tracemalloc_free(void *ctx, void *ptr)
744{
Victor Stinnerd8f0d922014-06-02 21:57:10 +0200745 PyMemAllocatorEx *alloc = (PyMemAllocatorEx *)ctx;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100746
747 if (ptr == NULL)
748 return;
749
750 /* GIL cannot be locked in PyMem_RawFree() because it would introduce
751 a deadlock in PyThreadState_DeleteCurrent(). */
752
753 alloc->free(alloc->ctx, ptr);
Victor Stinner88c29872013-12-04 01:47:46 +0100754
755 TABLES_LOCK();
Victor Stinnere492ae52016-03-22 12:58:23 +0100756 REMOVE_TRACE(ptr);
Victor Stinner88c29872013-12-04 01:47:46 +0100757 TABLES_UNLOCK();
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100758}
759
Victor Stinnere492ae52016-03-22 12:58:23 +0100760
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100761static void*
Victor Stinnerdb067af2014-05-02 22:31:14 +0200762tracemalloc_alloc_gil(int use_calloc, void *ctx, size_t nelem, size_t elsize)
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100763{
Victor Stinner15116802013-12-04 01:29:35 +0100764 void *ptr;
765
766 if (get_reentrant()) {
Victor Stinnerd8f0d922014-06-02 21:57:10 +0200767 PyMemAllocatorEx *alloc = (PyMemAllocatorEx *)ctx;
Victor Stinnerdb067af2014-05-02 22:31:14 +0200768 if (use_calloc)
769 return alloc->calloc(alloc->ctx, nelem, elsize);
770 else
771 return alloc->malloc(alloc->ctx, nelem * elsize);
Victor Stinner15116802013-12-04 01:29:35 +0100772 }
773
774 /* Ignore reentrant call. PyObjet_Malloc() calls PyMem_Malloc() for
775 allocations larger than 512 bytes, don't trace the same memory
776 allocation twice. */
777 set_reentrant(1);
778
Victor Stinnerdb067af2014-05-02 22:31:14 +0200779 ptr = tracemalloc_alloc(use_calloc, ctx, nelem, elsize);
Victor Stinner15116802013-12-04 01:29:35 +0100780
781 set_reentrant(0);
782 return ptr;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100783}
784
Victor Stinnere492ae52016-03-22 12:58:23 +0100785
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100786static void*
Victor Stinnerdb067af2014-05-02 22:31:14 +0200787tracemalloc_malloc_gil(void *ctx, size_t size)
788{
789 return tracemalloc_alloc_gil(0, ctx, 1, size);
790}
791
Victor Stinnere492ae52016-03-22 12:58:23 +0100792
Victor Stinnerdb067af2014-05-02 22:31:14 +0200793static void*
794tracemalloc_calloc_gil(void *ctx, size_t nelem, size_t elsize)
795{
796 return tracemalloc_alloc_gil(1, ctx, nelem, elsize);
797}
798
Victor Stinnere492ae52016-03-22 12:58:23 +0100799
Victor Stinnerdb067af2014-05-02 22:31:14 +0200800static void*
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100801tracemalloc_realloc_gil(void *ctx, void *ptr, size_t new_size)
802{
Victor Stinner15116802013-12-04 01:29:35 +0100803 void *ptr2;
804
805 if (get_reentrant()) {
806 /* Reentrant call to PyMem_Realloc() and PyMem_RawRealloc().
807 Example: PyMem_RawRealloc() is called internally by pymalloc
808 (_PyObject_Malloc() and _PyObject_Realloc()) to allocate a new
809 arena (new_arena()). */
Victor Stinnerd8f0d922014-06-02 21:57:10 +0200810 PyMemAllocatorEx *alloc = (PyMemAllocatorEx *)ctx;
Victor Stinner15116802013-12-04 01:29:35 +0100811
812 ptr2 = alloc->realloc(alloc->ctx, ptr, new_size);
Victor Stinner88c29872013-12-04 01:47:46 +0100813 if (ptr2 != NULL && ptr != NULL) {
814 TABLES_LOCK();
Victor Stinnere492ae52016-03-22 12:58:23 +0100815 REMOVE_TRACE(ptr);
Victor Stinner88c29872013-12-04 01:47:46 +0100816 TABLES_UNLOCK();
817 }
Victor Stinner15116802013-12-04 01:29:35 +0100818 return ptr2;
819 }
820
821 /* Ignore reentrant call. PyObjet_Realloc() calls PyMem_Realloc() for
822 allocations larger than 512 bytes. Don't trace the same memory
823 allocation twice. */
824 set_reentrant(1);
825
826 ptr2 = tracemalloc_realloc(ctx, ptr, new_size);
827
828 set_reentrant(0);
829 return ptr2;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100830}
831
Victor Stinnere492ae52016-03-22 12:58:23 +0100832
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100833#ifdef TRACE_RAW_MALLOC
834static void*
Victor Stinnerdb067af2014-05-02 22:31:14 +0200835tracemalloc_raw_alloc(int use_calloc, void *ctx, size_t nelem, size_t elsize)
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100836{
Victor Stinner15116802013-12-04 01:29:35 +0100837 PyGILState_STATE gil_state;
Victor Stinner15116802013-12-04 01:29:35 +0100838 void *ptr;
839
840 if (get_reentrant()) {
Victor Stinnerd8f0d922014-06-02 21:57:10 +0200841 PyMemAllocatorEx *alloc = (PyMemAllocatorEx *)ctx;
Victor Stinnerdb067af2014-05-02 22:31:14 +0200842 if (use_calloc)
843 return alloc->calloc(alloc->ctx, nelem, elsize);
844 else
845 return alloc->malloc(alloc->ctx, nelem * elsize);
Victor Stinner15116802013-12-04 01:29:35 +0100846 }
847
848 /* Ignore reentrant call. PyGILState_Ensure() may call PyMem_RawMalloc()
849 indirectly which would call PyGILState_Ensure() if reentrant are not
850 disabled. */
851 set_reentrant(1);
852
Victor Stinner15116802013-12-04 01:29:35 +0100853 gil_state = PyGILState_Ensure();
Victor Stinnerdb067af2014-05-02 22:31:14 +0200854 ptr = tracemalloc_alloc(use_calloc, ctx, nelem, elsize);
Victor Stinner15116802013-12-04 01:29:35 +0100855 PyGILState_Release(gil_state);
Victor Stinner15116802013-12-04 01:29:35 +0100856
857 set_reentrant(0);
858 return ptr;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100859}
860
Victor Stinnere492ae52016-03-22 12:58:23 +0100861
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100862static void*
Victor Stinnerdb067af2014-05-02 22:31:14 +0200863tracemalloc_raw_malloc(void *ctx, size_t size)
864{
865 return tracemalloc_raw_alloc(0, ctx, 1, size);
866}
867
Victor Stinnere492ae52016-03-22 12:58:23 +0100868
Victor Stinnerdb067af2014-05-02 22:31:14 +0200869static void*
870tracemalloc_raw_calloc(void *ctx, size_t nelem, size_t elsize)
871{
872 return tracemalloc_raw_alloc(1, ctx, nelem, elsize);
873}
874
Victor Stinnere492ae52016-03-22 12:58:23 +0100875
Victor Stinnerdb067af2014-05-02 22:31:14 +0200876static void*
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100877tracemalloc_raw_realloc(void *ctx, void *ptr, size_t new_size)
878{
Victor Stinner15116802013-12-04 01:29:35 +0100879 PyGILState_STATE gil_state;
Victor Stinner15116802013-12-04 01:29:35 +0100880 void *ptr2;
881
882 if (get_reentrant()) {
883 /* Reentrant call to PyMem_RawRealloc(). */
Victor Stinnerd8f0d922014-06-02 21:57:10 +0200884 PyMemAllocatorEx *alloc = (PyMemAllocatorEx *)ctx;
Victor Stinner15116802013-12-04 01:29:35 +0100885
886 ptr2 = alloc->realloc(alloc->ctx, ptr, new_size);
Victor Stinner15116802013-12-04 01:29:35 +0100887
Victor Stinner88c29872013-12-04 01:47:46 +0100888 if (ptr2 != NULL && ptr != NULL) {
889 TABLES_LOCK();
Victor Stinnere492ae52016-03-22 12:58:23 +0100890 REMOVE_TRACE(ptr);
Victor Stinner88c29872013-12-04 01:47:46 +0100891 TABLES_UNLOCK();
892 }
Victor Stinner15116802013-12-04 01:29:35 +0100893 return ptr2;
894 }
895
896 /* Ignore reentrant call. PyGILState_Ensure() may call PyMem_RawMalloc()
897 indirectly which would call PyGILState_Ensure() if reentrant calls are
898 not disabled. */
899 set_reentrant(1);
900
Victor Stinner15116802013-12-04 01:29:35 +0100901 gil_state = PyGILState_Ensure();
902 ptr2 = tracemalloc_realloc(ctx, ptr, new_size);
903 PyGILState_Release(gil_state);
Victor Stinner15116802013-12-04 01:29:35 +0100904
905 set_reentrant(0);
906 return ptr2;
907}
908#endif /* TRACE_RAW_MALLOC */
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100909
Victor Stinnere492ae52016-03-22 12:58:23 +0100910
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100911static int
Victor Stinner285cf0a2016-03-21 22:00:58 +0100912tracemalloc_clear_filename(_Py_hashtable_t *ht, _Py_hashtable_entry_t *entry,
913 void *user_data)
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100914{
Victor Stinner285cf0a2016-03-21 22:00:58 +0100915 PyObject *filename;
916
Victor Stinner5dacbd42016-03-23 09:52:13 +0100917 _Py_HASHTABLE_ENTRY_READ_KEY(ht, entry, filename);
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100918 Py_DECREF(filename);
919 return 0;
920}
921
Victor Stinnere492ae52016-03-22 12:58:23 +0100922
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100923static int
Victor Stinner285cf0a2016-03-21 22:00:58 +0100924traceback_free_traceback(_Py_hashtable_t *ht, _Py_hashtable_entry_t *entry,
925 void *user_data)
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100926{
Victor Stinner285cf0a2016-03-21 22:00:58 +0100927 traceback_t *traceback;
928
Victor Stinner5dacbd42016-03-23 09:52:13 +0100929 _Py_HASHTABLE_ENTRY_READ_KEY(ht, entry, traceback);
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100930 raw_free(traceback);
931 return 0;
932}
933
Victor Stinnere492ae52016-03-22 12:58:23 +0100934
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100935/* reentrant flag must be set to call this function and GIL must be held */
936static void
937tracemalloc_clear_traces(void)
938{
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100939 /* The GIL protects variables againt concurrent access */
940 assert(PyGILState_Check());
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100941
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100942 TABLES_LOCK();
943 _Py_hashtable_clear(tracemalloc_traces);
944 tracemalloc_traced_memory = 0;
Victor Stinner3c0481d2013-11-27 21:39:49 +0100945 tracemalloc_peak_traced_memory = 0;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100946 TABLES_UNLOCK();
947
948 _Py_hashtable_foreach(tracemalloc_tracebacks, traceback_free_traceback, NULL);
949 _Py_hashtable_clear(tracemalloc_tracebacks);
950
951 _Py_hashtable_foreach(tracemalloc_filenames, tracemalloc_clear_filename, NULL);
952 _Py_hashtable_clear(tracemalloc_filenames);
953}
954
Victor Stinnere492ae52016-03-22 12:58:23 +0100955
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100956static int
957tracemalloc_init(void)
958{
959 if (tracemalloc_config.initialized == TRACEMALLOC_FINALIZED) {
960 PyErr_SetString(PyExc_RuntimeError,
961 "the tracemalloc module has been unloaded");
962 return -1;
963 }
964
Victor Stinnerf9a71152016-03-22 23:54:42 +0100965 if (tracemalloc_config.initialized == TRACEMALLOC_INITIALIZED)
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100966 return 0;
967
968 PyMem_GetAllocator(PYMEM_DOMAIN_RAW, &allocators.raw);
969
970#ifdef REENTRANT_THREADLOCAL
Masayuki Yamamoto731e1892017-10-06 19:41:34 +0900971 if (PyThread_tss_create(&tracemalloc_reentrant_key) != 0) {
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100972#ifdef MS_WINDOWS
973 PyErr_SetFromWindowsErr(0);
974#else
975 PyErr_SetFromErrno(PyExc_OSError);
976#endif
977 return -1;
978 }
979#endif
980
Antoine Pitroua6a4dc82017-09-07 18:56:24 +0200981#if defined(TRACE_RAW_MALLOC)
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100982 if (tables_lock == NULL) {
983 tables_lock = PyThread_allocate_lock();
984 if (tables_lock == NULL) {
985 PyErr_SetString(PyExc_RuntimeError, "cannot allocate lock");
986 return -1;
987 }
988 }
989#endif
990
Victor Stinner285cf0a2016-03-21 22:00:58 +0100991 tracemalloc_filenames = hashtable_new(sizeof(PyObject *), 0,
992 hashtable_hash_pyobject,
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100993 hashtable_compare_unicode);
994
Victor Stinner285cf0a2016-03-21 22:00:58 +0100995 tracemalloc_tracebacks = hashtable_new(sizeof(traceback_t *), 0,
996 hashtable_hash_traceback,
997 hashtable_compare_traceback);
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100998
Victor Stinnere492ae52016-03-22 12:58:23 +0100999 if (tracemalloc_config.use_domain) {
1000 tracemalloc_traces = hashtable_new(sizeof(pointer_t),
1001 sizeof(trace_t),
1002 hashtable_hash_pointer_t,
1003 hashtable_compare_pointer_t);
1004 }
1005 else {
Benjamin Petersonca470632016-09-06 13:47:26 -07001006 tracemalloc_traces = hashtable_new(sizeof(uintptr_t),
Victor Stinnere492ae52016-03-22 12:58:23 +01001007 sizeof(trace_t),
1008 _Py_hashtable_hash_ptr,
1009 _Py_hashtable_compare_direct);
1010 }
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001011
1012 if (tracemalloc_filenames == NULL || tracemalloc_tracebacks == NULL
Victor Stinner285cf0a2016-03-21 22:00:58 +01001013 || tracemalloc_traces == NULL) {
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001014 PyErr_NoMemory();
1015 return -1;
1016 }
1017
1018 unknown_filename = PyUnicode_FromString("<unknown>");
1019 if (unknown_filename == NULL)
1020 return -1;
1021 PyUnicode_InternInPlace(&unknown_filename);
1022
1023 tracemalloc_empty_traceback.nframe = 1;
1024 /* borrowed reference */
1025 tracemalloc_empty_traceback.frames[0].filename = unknown_filename;
1026 tracemalloc_empty_traceback.frames[0].lineno = 0;
1027 tracemalloc_empty_traceback.hash = traceback_hash(&tracemalloc_empty_traceback);
1028
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001029 tracemalloc_config.initialized = TRACEMALLOC_INITIALIZED;
1030 return 0;
1031}
1032
Victor Stinnere492ae52016-03-22 12:58:23 +01001033
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001034static void
1035tracemalloc_deinit(void)
1036{
Victor Stinnerf9a71152016-03-22 23:54:42 +01001037 if (tracemalloc_config.initialized != TRACEMALLOC_INITIALIZED)
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001038 return;
1039 tracemalloc_config.initialized = TRACEMALLOC_FINALIZED;
1040
1041 tracemalloc_stop();
1042
1043 /* destroy hash tables */
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001044 _Py_hashtable_destroy(tracemalloc_tracebacks);
1045 _Py_hashtable_destroy(tracemalloc_filenames);
Victor Stinner285cf0a2016-03-21 22:00:58 +01001046 _Py_hashtable_destroy(tracemalloc_traces);
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001047
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02001048#if defined(TRACE_RAW_MALLOC)
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001049 if (tables_lock != NULL) {
1050 PyThread_free_lock(tables_lock);
1051 tables_lock = NULL;
1052 }
1053#endif
1054
1055#ifdef REENTRANT_THREADLOCAL
Masayuki Yamamoto731e1892017-10-06 19:41:34 +09001056 PyThread_tss_delete(&tracemalloc_reentrant_key);
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001057#endif
1058
1059 Py_XDECREF(unknown_filename);
1060}
1061
Victor Stinnere492ae52016-03-22 12:58:23 +01001062
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001063static int
Victor Stinnerf28ce602013-11-27 22:27:13 +01001064tracemalloc_start(int max_nframe)
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001065{
Victor Stinnerd8f0d922014-06-02 21:57:10 +02001066 PyMemAllocatorEx alloc;
Victor Stinnerf28ce602013-11-27 22:27:13 +01001067 size_t size;
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001068
Victor Stinnerf9a71152016-03-22 23:54:42 +01001069 if (tracemalloc_init() < 0)
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001070 return -1;
1071
1072 if (tracemalloc_config.tracing) {
1073 /* hook already installed: do nothing */
1074 return 0;
1075 }
1076
Victor Stinner52aee852014-08-16 15:44:02 +02001077 assert(1 <= max_nframe && max_nframe <= MAX_NFRAME);
Victor Stinnerf28ce602013-11-27 22:27:13 +01001078 tracemalloc_config.max_nframe = max_nframe;
1079
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 */
1114 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 Stinnerf9a71152016-03-22 23:54:42 +01001123 if (!tracemalloc_config.tracing)
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001124 return;
1125
1126 /* stop tracing Python memory allocations */
1127 tracemalloc_config.tracing = 0;
1128
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{
1155 return PyBool_FromLong(tracemalloc_config.tracing);
1156}
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{
1169 if (!tracemalloc_config.tracing)
1170 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
Victor Stinnere492ae52016-03-22 12:58:23 +01001249 trace_obj = PyTuple_New(3);
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
1274 return trace_obj;
1275}
1276
Victor Stinnere492ae52016-03-22 12:58:23 +01001277
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001278typedef struct {
1279 _Py_hashtable_t *traces;
1280 _Py_hashtable_t *tracebacks;
1281 PyObject *list;
1282} get_traces_t;
1283
1284static int
Victor Stinner285cf0a2016-03-21 22:00:58 +01001285tracemalloc_get_traces_fill(_Py_hashtable_t *traces, _Py_hashtable_entry_t *entry,
1286 void *user_data)
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001287{
1288 get_traces_t *get_traces = user_data;
Victor Stinner5ea4c062017-06-20 17:46:36 +02001289 unsigned int domain;
Victor Stinner5dacbd42016-03-23 09:52:13 +01001290 trace_t trace;
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001291 PyObject *tracemalloc_obj;
1292 int res;
1293
Victor Stinnere492ae52016-03-22 12:58:23 +01001294 if (tracemalloc_config.use_domain) {
1295 pointer_t key;
Victor Stinner5dacbd42016-03-23 09:52:13 +01001296 _Py_HASHTABLE_ENTRY_READ_KEY(traces, entry, key);
Victor Stinnere492ae52016-03-22 12:58:23 +01001297 domain = key.domain;
1298 }
1299 else {
1300 domain = DEFAULT_DOMAIN;
1301 }
Victor Stinner5dacbd42016-03-23 09:52:13 +01001302 _Py_HASHTABLE_ENTRY_READ_DATA(traces, entry, trace);
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001303
Victor Stinner5dacbd42016-03-23 09:52:13 +01001304 tracemalloc_obj = trace_to_pyobject(domain, &trace, get_traces->tracebacks);
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001305 if (tracemalloc_obj == NULL)
1306 return 1;
1307
1308 res = PyList_Append(get_traces->list, tracemalloc_obj);
1309 Py_DECREF(tracemalloc_obj);
1310 if (res < 0)
1311 return 1;
1312
1313 return 0;
1314}
1315
Victor Stinnere492ae52016-03-22 12:58:23 +01001316
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001317static int
Victor Stinner285cf0a2016-03-21 22:00:58 +01001318tracemalloc_pyobject_decref_cb(_Py_hashtable_t *tracebacks,
1319 _Py_hashtable_entry_t *entry,
1320 void *user_data)
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001321{
Victor Stinnerc9553872016-03-22 12:13:01 +01001322 PyObject *obj;
Victor Stinnere8c6b2f2016-03-23 09:25:01 +01001323 _Py_HASHTABLE_ENTRY_READ_DATA(tracebacks, entry, obj);
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001324 Py_DECREF(obj);
1325 return 0;
1326}
1327
Victor Stinnere492ae52016-03-22 12:58:23 +01001328
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001329
Serhiy Storchakab451f912017-02-04 12:18:38 +02001330/*[clinic input]
1331_tracemalloc._get_traces
1332
1333Get traces of all memory blocks allocated by Python.
1334
1335Return a list of (size: int, traceback: tuple) tuples.
1336traceback is a tuple of (filename: str, lineno: int) tuples.
1337
1338Return an empty list if the tracemalloc module is disabled.
1339[clinic start generated code]*/
1340
1341static PyObject *
1342_tracemalloc__get_traces_impl(PyObject *module)
1343/*[clinic end generated code: output=e9929876ced4b5cc input=6c7d2230b24255aa]*/
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001344{
1345 get_traces_t get_traces;
1346 int err;
1347
1348 get_traces.traces = NULL;
1349 get_traces.tracebacks = NULL;
1350 get_traces.list = PyList_New(0);
1351 if (get_traces.list == NULL)
1352 goto error;
1353
1354 if (!tracemalloc_config.tracing)
1355 return get_traces.list;
1356
Victor Stinnerde2f1322013-11-26 00:26:23 +01001357 /* the traceback hash table is used temporarily to intern traceback tuple
1358 of (filename, lineno) tuples */
Victor Stinnerc9553872016-03-22 12:13:01 +01001359 get_traces.tracebacks = hashtable_new(sizeof(traceback_t *),
1360 sizeof(PyObject *),
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001361 _Py_hashtable_hash_ptr,
1362 _Py_hashtable_compare_direct);
1363 if (get_traces.tracebacks == NULL) {
1364 PyErr_NoMemory();
1365 goto error;
1366 }
1367
1368 TABLES_LOCK();
1369 get_traces.traces = _Py_hashtable_copy(tracemalloc_traces);
1370 TABLES_UNLOCK();
1371
1372 if (get_traces.traces == NULL) {
1373 PyErr_NoMemory();
1374 goto error;
1375 }
1376
1377 set_reentrant(1);
1378 err = _Py_hashtable_foreach(get_traces.traces,
1379 tracemalloc_get_traces_fill, &get_traces);
1380 set_reentrant(0);
1381 if (err)
1382 goto error;
1383
1384 goto finally;
1385
1386error:
1387 Py_CLEAR(get_traces.list);
1388
1389finally:
1390 if (get_traces.tracebacks != NULL) {
1391 _Py_hashtable_foreach(get_traces.tracebacks,
Victor Stinner285cf0a2016-03-21 22:00:58 +01001392 tracemalloc_pyobject_decref_cb, NULL);
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001393 _Py_hashtable_destroy(get_traces.tracebacks);
1394 }
Victor Stinnerc9553872016-03-22 12:13:01 +01001395 if (get_traces.traces != NULL) {
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001396 _Py_hashtable_destroy(get_traces.traces);
Victor Stinnerc9553872016-03-22 12:13:01 +01001397 }
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001398
1399 return get_traces.list;
1400}
1401
Victor Stinnere492ae52016-03-22 12:58:23 +01001402
Victor Stinner0611c262016-03-15 22:22:13 +01001403static traceback_t*
Victor Stinner5ea4c062017-06-20 17:46:36 +02001404tracemalloc_get_traceback(unsigned int domain, uintptr_t ptr)
Victor Stinner0611c262016-03-15 22:22:13 +01001405{
1406 trace_t trace;
1407 int found;
1408
1409 if (!tracemalloc_config.tracing)
1410 return NULL;
1411
1412 TABLES_LOCK();
Victor Stinnere492ae52016-03-22 12:58:23 +01001413 if (tracemalloc_config.use_domain) {
Victor Stinner10b73e12016-03-22 13:39:05 +01001414 pointer_t key = {ptr, domain};
Victor Stinnere492ae52016-03-22 12:58:23 +01001415 found = _Py_HASHTABLE_GET(tracemalloc_traces, key, trace);
1416 }
1417 else {
1418 found = _Py_HASHTABLE_GET(tracemalloc_traces, ptr, trace);
1419 }
Victor Stinner0611c262016-03-15 22:22:13 +01001420 TABLES_UNLOCK();
1421
1422 if (!found)
1423 return NULL;
1424
1425 return trace.traceback;
1426}
1427
Victor Stinnere492ae52016-03-22 12:58:23 +01001428
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001429
Serhiy Storchakab451f912017-02-04 12:18:38 +02001430/*[clinic input]
1431_tracemalloc._get_object_traceback
1432
1433 obj: object
1434 /
1435
1436Get the traceback where the Python object obj was allocated.
1437
1438Return a tuple of (filename: str, lineno: int) tuples.
1439Return None if the tracemalloc module is disabled or did not
1440trace the allocation of the object.
1441[clinic start generated code]*/
1442
1443static PyObject *
1444_tracemalloc__get_object_traceback(PyObject *module, PyObject *obj)
1445/*[clinic end generated code: output=41ee0553a658b0aa input=29495f1b21c53212]*/
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001446{
1447 PyTypeObject *type;
1448 void *ptr;
Victor Stinner0611c262016-03-15 22:22:13 +01001449 traceback_t *traceback;
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001450
1451 type = Py_TYPE(obj);
1452 if (PyType_IS_GC(type))
1453 ptr = (void *)((char *)obj - sizeof(PyGC_Head));
1454 else
1455 ptr = (void *)obj;
1456
Benjamin Petersonca470632016-09-06 13:47:26 -07001457 traceback = tracemalloc_get_traceback(DEFAULT_DOMAIN, (uintptr_t)ptr);
Victor Stinner0611c262016-03-15 22:22:13 +01001458 if (traceback == NULL)
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001459 Py_RETURN_NONE;
1460
Victor Stinner0611c262016-03-15 22:22:13 +01001461 return traceback_to_pyobject(traceback, NULL);
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001462}
1463
Victor Stinnere492ae52016-03-22 12:58:23 +01001464
Victor Stinner0611c262016-03-15 22:22:13 +01001465#define PUTS(fd, str) _Py_write_noraise(fd, str, (int)strlen(str))
1466
1467static void
1468_PyMem_DumpFrame(int fd, frame_t * frame)
1469{
1470 PUTS(fd, " File \"");
1471 _Py_DumpASCII(fd, frame->filename);
1472 PUTS(fd, "\", line ");
1473 _Py_DumpDecimal(fd, frame->lineno);
1474 PUTS(fd, "\n");
1475}
1476
1477/* Dump the traceback where a memory block was allocated into file descriptor
1478 fd. The function may block on TABLES_LOCK() but it is unlikely. */
1479void
1480_PyMem_DumpTraceback(int fd, const void *ptr)
1481{
1482 traceback_t *traceback;
1483 int i;
1484
Benjamin Petersonca470632016-09-06 13:47:26 -07001485 traceback = tracemalloc_get_traceback(DEFAULT_DOMAIN, (uintptr_t)ptr);
Victor Stinner0611c262016-03-15 22:22:13 +01001486 if (traceback == NULL)
1487 return;
1488
1489 PUTS(fd, "Memory block allocated at (most recent call first):\n");
1490 for (i=0; i < traceback->nframe; i++) {
1491 _PyMem_DumpFrame(fd, &traceback->frames[i]);
1492 }
1493 PUTS(fd, "\n");
1494}
1495
1496#undef PUTS
1497
Victor Stinnere492ae52016-03-22 12:58:23 +01001498
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001499
Serhiy Storchakab451f912017-02-04 12:18:38 +02001500/*[clinic input]
1501_tracemalloc.start
1502
1503 nframe: Py_ssize_t = 1
1504 /
1505
1506Start tracing Python memory allocations.
1507
1508Also set the maximum number of frames stored in the traceback of a
1509trace to nframe.
1510[clinic start generated code]*/
1511
1512static PyObject *
1513_tracemalloc_start_impl(PyObject *module, Py_ssize_t nframe)
1514/*[clinic end generated code: output=0f558d2079511553 input=997841629cc441cb]*/
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001515{
Victor Stinnerf28ce602013-11-27 22:27:13 +01001516 int nframe_int;
Victor Stinner3728d6c2013-11-23 12:37:20 +01001517
Victor Stinner52aee852014-08-16 15:44:02 +02001518 if (nframe < 1 || nframe > MAX_NFRAME) {
Victor Stinner3728d6c2013-11-23 12:37:20 +01001519 PyErr_Format(PyExc_ValueError,
1520 "the number of frames must be in range [1; %i]",
Serhiy Storchakab451f912017-02-04 12:18:38 +02001521 (int)MAX_NFRAME);
Victor Stinner3728d6c2013-11-23 12:37:20 +01001522 return NULL;
1523 }
Victor Stinnerf28ce602013-11-27 22:27:13 +01001524 nframe_int = Py_SAFE_DOWNCAST(nframe, Py_ssize_t, int);
Victor Stinner3728d6c2013-11-23 12:37:20 +01001525
Victor Stinnerf9a71152016-03-22 23:54:42 +01001526 if (tracemalloc_start(nframe_int) < 0)
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001527 return NULL;
1528
1529 Py_RETURN_NONE;
1530}
1531
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001532
Serhiy Storchakab451f912017-02-04 12:18:38 +02001533/*[clinic input]
1534_tracemalloc.stop
Victor Stinnere492ae52016-03-22 12:58:23 +01001535
Serhiy Storchakab451f912017-02-04 12:18:38 +02001536Stop tracing Python memory allocations.
1537
1538Also clear traces of memory blocks allocated by Python.
1539[clinic start generated code]*/
1540
1541static PyObject *
1542_tracemalloc_stop_impl(PyObject *module)
1543/*[clinic end generated code: output=c3c42ae03e3955cd input=7478f075e51dae18]*/
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001544{
1545 tracemalloc_stop();
1546 Py_RETURN_NONE;
1547}
1548
Victor Stinnere492ae52016-03-22 12:58:23 +01001549
Serhiy Storchakab451f912017-02-04 12:18:38 +02001550/*[clinic input]
1551_tracemalloc.get_traceback_limit
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001552
Serhiy Storchakab451f912017-02-04 12:18:38 +02001553Get the maximum number of frames stored in the traceback of a trace.
1554
1555By default, a trace of an allocated memory block only stores
1556the most recent frame: the limit is 1.
1557[clinic start generated code]*/
1558
1559static PyObject *
1560_tracemalloc_get_traceback_limit_impl(PyObject *module)
1561/*[clinic end generated code: output=d556d9306ba95567 input=da3cd977fc68ae3b]*/
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001562{
1563 return PyLong_FromLong(tracemalloc_config.max_nframe);
1564}
1565
Victor Stinnere492ae52016-03-22 12:58:23 +01001566
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001567
Serhiy Storchakab451f912017-02-04 12:18:38 +02001568/*[clinic input]
1569_tracemalloc.get_tracemalloc_memory
1570
1571Get the memory usage in bytes of the tracemalloc module.
1572
1573This memory is used internally to trace memory allocations.
1574[clinic start generated code]*/
1575
1576static PyObject *
1577_tracemalloc_get_tracemalloc_memory_impl(PyObject *module)
1578/*[clinic end generated code: output=e3f14e280a55f5aa input=5d919c0f4d5132ad]*/
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001579{
1580 size_t size;
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001581
1582 size = _Py_hashtable_size(tracemalloc_tracebacks);
1583 size += _Py_hashtable_size(tracemalloc_filenames);
1584
1585 TABLES_LOCK();
1586 size += _Py_hashtable_size(tracemalloc_traces);
1587 TABLES_UNLOCK();
1588
Serhiy Storchakab451f912017-02-04 12:18:38 +02001589 return PyLong_FromSize_t(size);
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001590}
1591
Victor Stinnere492ae52016-03-22 12:58:23 +01001592
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001593
Serhiy Storchakab451f912017-02-04 12:18:38 +02001594/*[clinic input]
1595_tracemalloc.get_traced_memory
1596
1597Get the current size and peak size of memory blocks traced by tracemalloc.
1598
1599Returns a tuple: (current: int, peak: int).
1600[clinic start generated code]*/
1601
1602static PyObject *
1603_tracemalloc_get_traced_memory_impl(PyObject *module)
1604/*[clinic end generated code: output=5b167189adb9e782 input=61ddb5478400ff66]*/
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001605{
Victor Stinner3c0481d2013-11-27 21:39:49 +01001606 Py_ssize_t size, peak_size;
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001607
1608 if (!tracemalloc_config.tracing)
1609 return Py_BuildValue("ii", 0, 0);
1610
1611 TABLES_LOCK();
1612 size = tracemalloc_traced_memory;
Victor Stinner3c0481d2013-11-27 21:39:49 +01001613 peak_size = tracemalloc_peak_traced_memory;
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001614 TABLES_UNLOCK();
1615
Serhiy Storchakab451f912017-02-04 12:18:38 +02001616 return Py_BuildValue("nn", size, peak_size);
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001617}
1618
Victor Stinnere492ae52016-03-22 12:58:23 +01001619
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001620static PyMethodDef module_methods[] = {
Serhiy Storchakab451f912017-02-04 12:18:38 +02001621 _TRACEMALLOC_IS_TRACING_METHODDEF
1622 _TRACEMALLOC_CLEAR_TRACES_METHODDEF
1623 _TRACEMALLOC__GET_TRACES_METHODDEF
1624 _TRACEMALLOC__GET_OBJECT_TRACEBACK_METHODDEF
1625 _TRACEMALLOC_START_METHODDEF
1626 _TRACEMALLOC_STOP_METHODDEF
1627 _TRACEMALLOC_GET_TRACEBACK_LIMIT_METHODDEF
1628 _TRACEMALLOC_GET_TRACEMALLOC_MEMORY_METHODDEF
1629 _TRACEMALLOC_GET_TRACED_MEMORY_METHODDEF
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001630 /* sentinel */
1631 {NULL, NULL}
1632};
1633
1634PyDoc_STRVAR(module_doc,
1635"Debug module to trace memory blocks allocated by Python.");
1636
1637static struct PyModuleDef module_def = {
1638 PyModuleDef_HEAD_INIT,
1639 "_tracemalloc",
1640 module_doc,
1641 0, /* non-negative size to be able to unload the module */
1642 module_methods,
1643 NULL,
1644};
1645
1646PyMODINIT_FUNC
1647PyInit__tracemalloc(void)
1648{
1649 PyObject *m;
1650 m = PyModule_Create(&module_def);
1651 if (m == NULL)
1652 return NULL;
1653
1654 if (tracemalloc_init() < 0)
1655 return NULL;
1656
1657 return m;
1658}
1659
Victor Stinnere492ae52016-03-22 12:58:23 +01001660
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001661static int
1662parse_sys_xoptions(PyObject *value)
1663{
1664 PyObject *valuelong;
1665 long nframe;
1666
1667 if (value == Py_True)
1668 return 1;
1669
1670 assert(PyUnicode_Check(value));
1671 if (PyUnicode_GetLength(value) == 0)
1672 return -1;
1673
1674 valuelong = PyLong_FromUnicodeObject(value, 10);
1675 if (valuelong == NULL)
1676 return -1;
1677
1678 nframe = PyLong_AsLong(valuelong);
1679 Py_DECREF(valuelong);
1680 if (nframe == -1 && PyErr_Occurred())
1681 return -1;
1682
Victor Stinner52aee852014-08-16 15:44:02 +02001683 if (nframe < 1 || nframe > MAX_NFRAME)
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001684 return -1;
1685
1686 return Py_SAFE_DOWNCAST(nframe, long, int);
1687}
1688
Victor Stinnere492ae52016-03-22 12:58:23 +01001689
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001690int
1691_PyTraceMalloc_Init(void)
1692{
1693 char *p;
1694 int nframe;
1695
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001696 assert(PyGILState_Check());
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001697
1698 if ((p = Py_GETENV("PYTHONTRACEMALLOC")) && *p != '\0') {
1699 char *endptr = p;
Victor Stinnerf28ce602013-11-27 22:27:13 +01001700 long value;
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001701
Victor Stinner711e27c2013-12-16 23:06:19 +01001702 errno = 0;
Victor Stinnerf28ce602013-11-27 22:27:13 +01001703 value = strtol(p, &endptr, 10);
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001704 if (*endptr != '\0'
1705 || value < 1
Victor Stinner52aee852014-08-16 15:44:02 +02001706 || value > MAX_NFRAME
Victor Stinner711e27c2013-12-16 23:06:19 +01001707 || errno == ERANGE)
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001708 {
Victor Stinnerf28ce602013-11-27 22:27:13 +01001709 Py_FatalError("PYTHONTRACEMALLOC: invalid number of frames");
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001710 return -1;
1711 }
1712
1713 nframe = (int)value;
1714 }
1715 else {
1716 PyObject *xoptions, *key, *value;
1717
1718 xoptions = PySys_GetXOptions();
1719 if (xoptions == NULL)
1720 return -1;
1721
1722 key = PyUnicode_FromString("tracemalloc");
1723 if (key == NULL)
1724 return -1;
1725
Xiang Zhang4ed5ad72017-07-19 00:33:29 +08001726 value = PyDict_GetItemWithError(xoptions, key); /* borrowed */
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001727 Py_DECREF(key);
1728 if (value == NULL) {
1729 if (PyErr_Occurred())
1730 return -1;
1731
1732 /* -X tracemalloc is not used */
1733 return 0;
1734 }
1735
1736 nframe = parse_sys_xoptions(value);
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001737 if (nframe < 0) {
Victor Stinnerf28ce602013-11-27 22:27:13 +01001738 Py_FatalError("-X tracemalloc=NFRAME: invalid number of frames");
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001739 }
1740 }
1741
Victor Stinnerf28ce602013-11-27 22:27:13 +01001742 return tracemalloc_start(nframe);
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001743}
1744
Victor Stinnere492ae52016-03-22 12:58:23 +01001745
Victor Stinnerbe0708f2013-12-01 10:03:26 +01001746void
1747_PyTraceMalloc_Fini(void)
1748{
Victor Stinnerbe0708f2013-12-01 10:03:26 +01001749 assert(PyGILState_Check());
Victor Stinnerbe0708f2013-12-01 10:03:26 +01001750 tracemalloc_deinit();
1751}
Victor Stinner10b73e12016-03-22 13:39:05 +01001752
1753int
Victor Stinner5ea4c062017-06-20 17:46:36 +02001754PyTraceMalloc_Track(unsigned int domain, uintptr_t ptr,
1755 size_t size)
Victor Stinner10b73e12016-03-22 13:39:05 +01001756{
1757 int res;
Victor Stinner10b73e12016-03-22 13:39:05 +01001758 PyGILState_STATE gil_state;
Victor Stinner10b73e12016-03-22 13:39:05 +01001759
1760 if (!tracemalloc_config.tracing) {
1761 /* tracemalloc is not tracing: do nothing */
1762 return -2;
1763 }
1764
Victor Stinner10b73e12016-03-22 13:39:05 +01001765 gil_state = PyGILState_Ensure();
Victor Stinner10b73e12016-03-22 13:39:05 +01001766
1767 TABLES_LOCK();
1768 res = tracemalloc_add_trace(domain, ptr, size);
1769 TABLES_UNLOCK();
1770
Victor Stinner10b73e12016-03-22 13:39:05 +01001771 PyGILState_Release(gil_state);
Victor Stinner10b73e12016-03-22 13:39:05 +01001772 return res;
1773}
1774
1775
1776int
Victor Stinner5ea4c062017-06-20 17:46:36 +02001777PyTraceMalloc_Untrack(unsigned int domain, uintptr_t ptr)
Victor Stinner10b73e12016-03-22 13:39:05 +01001778{
1779 if (!tracemalloc_config.tracing) {
1780 /* tracemalloc is not tracing: do nothing */
1781 return -2;
1782 }
1783
1784 TABLES_LOCK();
1785 tracemalloc_remove_trace(domain, ptr);
1786 TABLES_UNLOCK();
1787
1788 return 0;
1789}
1790
1791
1792PyObject*
Victor Stinner5ea4c062017-06-20 17:46:36 +02001793_PyTraceMalloc_GetTraceback(unsigned int domain, uintptr_t ptr)
Victor Stinner10b73e12016-03-22 13:39:05 +01001794{
1795 traceback_t *traceback;
1796
1797 traceback = tracemalloc_get_traceback(domain, ptr);
1798 if (traceback == NULL)
1799 Py_RETURN_NONE;
1800
1801 return traceback_to_pyobject(traceback, NULL);
1802}