blob: 386f2f11ba7f332c981ca8f2786c923400f3253a [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
170/* If your OS does not provide native thread local storage, you can implement
171 it manually using a lock. Functions of thread.c cannot be used because
172 they use PyMem_RawMalloc() which leads to a reentrant call. */
173#if !(defined(_POSIX_THREADS) || defined(NT_THREADS))
174# error "need native thread local storage (TLS)"
175#endif
176
Victor Stinner4a066472016-03-22 17:45:09 +0100177static int tracemalloc_reentrant_key = -1;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100178
179/* Any non-NULL pointer can be used */
180#define REENTRANT Py_True
181
182static int
183get_reentrant(void)
184{
Victor Stinner4a066472016-03-22 17:45:09 +0100185 void *ptr;
186
187 assert(tracemalloc_reentrant_key != -1);
188 ptr = PyThread_get_key_value(tracemalloc_reentrant_key);
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100189 if (ptr != NULL) {
190 assert(ptr == REENTRANT);
191 return 1;
192 }
193 else
194 return 0;
195}
196
197static void
198set_reentrant(int reentrant)
199{
Victor Stinner2ead3d22013-11-26 01:08:53 +0100200 assert(reentrant == 0 || reentrant == 1);
Victor Stinner4a066472016-03-22 17:45:09 +0100201 assert(tracemalloc_reentrant_key != -1);
202
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100203 if (reentrant) {
Victor Stinner0cfc0582016-03-22 17:40:07 +0100204 assert(!get_reentrant());
Victor Stinner590cebe2013-12-13 11:08:56 +0100205 PyThread_set_key_value(tracemalloc_reentrant_key, REENTRANT);
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100206 }
207 else {
Victor Stinner0cfc0582016-03-22 17:40:07 +0100208 assert(get_reentrant());
Victor Stinner590cebe2013-12-13 11:08:56 +0100209 PyThread_set_key_value(tracemalloc_reentrant_key, NULL);
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100210 }
211}
212
213#else
214
Antoine Pitroua6a4dc82017-09-07 18:56:24 +0200215/* TRACE_RAW_MALLOC not defined: variable protected by the GIL */
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100216static int tracemalloc_reentrant = 0;
217
218static int
219get_reentrant(void)
220{
221 return tracemalloc_reentrant;
222}
223
224static void
225set_reentrant(int reentrant)
226{
Victor Stinnerd5871e62016-03-23 00:17:04 +0100227 assert(reentrant != tracemalloc_reentrant);
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100228 tracemalloc_reentrant = reentrant;
229}
230#endif
231
Victor Stinnere492ae52016-03-22 12:58:23 +0100232
Victor Stinner285cf0a2016-03-21 22:00:58 +0100233static Py_uhash_t
Victor Stinner5dacbd42016-03-23 09:52:13 +0100234hashtable_hash_pyobject(_Py_hashtable_t *ht, const void *pkey)
Victor Stinner51b846c2016-03-18 21:52:22 +0100235{
Victor Stinner285cf0a2016-03-21 22:00:58 +0100236 PyObject *obj;
237
Victor Stinner5dacbd42016-03-23 09:52:13 +0100238 _Py_HASHTABLE_READ_KEY(ht, pkey, obj);
Victor Stinner285cf0a2016-03-21 22:00:58 +0100239 return PyObject_Hash(obj);
240}
241
Victor Stinnere492ae52016-03-22 12:58:23 +0100242
Victor Stinner285cf0a2016-03-21 22:00:58 +0100243static int
Victor Stinner5dacbd42016-03-23 09:52:13 +0100244hashtable_compare_unicode(_Py_hashtable_t *ht, const void *pkey,
Victor Stinner285cf0a2016-03-21 22:00:58 +0100245 const _Py_hashtable_entry_t *entry)
246{
Victor Stinnere492ae52016-03-22 12:58:23 +0100247 PyObject *key1, *key2;
Victor Stinner285cf0a2016-03-21 22:00:58 +0100248
Victor Stinner5dacbd42016-03-23 09:52:13 +0100249 _Py_HASHTABLE_READ_KEY(ht, pkey, key1);
250 _Py_HASHTABLE_ENTRY_READ_KEY(ht, entry, key2);
Victor Stinner285cf0a2016-03-21 22:00:58 +0100251
Victor Stinnere492ae52016-03-22 12:58:23 +0100252 if (key1 != NULL && key2 != NULL)
253 return (PyUnicode_Compare(key1, key2) == 0);
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100254 else
Victor Stinnere492ae52016-03-22 12:58:23 +0100255 return key1 == key2;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100256}
257
Victor Stinnere492ae52016-03-22 12:58:23 +0100258
259static Py_uhash_t
Victor Stinner5dacbd42016-03-23 09:52:13 +0100260hashtable_hash_pointer_t(_Py_hashtable_t *ht, const void *pkey)
Victor Stinnere492ae52016-03-22 12:58:23 +0100261{
262 pointer_t ptr;
263 Py_uhash_t hash;
264
Victor Stinner5dacbd42016-03-23 09:52:13 +0100265 _Py_HASHTABLE_READ_KEY(ht, pkey, ptr);
Victor Stinnere492ae52016-03-22 12:58:23 +0100266
267 hash = (Py_uhash_t)_Py_HashPointer((void*)ptr.ptr);
268 hash ^= ptr.domain;
269 return hash;
270}
271
272
doko@ubuntu.combc731502016-05-18 01:06:01 +0200273static int
Victor Stinner5dacbd42016-03-23 09:52:13 +0100274hashtable_compare_pointer_t(_Py_hashtable_t *ht, const void *pkey,
Victor Stinnere492ae52016-03-22 12:58:23 +0100275 const _Py_hashtable_entry_t *entry)
276{
277 pointer_t ptr1, ptr2;
278
Victor Stinner5dacbd42016-03-23 09:52:13 +0100279 _Py_HASHTABLE_READ_KEY(ht, pkey, ptr1);
280 _Py_HASHTABLE_ENTRY_READ_KEY(ht, entry, ptr2);
Victor Stinnere492ae52016-03-22 12:58:23 +0100281
282 /* compare pointer before domain, because pointer is more likely to be
283 different */
284 return (ptr1.ptr == ptr2.ptr && ptr1.domain == ptr2.domain);
285
286}
287
288
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100289static _Py_hashtable_t *
Victor Stinner285cf0a2016-03-21 22:00:58 +0100290hashtable_new(size_t key_size, size_t data_size,
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100291 _Py_hashtable_hash_func hash_func,
292 _Py_hashtable_compare_func compare_func)
293{
Victor Stinnerc9553872016-03-22 12:13:01 +0100294 _Py_hashtable_allocator_t hashtable_alloc = {malloc, free};
Victor Stinner285cf0a2016-03-21 22:00:58 +0100295 return _Py_hashtable_new_full(key_size, data_size, 0,
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100296 hash_func, compare_func,
Victor Stinnerc9553872016-03-22 12:13:01 +0100297 &hashtable_alloc);
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100298}
299
Victor Stinnere492ae52016-03-22 12:58:23 +0100300
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100301static void*
302raw_malloc(size_t size)
303{
304 return allocators.raw.malloc(allocators.raw.ctx, size);
305}
306
307static void
308raw_free(void *ptr)
309{
310 allocators.raw.free(allocators.raw.ctx, ptr);
311}
312
Victor Stinnere492ae52016-03-22 12:58:23 +0100313
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100314static Py_uhash_t
Victor Stinner5dacbd42016-03-23 09:52:13 +0100315hashtable_hash_traceback(_Py_hashtable_t *ht, const void *pkey)
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100316{
Victor Stinnerb32a7ed2016-03-21 23:05:08 +0100317 traceback_t *traceback;
Victor Stinner285cf0a2016-03-21 22:00:58 +0100318
Victor Stinner5dacbd42016-03-23 09:52:13 +0100319 _Py_HASHTABLE_READ_KEY(ht, pkey, traceback);
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100320 return traceback->hash;
321}
322
Victor Stinnere492ae52016-03-22 12:58:23 +0100323
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100324static int
Victor Stinner5dacbd42016-03-23 09:52:13 +0100325hashtable_compare_traceback(_Py_hashtable_t *ht, const void *pkey,
326 const _Py_hashtable_entry_t *entry)
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100327{
Victor Stinner285cf0a2016-03-21 22:00:58 +0100328 traceback_t *traceback1, *traceback2;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100329 const frame_t *frame1, *frame2;
330 int i;
331
Victor Stinner5dacbd42016-03-23 09:52:13 +0100332 _Py_HASHTABLE_READ_KEY(ht, pkey, traceback1);
333 _Py_HASHTABLE_ENTRY_READ_KEY(ht, entry, traceback2);
Victor Stinner285cf0a2016-03-21 22:00:58 +0100334
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100335 if (traceback1->nframe != traceback2->nframe)
336 return 0;
337
338 for (i=0; i < traceback1->nframe; i++) {
339 frame1 = &traceback1->frames[i];
340 frame2 = &traceback2->frames[i];
341
342 if (frame1->lineno != frame2->lineno)
343 return 0;
344
345 if (frame1->filename != frame2->filename) {
346 assert(PyUnicode_Compare(frame1->filename, frame2->filename) != 0);
347 return 0;
348 }
349 }
350 return 1;
351}
352
Victor Stinnere492ae52016-03-22 12:58:23 +0100353
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100354static void
355tracemalloc_get_frame(PyFrameObject *pyframe, frame_t *frame)
356{
357 PyCodeObject *code;
358 PyObject *filename;
359 _Py_hashtable_entry_t *entry;
Victor Stinner95283342016-03-15 21:57:02 +0100360 int lineno;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100361
362 frame->filename = unknown_filename;
Victor Stinner95283342016-03-15 21:57:02 +0100363 lineno = PyFrame_GetLineNumber(pyframe);
364 if (lineno < 0)
365 lineno = 0;
366 frame->lineno = (unsigned int)lineno;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100367
368 code = pyframe->f_code;
369 if (code == NULL) {
370#ifdef TRACE_DEBUG
Victor Stinner4dc74202013-11-26 01:18:52 +0100371 tracemalloc_error("failed to get the code object of the frame");
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100372#endif
373 return;
374 }
375
376 if (code->co_filename == NULL) {
377#ifdef TRACE_DEBUG
378 tracemalloc_error("failed to get the filename of the code object");
379#endif
380 return;
381 }
382
383 filename = code->co_filename;
384 assert(filename != NULL);
385 if (filename == NULL)
386 return;
387
388 if (!PyUnicode_Check(filename)) {
389#ifdef TRACE_DEBUG
Martin Panter6245cb32016-04-15 02:14:19 +0000390 tracemalloc_error("filename is not a unicode string");
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100391#endif
392 return;
393 }
394 if (!PyUnicode_IS_READY(filename)) {
395 /* Don't make a Unicode string ready to avoid reentrant calls
396 to tracemalloc_malloc() or tracemalloc_realloc() */
397#ifdef TRACE_DEBUG
398 tracemalloc_error("filename is not a ready unicode string");
399#endif
400 return;
401 }
402
403 /* intern the filename */
Victor Stinner285cf0a2016-03-21 22:00:58 +0100404 entry = _Py_HASHTABLE_GET_ENTRY(tracemalloc_filenames, filename);
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100405 if (entry != NULL) {
Victor Stinner5dacbd42016-03-23 09:52:13 +0100406 _Py_HASHTABLE_ENTRY_READ_KEY(tracemalloc_filenames, entry, filename);
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100407 }
408 else {
409 /* tracemalloc_filenames is responsible to keep a reference
410 to the filename */
411 Py_INCREF(filename);
Victor Stinner285cf0a2016-03-21 22:00:58 +0100412 if (_Py_HASHTABLE_SET_NODATA(tracemalloc_filenames, filename) < 0) {
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100413 Py_DECREF(filename);
414#ifdef TRACE_DEBUG
415 tracemalloc_error("failed to intern the filename");
416#endif
417 return;
418 }
419 }
420
421 /* the tracemalloc_filenames table keeps a reference to the filename */
422 frame->filename = filename;
423}
424
Victor Stinnere492ae52016-03-22 12:58:23 +0100425
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100426static Py_uhash_t
427traceback_hash(traceback_t *traceback)
428{
429 /* code based on tuplehash() of Objects/tupleobject.c */
Victor Stinner4d8c29c2013-12-16 23:05:13 +0100430 Py_uhash_t x, y; /* Unsigned for defined overflow behavior. */
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100431 int len = traceback->nframe;
432 Py_uhash_t mult = _PyHASH_MULTIPLIER;
433 frame_t *frame;
434
435 x = 0x345678UL;
436 frame = traceback->frames;
437 while (--len >= 0) {
Victor Stinner4d8c29c2013-12-16 23:05:13 +0100438 y = (Py_uhash_t)PyObject_Hash(frame->filename);
439 y ^= (Py_uhash_t)frame->lineno;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100440 frame++;
441
442 x = (x ^ y) * mult;
443 /* the cast might truncate len; that doesn't change hash stability */
Victor Stinner4d8c29c2013-12-16 23:05:13 +0100444 mult += (Py_uhash_t)(82520UL + len + len);
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100445 }
446 x += 97531UL;
447 return x;
448}
449
Victor Stinnere492ae52016-03-22 12:58:23 +0100450
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100451static void
452traceback_get_frames(traceback_t *traceback)
453{
454 PyThreadState *tstate;
455 PyFrameObject *pyframe;
456
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100457 tstate = PyGILState_GetThisThreadState();
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100458 if (tstate == NULL) {
459#ifdef TRACE_DEBUG
460 tracemalloc_error("failed to get the current thread state");
461#endif
462 return;
463 }
464
465 for (pyframe = tstate->frame; pyframe != NULL; pyframe = pyframe->f_back) {
466 tracemalloc_get_frame(pyframe, &traceback->frames[traceback->nframe]);
467 assert(traceback->frames[traceback->nframe].filename != NULL);
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100468 traceback->nframe++;
469 if (traceback->nframe == tracemalloc_config.max_nframe)
470 break;
471 }
472}
473
Victor Stinnere492ae52016-03-22 12:58:23 +0100474
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100475static traceback_t *
476traceback_new(void)
477{
Victor Stinnerf28ce602013-11-27 22:27:13 +0100478 traceback_t *traceback;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100479 _Py_hashtable_entry_t *entry;
480
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100481 assert(PyGILState_Check());
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100482
483 /* get frames */
Victor Stinnerf28ce602013-11-27 22:27:13 +0100484 traceback = tracemalloc_traceback;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100485 traceback->nframe = 0;
486 traceback_get_frames(traceback);
487 if (traceback->nframe == 0)
488 return &tracemalloc_empty_traceback;
489 traceback->hash = traceback_hash(traceback);
490
491 /* intern the traceback */
Victor Stinner285cf0a2016-03-21 22:00:58 +0100492 entry = _Py_HASHTABLE_GET_ENTRY(tracemalloc_tracebacks, traceback);
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100493 if (entry != NULL) {
Victor Stinner5dacbd42016-03-23 09:52:13 +0100494 _Py_HASHTABLE_ENTRY_READ_KEY(tracemalloc_tracebacks, entry, traceback);
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100495 }
496 else {
497 traceback_t *copy;
498 size_t traceback_size;
499
500 traceback_size = TRACEBACK_SIZE(traceback->nframe);
501
502 copy = raw_malloc(traceback_size);
503 if (copy == NULL) {
504#ifdef TRACE_DEBUG
505 tracemalloc_error("failed to intern the traceback: malloc failed");
506#endif
507 return NULL;
508 }
509 memcpy(copy, traceback, traceback_size);
510
Victor Stinner285cf0a2016-03-21 22:00:58 +0100511 if (_Py_HASHTABLE_SET_NODATA(tracemalloc_tracebacks, copy) < 0) {
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100512 raw_free(copy);
513#ifdef TRACE_DEBUG
514 tracemalloc_error("failed to intern the traceback: putdata failed");
515#endif
516 return NULL;
517 }
518 traceback = copy;
519 }
520 return traceback;
521}
522
Victor Stinnere492ae52016-03-22 12:58:23 +0100523
Victor Stinner5e14a382016-03-23 22:03:55 +0100524static int
525tracemalloc_use_domain_cb(_Py_hashtable_t *old_traces,
526 _Py_hashtable_entry_t *entry, void *user_data)
527{
Benjamin Petersonca470632016-09-06 13:47:26 -0700528 uintptr_t ptr;
Victor Stinner5e14a382016-03-23 22:03:55 +0100529 pointer_t key;
530 _Py_hashtable_t *new_traces = (_Py_hashtable_t *)user_data;
531 const void *pdata = _Py_HASHTABLE_ENTRY_PDATA(old_traces, entry);
532
533 _Py_HASHTABLE_ENTRY_READ_KEY(old_traces, entry, ptr);
534 key.ptr = ptr;
535 key.domain = DEFAULT_DOMAIN;
536
537 return _Py_hashtable_set(new_traces,
538 sizeof(key), &key,
539 old_traces->data_size, pdata);
540}
541
542
Benjamin Petersonca470632016-09-06 13:47:26 -0700543/* Convert tracemalloc_traces from compact key (uintptr_t) to pointer_t key.
Victor Stinner5e14a382016-03-23 22:03:55 +0100544 * Return 0 on success, -1 on error. */
545static int
546tracemalloc_use_domain(void)
547{
548 _Py_hashtable_t *new_traces = NULL;
549
550 assert(!tracemalloc_config.use_domain);
551
552 new_traces = hashtable_new(sizeof(pointer_t),
553 sizeof(trace_t),
554 hashtable_hash_pointer_t,
555 hashtable_compare_pointer_t);
556 if (new_traces == NULL) {
557 return -1;
558 }
559
560 if (_Py_hashtable_foreach(tracemalloc_traces, tracemalloc_use_domain_cb,
561 new_traces) < 0)
562 {
563 _Py_hashtable_destroy(new_traces);
564 return -1;
565 }
566
567 _Py_hashtable_destroy(tracemalloc_traces);
568 tracemalloc_traces = new_traces;
569
570 tracemalloc_config.use_domain = 1;
571
572 return 0;
573}
574
575
Victor Stinnere492ae52016-03-22 12:58:23 +0100576static void
Victor Stinner5ea4c062017-06-20 17:46:36 +0200577tracemalloc_remove_trace(unsigned int domain, uintptr_t ptr)
Victor Stinnere492ae52016-03-22 12:58:23 +0100578{
579 trace_t trace;
580 int removed;
581
Victor Stinner10b73e12016-03-22 13:39:05 +0100582 assert(tracemalloc_config.tracing);
583
Victor Stinnere492ae52016-03-22 12:58:23 +0100584 if (tracemalloc_config.use_domain) {
585 pointer_t key = {ptr, domain};
586 removed = _Py_HASHTABLE_POP(tracemalloc_traces, key, trace);
587 }
588 else {
589 removed = _Py_HASHTABLE_POP(tracemalloc_traces, ptr, trace);
590 }
591 if (!removed) {
592 return;
593 }
594
595 assert(tracemalloc_traced_memory >= trace.size);
596 tracemalloc_traced_memory -= trace.size;
597}
598
599#define REMOVE_TRACE(ptr) \
Benjamin Petersonca470632016-09-06 13:47:26 -0700600 tracemalloc_remove_trace(DEFAULT_DOMAIN, (uintptr_t)(ptr))
Victor Stinnere492ae52016-03-22 12:58:23 +0100601
602
Victor Stinner52968672013-11-24 11:37:15 +0100603static int
Victor Stinner5ea4c062017-06-20 17:46:36 +0200604tracemalloc_add_trace(unsigned int domain, uintptr_t ptr,
Victor Stinner10b73e12016-03-22 13:39:05 +0100605 size_t size)
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100606{
Victor Stinnerca79ccd2016-03-23 09:38:54 +0100607 pointer_t key = {ptr, domain};
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100608 traceback_t *traceback;
609 trace_t trace;
Victor Stinnerca79ccd2016-03-23 09:38:54 +0100610 _Py_hashtable_entry_t* entry;
Victor Stinner52968672013-11-24 11:37:15 +0100611 int res;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100612
Victor Stinner10b73e12016-03-22 13:39:05 +0100613 assert(tracemalloc_config.tracing);
614
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100615 traceback = traceback_new();
Victor Stinnere492ae52016-03-22 12:58:23 +0100616 if (traceback == NULL) {
Victor Stinner52968672013-11-24 11:37:15 +0100617 return -1;
Victor Stinnere492ae52016-03-22 12:58:23 +0100618 }
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100619
Victor Stinner5e14a382016-03-23 22:03:55 +0100620 if (!tracemalloc_config.use_domain && domain != DEFAULT_DOMAIN) {
621 /* first trace using a non-zero domain whereas traces use compact
Benjamin Petersonca470632016-09-06 13:47:26 -0700622 (uintptr_t) keys: switch to pointer_t keys. */
Victor Stinner5e14a382016-03-23 22:03:55 +0100623 if (tracemalloc_use_domain() < 0) {
624 return -1;
625 }
626 }
627
Victor Stinnere492ae52016-03-22 12:58:23 +0100628 if (tracemalloc_config.use_domain) {
Victor Stinnerca79ccd2016-03-23 09:38:54 +0100629 entry = _Py_HASHTABLE_GET_ENTRY(tracemalloc_traces, key);
Victor Stinnere492ae52016-03-22 12:58:23 +0100630 }
631 else {
Victor Stinnerca79ccd2016-03-23 09:38:54 +0100632 entry = _Py_HASHTABLE_GET_ENTRY(tracemalloc_traces, ptr);
Victor Stinnerd606ba72013-11-24 11:28:20 +0100633 }
Victor Stinner52968672013-11-24 11:37:15 +0100634
Victor Stinnerca79ccd2016-03-23 09:38:54 +0100635 if (entry != NULL) {
636 /* the memory block is already tracked */
637 _Py_HASHTABLE_ENTRY_READ_DATA(tracemalloc_traces, entry, trace);
638 assert(tracemalloc_traced_memory >= trace.size);
639 tracemalloc_traced_memory -= trace.size;
640
641 trace.size = size;
642 trace.traceback = traceback;
643 _Py_HASHTABLE_ENTRY_WRITE_DATA(tracemalloc_traces, entry, trace);
644 }
645 else {
646 trace.size = size;
647 trace.traceback = traceback;
648
649 if (tracemalloc_config.use_domain) {
650 res = _Py_HASHTABLE_SET(tracemalloc_traces, key, trace);
651 }
652 else {
653 res = _Py_HASHTABLE_SET(tracemalloc_traces, ptr, trace);
654 }
655 if (res != 0) {
656 return res;
657 }
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100658 }
Victor Stinnere492ae52016-03-22 12:58:23 +0100659
Benjamin Peterson2f8bfef2016-09-07 09:26:18 -0700660 assert(tracemalloc_traced_memory <= SIZE_MAX - size);
Victor Stinnere492ae52016-03-22 12:58:23 +0100661 tracemalloc_traced_memory += size;
662 if (tracemalloc_traced_memory > tracemalloc_peak_traced_memory)
663 tracemalloc_peak_traced_memory = tracemalloc_traced_memory;
664 return 0;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100665}
666
Victor Stinnere492ae52016-03-22 12:58:23 +0100667#define ADD_TRACE(ptr, size) \
Benjamin Petersonca470632016-09-06 13:47:26 -0700668 tracemalloc_add_trace(DEFAULT_DOMAIN, (uintptr_t)(ptr), size)
Victor Stinnere492ae52016-03-22 12:58:23 +0100669
670
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100671static void*
Victor Stinnerdb067af2014-05-02 22:31:14 +0200672tracemalloc_alloc(int use_calloc, void *ctx, size_t nelem, size_t elsize)
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100673{
Victor Stinnerd8f0d922014-06-02 21:57:10 +0200674 PyMemAllocatorEx *alloc = (PyMemAllocatorEx *)ctx;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100675 void *ptr;
676
Benjamin Peterson2f8bfef2016-09-07 09:26:18 -0700677 assert(elsize == 0 || nelem <= SIZE_MAX / elsize);
Victor Stinnerdb067af2014-05-02 22:31:14 +0200678
679 if (use_calloc)
680 ptr = alloc->calloc(alloc->ctx, nelem, elsize);
681 else
682 ptr = alloc->malloc(alloc->ctx, nelem * elsize);
Victor Stinner15116802013-12-04 01:29:35 +0100683 if (ptr == NULL)
684 return NULL;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100685
Victor Stinner88c29872013-12-04 01:47:46 +0100686 TABLES_LOCK();
Victor Stinnere492ae52016-03-22 12:58:23 +0100687 if (ADD_TRACE(ptr, nelem * elsize) < 0) {
Victor Stinner15116802013-12-04 01:29:35 +0100688 /* Failed to allocate a trace for the new memory block */
Victor Stinner88c29872013-12-04 01:47:46 +0100689 TABLES_UNLOCK();
Victor Stinner15116802013-12-04 01:29:35 +0100690 alloc->free(alloc->ctx, ptr);
691 return NULL;
Victor Stinner52968672013-11-24 11:37:15 +0100692 }
Victor Stinner88c29872013-12-04 01:47:46 +0100693 TABLES_UNLOCK();
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100694 return ptr;
695}
696
Victor Stinnere492ae52016-03-22 12:58:23 +0100697
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100698static void*
Victor Stinner15116802013-12-04 01:29:35 +0100699tracemalloc_realloc(void *ctx, void *ptr, size_t new_size)
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100700{
Victor Stinnerd8f0d922014-06-02 21:57:10 +0200701 PyMemAllocatorEx *alloc = (PyMemAllocatorEx *)ctx;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100702 void *ptr2;
703
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100704 ptr2 = alloc->realloc(alloc->ctx, ptr, new_size);
Victor Stinner15116802013-12-04 01:29:35 +0100705 if (ptr2 == NULL)
706 return NULL;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100707
Victor Stinner15116802013-12-04 01:29:35 +0100708 if (ptr != NULL) {
709 /* an existing memory block has been resized */
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100710
Victor Stinner88c29872013-12-04 01:47:46 +0100711 TABLES_LOCK();
Victor Stinner42bcf372016-03-23 09:08:08 +0100712
713 /* tracemalloc_add_trace() updates the trace if there is already
714 a trace at address (domain, ptr2) */
715 if (ptr2 != ptr) {
716 REMOVE_TRACE(ptr);
717 }
Victor Stinner08facd22013-11-24 12:27:59 +0100718
Victor Stinnere492ae52016-03-22 12:58:23 +0100719 if (ADD_TRACE(ptr2, new_size) < 0) {
Victor Stinner15116802013-12-04 01:29:35 +0100720 /* Memory allocation failed. The error cannot be reported to
Raymond Hettinger15f44ab2016-08-30 10:47:49 -0700721 the caller, because realloc() may already have shrunk the
Victor Stinner15116802013-12-04 01:29:35 +0100722 memory block and so removed bytes.
723
Serhiy Storchaka6a7b3a72016-04-17 08:32:47 +0300724 This case is very unlikely: a hash entry has just been
Victor Stinner88c29872013-12-04 01:47:46 +0100725 released, so the hash table should have at least one free entry.
726
727 The GIL and the table lock ensures that only one thread is
728 allocating memory. */
Barry Warsawb2e57942017-09-14 18:13:16 -0700729 Py_UNREACHABLE();
Victor Stinner52968672013-11-24 11:37:15 +0100730 }
Victor Stinner88c29872013-12-04 01:47:46 +0100731 TABLES_UNLOCK();
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100732 }
Victor Stinner15116802013-12-04 01:29:35 +0100733 else {
734 /* new allocation */
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100735
Victor Stinner88c29872013-12-04 01:47:46 +0100736 TABLES_LOCK();
Victor Stinnere492ae52016-03-22 12:58:23 +0100737 if (ADD_TRACE(ptr2, new_size) < 0) {
Victor Stinner15116802013-12-04 01:29:35 +0100738 /* Failed to allocate a trace for the new memory block */
Victor Stinner88c29872013-12-04 01:47:46 +0100739 TABLES_UNLOCK();
Victor Stinner15116802013-12-04 01:29:35 +0100740 alloc->free(alloc->ctx, ptr2);
741 return NULL;
742 }
Victor Stinner88c29872013-12-04 01:47:46 +0100743 TABLES_UNLOCK();
Victor Stinner15116802013-12-04 01:29:35 +0100744 }
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100745 return ptr2;
746}
747
Victor Stinnere492ae52016-03-22 12:58:23 +0100748
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100749static void
750tracemalloc_free(void *ctx, void *ptr)
751{
Victor Stinnerd8f0d922014-06-02 21:57:10 +0200752 PyMemAllocatorEx *alloc = (PyMemAllocatorEx *)ctx;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100753
754 if (ptr == NULL)
755 return;
756
757 /* GIL cannot be locked in PyMem_RawFree() because it would introduce
758 a deadlock in PyThreadState_DeleteCurrent(). */
759
760 alloc->free(alloc->ctx, ptr);
Victor Stinner88c29872013-12-04 01:47:46 +0100761
762 TABLES_LOCK();
Victor Stinnere492ae52016-03-22 12:58:23 +0100763 REMOVE_TRACE(ptr);
Victor Stinner88c29872013-12-04 01:47:46 +0100764 TABLES_UNLOCK();
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100765}
766
Victor Stinnere492ae52016-03-22 12:58:23 +0100767
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100768static void*
Victor Stinnerdb067af2014-05-02 22:31:14 +0200769tracemalloc_alloc_gil(int use_calloc, void *ctx, size_t nelem, size_t elsize)
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100770{
Victor Stinner15116802013-12-04 01:29:35 +0100771 void *ptr;
772
773 if (get_reentrant()) {
Victor Stinnerd8f0d922014-06-02 21:57:10 +0200774 PyMemAllocatorEx *alloc = (PyMemAllocatorEx *)ctx;
Victor Stinnerdb067af2014-05-02 22:31:14 +0200775 if (use_calloc)
776 return alloc->calloc(alloc->ctx, nelem, elsize);
777 else
778 return alloc->malloc(alloc->ctx, nelem * elsize);
Victor Stinner15116802013-12-04 01:29:35 +0100779 }
780
781 /* Ignore reentrant call. PyObjet_Malloc() calls PyMem_Malloc() for
782 allocations larger than 512 bytes, don't trace the same memory
783 allocation twice. */
784 set_reentrant(1);
785
Victor Stinnerdb067af2014-05-02 22:31:14 +0200786 ptr = tracemalloc_alloc(use_calloc, ctx, nelem, elsize);
Victor Stinner15116802013-12-04 01:29:35 +0100787
788 set_reentrant(0);
789 return ptr;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100790}
791
Victor Stinnere492ae52016-03-22 12:58:23 +0100792
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100793static void*
Victor Stinnerdb067af2014-05-02 22:31:14 +0200794tracemalloc_malloc_gil(void *ctx, size_t size)
795{
796 return tracemalloc_alloc_gil(0, ctx, 1, size);
797}
798
Victor Stinnere492ae52016-03-22 12:58:23 +0100799
Victor Stinnerdb067af2014-05-02 22:31:14 +0200800static void*
801tracemalloc_calloc_gil(void *ctx, size_t nelem, size_t elsize)
802{
803 return tracemalloc_alloc_gil(1, ctx, nelem, elsize);
804}
805
Victor Stinnere492ae52016-03-22 12:58:23 +0100806
Victor Stinnerdb067af2014-05-02 22:31:14 +0200807static void*
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100808tracemalloc_realloc_gil(void *ctx, void *ptr, size_t new_size)
809{
Victor Stinner15116802013-12-04 01:29:35 +0100810 void *ptr2;
811
812 if (get_reentrant()) {
813 /* Reentrant call to PyMem_Realloc() and PyMem_RawRealloc().
814 Example: PyMem_RawRealloc() is called internally by pymalloc
815 (_PyObject_Malloc() and _PyObject_Realloc()) to allocate a new
816 arena (new_arena()). */
Victor Stinnerd8f0d922014-06-02 21:57:10 +0200817 PyMemAllocatorEx *alloc = (PyMemAllocatorEx *)ctx;
Victor Stinner15116802013-12-04 01:29:35 +0100818
819 ptr2 = alloc->realloc(alloc->ctx, ptr, new_size);
Victor Stinner88c29872013-12-04 01:47:46 +0100820 if (ptr2 != NULL && ptr != NULL) {
821 TABLES_LOCK();
Victor Stinnere492ae52016-03-22 12:58:23 +0100822 REMOVE_TRACE(ptr);
Victor Stinner88c29872013-12-04 01:47:46 +0100823 TABLES_UNLOCK();
824 }
Victor Stinner15116802013-12-04 01:29:35 +0100825 return ptr2;
826 }
827
828 /* Ignore reentrant call. PyObjet_Realloc() calls PyMem_Realloc() for
829 allocations larger than 512 bytes. Don't trace the same memory
830 allocation twice. */
831 set_reentrant(1);
832
833 ptr2 = tracemalloc_realloc(ctx, ptr, new_size);
834
835 set_reentrant(0);
836 return ptr2;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100837}
838
Victor Stinnere492ae52016-03-22 12:58:23 +0100839
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100840#ifdef TRACE_RAW_MALLOC
841static void*
Victor Stinnerdb067af2014-05-02 22:31:14 +0200842tracemalloc_raw_alloc(int use_calloc, void *ctx, size_t nelem, size_t elsize)
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100843{
Victor Stinner15116802013-12-04 01:29:35 +0100844 PyGILState_STATE gil_state;
Victor Stinner15116802013-12-04 01:29:35 +0100845 void *ptr;
846
847 if (get_reentrant()) {
Victor Stinnerd8f0d922014-06-02 21:57:10 +0200848 PyMemAllocatorEx *alloc = (PyMemAllocatorEx *)ctx;
Victor Stinnerdb067af2014-05-02 22:31:14 +0200849 if (use_calloc)
850 return alloc->calloc(alloc->ctx, nelem, elsize);
851 else
852 return alloc->malloc(alloc->ctx, nelem * elsize);
Victor Stinner15116802013-12-04 01:29:35 +0100853 }
854
855 /* Ignore reentrant call. PyGILState_Ensure() may call PyMem_RawMalloc()
856 indirectly which would call PyGILState_Ensure() if reentrant are not
857 disabled. */
858 set_reentrant(1);
859
Victor Stinner15116802013-12-04 01:29:35 +0100860 gil_state = PyGILState_Ensure();
Victor Stinnerdb067af2014-05-02 22:31:14 +0200861 ptr = tracemalloc_alloc(use_calloc, ctx, nelem, elsize);
Victor Stinner15116802013-12-04 01:29:35 +0100862 PyGILState_Release(gil_state);
Victor Stinner15116802013-12-04 01:29:35 +0100863
864 set_reentrant(0);
865 return ptr;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100866}
867
Victor Stinnere492ae52016-03-22 12:58:23 +0100868
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100869static void*
Victor Stinnerdb067af2014-05-02 22:31:14 +0200870tracemalloc_raw_malloc(void *ctx, size_t size)
871{
872 return tracemalloc_raw_alloc(0, ctx, 1, size);
873}
874
Victor Stinnere492ae52016-03-22 12:58:23 +0100875
Victor Stinnerdb067af2014-05-02 22:31:14 +0200876static void*
877tracemalloc_raw_calloc(void *ctx, size_t nelem, size_t elsize)
878{
879 return tracemalloc_raw_alloc(1, ctx, nelem, elsize);
880}
881
Victor Stinnere492ae52016-03-22 12:58:23 +0100882
Victor Stinnerdb067af2014-05-02 22:31:14 +0200883static void*
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100884tracemalloc_raw_realloc(void *ctx, void *ptr, size_t new_size)
885{
Victor Stinner15116802013-12-04 01:29:35 +0100886 PyGILState_STATE gil_state;
Victor Stinner15116802013-12-04 01:29:35 +0100887 void *ptr2;
888
889 if (get_reentrant()) {
890 /* Reentrant call to PyMem_RawRealloc(). */
Victor Stinnerd8f0d922014-06-02 21:57:10 +0200891 PyMemAllocatorEx *alloc = (PyMemAllocatorEx *)ctx;
Victor Stinner15116802013-12-04 01:29:35 +0100892
893 ptr2 = alloc->realloc(alloc->ctx, ptr, new_size);
Victor Stinner15116802013-12-04 01:29:35 +0100894
Victor Stinner88c29872013-12-04 01:47:46 +0100895 if (ptr2 != NULL && ptr != NULL) {
896 TABLES_LOCK();
Victor Stinnere492ae52016-03-22 12:58:23 +0100897 REMOVE_TRACE(ptr);
Victor Stinner88c29872013-12-04 01:47:46 +0100898 TABLES_UNLOCK();
899 }
Victor Stinner15116802013-12-04 01:29:35 +0100900 return ptr2;
901 }
902
903 /* Ignore reentrant call. PyGILState_Ensure() may call PyMem_RawMalloc()
904 indirectly which would call PyGILState_Ensure() if reentrant calls are
905 not disabled. */
906 set_reentrant(1);
907
Victor Stinner15116802013-12-04 01:29:35 +0100908 gil_state = PyGILState_Ensure();
909 ptr2 = tracemalloc_realloc(ctx, ptr, new_size);
910 PyGILState_Release(gil_state);
Victor Stinner15116802013-12-04 01:29:35 +0100911
912 set_reentrant(0);
913 return ptr2;
914}
915#endif /* TRACE_RAW_MALLOC */
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100916
Victor Stinnere492ae52016-03-22 12:58:23 +0100917
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100918static int
Victor Stinner285cf0a2016-03-21 22:00:58 +0100919tracemalloc_clear_filename(_Py_hashtable_t *ht, _Py_hashtable_entry_t *entry,
920 void *user_data)
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100921{
Victor Stinner285cf0a2016-03-21 22:00:58 +0100922 PyObject *filename;
923
Victor Stinner5dacbd42016-03-23 09:52:13 +0100924 _Py_HASHTABLE_ENTRY_READ_KEY(ht, entry, filename);
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100925 Py_DECREF(filename);
926 return 0;
927}
928
Victor Stinnere492ae52016-03-22 12:58:23 +0100929
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100930static int
Victor Stinner285cf0a2016-03-21 22:00:58 +0100931traceback_free_traceback(_Py_hashtable_t *ht, _Py_hashtable_entry_t *entry,
932 void *user_data)
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100933{
Victor Stinner285cf0a2016-03-21 22:00:58 +0100934 traceback_t *traceback;
935
Victor Stinner5dacbd42016-03-23 09:52:13 +0100936 _Py_HASHTABLE_ENTRY_READ_KEY(ht, entry, traceback);
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100937 raw_free(traceback);
938 return 0;
939}
940
Victor Stinnere492ae52016-03-22 12:58:23 +0100941
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100942/* reentrant flag must be set to call this function and GIL must be held */
943static void
944tracemalloc_clear_traces(void)
945{
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100946 /* The GIL protects variables againt concurrent access */
947 assert(PyGILState_Check());
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100948
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100949 TABLES_LOCK();
950 _Py_hashtable_clear(tracemalloc_traces);
951 tracemalloc_traced_memory = 0;
Victor Stinner3c0481d2013-11-27 21:39:49 +0100952 tracemalloc_peak_traced_memory = 0;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100953 TABLES_UNLOCK();
954
955 _Py_hashtable_foreach(tracemalloc_tracebacks, traceback_free_traceback, NULL);
956 _Py_hashtable_clear(tracemalloc_tracebacks);
957
958 _Py_hashtable_foreach(tracemalloc_filenames, tracemalloc_clear_filename, NULL);
959 _Py_hashtable_clear(tracemalloc_filenames);
960}
961
Victor Stinnere492ae52016-03-22 12:58:23 +0100962
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100963static int
964tracemalloc_init(void)
965{
966 if (tracemalloc_config.initialized == TRACEMALLOC_FINALIZED) {
967 PyErr_SetString(PyExc_RuntimeError,
968 "the tracemalloc module has been unloaded");
969 return -1;
970 }
971
Victor Stinnerf9a71152016-03-22 23:54:42 +0100972 if (tracemalloc_config.initialized == TRACEMALLOC_INITIALIZED)
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100973 return 0;
974
975 PyMem_GetAllocator(PYMEM_DOMAIN_RAW, &allocators.raw);
976
977#ifdef REENTRANT_THREADLOCAL
978 tracemalloc_reentrant_key = PyThread_create_key();
979 if (tracemalloc_reentrant_key == -1) {
980#ifdef MS_WINDOWS
981 PyErr_SetFromWindowsErr(0);
982#else
983 PyErr_SetFromErrno(PyExc_OSError);
984#endif
985 return -1;
986 }
987#endif
988
Antoine Pitroua6a4dc82017-09-07 18:56:24 +0200989#if defined(TRACE_RAW_MALLOC)
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100990 if (tables_lock == NULL) {
991 tables_lock = PyThread_allocate_lock();
992 if (tables_lock == NULL) {
993 PyErr_SetString(PyExc_RuntimeError, "cannot allocate lock");
994 return -1;
995 }
996 }
997#endif
998
Victor Stinner285cf0a2016-03-21 22:00:58 +0100999 tracemalloc_filenames = hashtable_new(sizeof(PyObject *), 0,
1000 hashtable_hash_pyobject,
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001001 hashtable_compare_unicode);
1002
Victor Stinner285cf0a2016-03-21 22:00:58 +01001003 tracemalloc_tracebacks = hashtable_new(sizeof(traceback_t *), 0,
1004 hashtable_hash_traceback,
1005 hashtable_compare_traceback);
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001006
Victor Stinnere492ae52016-03-22 12:58:23 +01001007 if (tracemalloc_config.use_domain) {
1008 tracemalloc_traces = hashtable_new(sizeof(pointer_t),
1009 sizeof(trace_t),
1010 hashtable_hash_pointer_t,
1011 hashtable_compare_pointer_t);
1012 }
1013 else {
Benjamin Petersonca470632016-09-06 13:47:26 -07001014 tracemalloc_traces = hashtable_new(sizeof(uintptr_t),
Victor Stinnere492ae52016-03-22 12:58:23 +01001015 sizeof(trace_t),
1016 _Py_hashtable_hash_ptr,
1017 _Py_hashtable_compare_direct);
1018 }
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001019
1020 if (tracemalloc_filenames == NULL || tracemalloc_tracebacks == NULL
Victor Stinner285cf0a2016-03-21 22:00:58 +01001021 || tracemalloc_traces == NULL) {
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001022 PyErr_NoMemory();
1023 return -1;
1024 }
1025
1026 unknown_filename = PyUnicode_FromString("<unknown>");
1027 if (unknown_filename == NULL)
1028 return -1;
1029 PyUnicode_InternInPlace(&unknown_filename);
1030
1031 tracemalloc_empty_traceback.nframe = 1;
1032 /* borrowed reference */
1033 tracemalloc_empty_traceback.frames[0].filename = unknown_filename;
1034 tracemalloc_empty_traceback.frames[0].lineno = 0;
1035 tracemalloc_empty_traceback.hash = traceback_hash(&tracemalloc_empty_traceback);
1036
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001037 tracemalloc_config.initialized = TRACEMALLOC_INITIALIZED;
1038 return 0;
1039}
1040
Victor Stinnere492ae52016-03-22 12:58:23 +01001041
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001042static void
1043tracemalloc_deinit(void)
1044{
Victor Stinnerf9a71152016-03-22 23:54:42 +01001045 if (tracemalloc_config.initialized != TRACEMALLOC_INITIALIZED)
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001046 return;
1047 tracemalloc_config.initialized = TRACEMALLOC_FINALIZED;
1048
1049 tracemalloc_stop();
1050
1051 /* destroy hash tables */
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001052 _Py_hashtable_destroy(tracemalloc_tracebacks);
1053 _Py_hashtable_destroy(tracemalloc_filenames);
Victor Stinner285cf0a2016-03-21 22:00:58 +01001054 _Py_hashtable_destroy(tracemalloc_traces);
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001055
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02001056#if defined(TRACE_RAW_MALLOC)
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001057 if (tables_lock != NULL) {
1058 PyThread_free_lock(tables_lock);
1059 tables_lock = NULL;
1060 }
1061#endif
1062
1063#ifdef REENTRANT_THREADLOCAL
1064 PyThread_delete_key(tracemalloc_reentrant_key);
Victor Stinner4a066472016-03-22 17:45:09 +01001065 tracemalloc_reentrant_key = -1;
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001066#endif
1067
1068 Py_XDECREF(unknown_filename);
1069}
1070
Victor Stinnere492ae52016-03-22 12:58:23 +01001071
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001072static int
Victor Stinnerf28ce602013-11-27 22:27:13 +01001073tracemalloc_start(int max_nframe)
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001074{
Victor Stinnerd8f0d922014-06-02 21:57:10 +02001075 PyMemAllocatorEx alloc;
Victor Stinnerf28ce602013-11-27 22:27:13 +01001076 size_t size;
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001077
Victor Stinnerf9a71152016-03-22 23:54:42 +01001078 if (tracemalloc_init() < 0)
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001079 return -1;
1080
1081 if (tracemalloc_config.tracing) {
1082 /* hook already installed: do nothing */
1083 return 0;
1084 }
1085
Victor Stinner52aee852014-08-16 15:44:02 +02001086 assert(1 <= max_nframe && max_nframe <= MAX_NFRAME);
Victor Stinnerf28ce602013-11-27 22:27:13 +01001087 tracemalloc_config.max_nframe = max_nframe;
1088
1089 /* allocate a buffer to store a new traceback */
1090 size = TRACEBACK_SIZE(max_nframe);
1091 assert(tracemalloc_traceback == NULL);
1092 tracemalloc_traceback = raw_malloc(size);
1093 if (tracemalloc_traceback == NULL) {
1094 PyErr_NoMemory();
1095 return -1;
1096 }
1097
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001098#ifdef TRACE_RAW_MALLOC
1099 alloc.malloc = tracemalloc_raw_malloc;
Victor Stinnerdb067af2014-05-02 22:31:14 +02001100 alloc.calloc = tracemalloc_raw_calloc;
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001101 alloc.realloc = tracemalloc_raw_realloc;
1102 alloc.free = tracemalloc_free;
1103
1104 alloc.ctx = &allocators.raw;
1105 PyMem_GetAllocator(PYMEM_DOMAIN_RAW, &allocators.raw);
1106 PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &alloc);
1107#endif
1108
1109 alloc.malloc = tracemalloc_malloc_gil;
Victor Stinnerdb067af2014-05-02 22:31:14 +02001110 alloc.calloc = tracemalloc_calloc_gil;
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001111 alloc.realloc = tracemalloc_realloc_gil;
1112 alloc.free = tracemalloc_free;
1113
1114 alloc.ctx = &allocators.mem;
1115 PyMem_GetAllocator(PYMEM_DOMAIN_MEM, &allocators.mem);
1116 PyMem_SetAllocator(PYMEM_DOMAIN_MEM, &alloc);
1117
1118 alloc.ctx = &allocators.obj;
1119 PyMem_GetAllocator(PYMEM_DOMAIN_OBJ, &allocators.obj);
1120 PyMem_SetAllocator(PYMEM_DOMAIN_OBJ, &alloc);
1121
1122 /* everything is ready: start tracing Python memory allocations */
1123 tracemalloc_config.tracing = 1;
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001124
1125 return 0;
1126}
1127
Victor Stinnere492ae52016-03-22 12:58:23 +01001128
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001129static void
1130tracemalloc_stop(void)
1131{
Victor Stinnerf9a71152016-03-22 23:54:42 +01001132 if (!tracemalloc_config.tracing)
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001133 return;
1134
1135 /* stop tracing Python memory allocations */
1136 tracemalloc_config.tracing = 0;
1137
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001138 /* unregister the hook on memory allocators */
1139#ifdef TRACE_RAW_MALLOC
1140 PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &allocators.raw);
1141#endif
1142 PyMem_SetAllocator(PYMEM_DOMAIN_MEM, &allocators.mem);
1143 PyMem_SetAllocator(PYMEM_DOMAIN_OBJ, &allocators.obj);
1144
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001145 tracemalloc_clear_traces();
Victor Stinner285cf0a2016-03-21 22:00:58 +01001146
1147 /* release memory */
Victor Stinnerf28ce602013-11-27 22:27:13 +01001148 raw_free(tracemalloc_traceback);
1149 tracemalloc_traceback = NULL;
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001150}
1151
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001152
Victor Stinnere492ae52016-03-22 12:58:23 +01001153
Serhiy Storchakab451f912017-02-04 12:18:38 +02001154/*[clinic input]
1155_tracemalloc.is_tracing
1156
1157Return True if the tracemalloc module is tracing Python memory allocations.
1158[clinic start generated code]*/
1159
1160static PyObject *
1161_tracemalloc_is_tracing_impl(PyObject *module)
Serhiy Storchaka97353842017-02-05 22:58:46 +02001162/*[clinic end generated code: output=2d763b42601cd3ef input=af104b0a00192f63]*/
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001163{
1164 return PyBool_FromLong(tracemalloc_config.tracing);
1165}
1166
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001167
Serhiy Storchakab451f912017-02-04 12:18:38 +02001168/*[clinic input]
1169_tracemalloc.clear_traces
Victor Stinnere492ae52016-03-22 12:58:23 +01001170
Serhiy Storchakab451f912017-02-04 12:18:38 +02001171Clear traces of memory blocks allocated by Python.
1172[clinic start generated code]*/
1173
1174static PyObject *
1175_tracemalloc_clear_traces_impl(PyObject *module)
1176/*[clinic end generated code: output=a86080ee41b84197 input=0dab5b6c785183a5]*/
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001177{
1178 if (!tracemalloc_config.tracing)
1179 Py_RETURN_NONE;
1180
1181 set_reentrant(1);
1182 tracemalloc_clear_traces();
1183 set_reentrant(0);
1184
1185 Py_RETURN_NONE;
1186}
1187
Victor Stinnere492ae52016-03-22 12:58:23 +01001188
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001189static PyObject*
1190frame_to_pyobject(frame_t *frame)
1191{
1192 PyObject *frame_obj, *lineno_obj;
1193
1194 frame_obj = PyTuple_New(2);
1195 if (frame_obj == NULL)
1196 return NULL;
1197
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001198 Py_INCREF(frame->filename);
1199 PyTuple_SET_ITEM(frame_obj, 0, frame->filename);
1200
Victor Stinner95283342016-03-15 21:57:02 +01001201 lineno_obj = PyLong_FromUnsignedLong(frame->lineno);
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001202 if (lineno_obj == NULL) {
1203 Py_DECREF(frame_obj);
1204 return NULL;
1205 }
1206 PyTuple_SET_ITEM(frame_obj, 1, lineno_obj);
1207
1208 return frame_obj;
1209}
1210
Victor Stinnere492ae52016-03-22 12:58:23 +01001211
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001212static PyObject*
1213traceback_to_pyobject(traceback_t *traceback, _Py_hashtable_t *intern_table)
1214{
1215 int i;
1216 PyObject *frames, *frame;
1217
1218 if (intern_table != NULL) {
1219 if (_Py_HASHTABLE_GET(intern_table, traceback, frames)) {
1220 Py_INCREF(frames);
1221 return frames;
1222 }
1223 }
1224
1225 frames = PyTuple_New(traceback->nframe);
1226 if (frames == NULL)
1227 return NULL;
1228
1229 for (i=0; i < traceback->nframe; i++) {
1230 frame = frame_to_pyobject(&traceback->frames[i]);
1231 if (frame == NULL) {
1232 Py_DECREF(frames);
1233 return NULL;
1234 }
1235 PyTuple_SET_ITEM(frames, i, frame);
1236 }
1237
1238 if (intern_table != NULL) {
1239 if (_Py_HASHTABLE_SET(intern_table, traceback, frames) < 0) {
1240 Py_DECREF(frames);
1241 PyErr_NoMemory();
1242 return NULL;
1243 }
1244 /* intern_table keeps a new reference to frames */
1245 Py_INCREF(frames);
1246 }
1247 return frames;
1248}
1249
Victor Stinnere492ae52016-03-22 12:58:23 +01001250
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001251static PyObject*
Victor Stinner5ea4c062017-06-20 17:46:36 +02001252trace_to_pyobject(unsigned int domain, trace_t *trace,
Victor Stinnere492ae52016-03-22 12:58:23 +01001253 _Py_hashtable_t *intern_tracebacks)
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001254{
1255 PyObject *trace_obj = NULL;
Victor Stinnere492ae52016-03-22 12:58:23 +01001256 PyObject *obj;
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001257
Victor Stinnere492ae52016-03-22 12:58:23 +01001258 trace_obj = PyTuple_New(3);
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001259 if (trace_obj == NULL)
1260 return NULL;
1261
Victor Stinnere492ae52016-03-22 12:58:23 +01001262 obj = PyLong_FromSize_t(domain);
1263 if (obj == NULL) {
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001264 Py_DECREF(trace_obj);
1265 return NULL;
1266 }
Victor Stinnere492ae52016-03-22 12:58:23 +01001267 PyTuple_SET_ITEM(trace_obj, 0, obj);
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001268
Victor Stinnere492ae52016-03-22 12:58:23 +01001269 obj = PyLong_FromSize_t(trace->size);
1270 if (obj == NULL) {
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001271 Py_DECREF(trace_obj);
1272 return NULL;
1273 }
Victor Stinnere492ae52016-03-22 12:58:23 +01001274 PyTuple_SET_ITEM(trace_obj, 1, obj);
1275
1276 obj = traceback_to_pyobject(trace->traceback, intern_tracebacks);
1277 if (obj == NULL) {
1278 Py_DECREF(trace_obj);
1279 return NULL;
1280 }
1281 PyTuple_SET_ITEM(trace_obj, 2, obj);
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001282
1283 return trace_obj;
1284}
1285
Victor Stinnere492ae52016-03-22 12:58:23 +01001286
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001287typedef struct {
1288 _Py_hashtable_t *traces;
1289 _Py_hashtable_t *tracebacks;
1290 PyObject *list;
1291} get_traces_t;
1292
1293static int
Victor Stinner285cf0a2016-03-21 22:00:58 +01001294tracemalloc_get_traces_fill(_Py_hashtable_t *traces, _Py_hashtable_entry_t *entry,
1295 void *user_data)
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001296{
1297 get_traces_t *get_traces = user_data;
Victor Stinner5ea4c062017-06-20 17:46:36 +02001298 unsigned int domain;
Victor Stinner5dacbd42016-03-23 09:52:13 +01001299 trace_t trace;
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001300 PyObject *tracemalloc_obj;
1301 int res;
1302
Victor Stinnere492ae52016-03-22 12:58:23 +01001303 if (tracemalloc_config.use_domain) {
1304 pointer_t key;
Victor Stinner5dacbd42016-03-23 09:52:13 +01001305 _Py_HASHTABLE_ENTRY_READ_KEY(traces, entry, key);
Victor Stinnere492ae52016-03-22 12:58:23 +01001306 domain = key.domain;
1307 }
1308 else {
1309 domain = DEFAULT_DOMAIN;
1310 }
Victor Stinner5dacbd42016-03-23 09:52:13 +01001311 _Py_HASHTABLE_ENTRY_READ_DATA(traces, entry, trace);
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001312
Victor Stinner5dacbd42016-03-23 09:52:13 +01001313 tracemalloc_obj = trace_to_pyobject(domain, &trace, get_traces->tracebacks);
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001314 if (tracemalloc_obj == NULL)
1315 return 1;
1316
1317 res = PyList_Append(get_traces->list, tracemalloc_obj);
1318 Py_DECREF(tracemalloc_obj);
1319 if (res < 0)
1320 return 1;
1321
1322 return 0;
1323}
1324
Victor Stinnere492ae52016-03-22 12:58:23 +01001325
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001326static int
Victor Stinner285cf0a2016-03-21 22:00:58 +01001327tracemalloc_pyobject_decref_cb(_Py_hashtable_t *tracebacks,
1328 _Py_hashtable_entry_t *entry,
1329 void *user_data)
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001330{
Victor Stinnerc9553872016-03-22 12:13:01 +01001331 PyObject *obj;
Victor Stinnere8c6b2f2016-03-23 09:25:01 +01001332 _Py_HASHTABLE_ENTRY_READ_DATA(tracebacks, entry, obj);
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001333 Py_DECREF(obj);
1334 return 0;
1335}
1336
Victor Stinnere492ae52016-03-22 12:58:23 +01001337
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001338
Serhiy Storchakab451f912017-02-04 12:18:38 +02001339/*[clinic input]
1340_tracemalloc._get_traces
1341
1342Get traces of all memory blocks allocated by Python.
1343
1344Return a list of (size: int, traceback: tuple) tuples.
1345traceback is a tuple of (filename: str, lineno: int) tuples.
1346
1347Return an empty list if the tracemalloc module is disabled.
1348[clinic start generated code]*/
1349
1350static PyObject *
1351_tracemalloc__get_traces_impl(PyObject *module)
1352/*[clinic end generated code: output=e9929876ced4b5cc input=6c7d2230b24255aa]*/
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001353{
1354 get_traces_t get_traces;
1355 int err;
1356
1357 get_traces.traces = NULL;
1358 get_traces.tracebacks = NULL;
1359 get_traces.list = PyList_New(0);
1360 if (get_traces.list == NULL)
1361 goto error;
1362
1363 if (!tracemalloc_config.tracing)
1364 return get_traces.list;
1365
Victor Stinnerde2f1322013-11-26 00:26:23 +01001366 /* the traceback hash table is used temporarily to intern traceback tuple
1367 of (filename, lineno) tuples */
Victor Stinnerc9553872016-03-22 12:13:01 +01001368 get_traces.tracebacks = hashtable_new(sizeof(traceback_t *),
1369 sizeof(PyObject *),
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001370 _Py_hashtable_hash_ptr,
1371 _Py_hashtable_compare_direct);
1372 if (get_traces.tracebacks == NULL) {
1373 PyErr_NoMemory();
1374 goto error;
1375 }
1376
1377 TABLES_LOCK();
1378 get_traces.traces = _Py_hashtable_copy(tracemalloc_traces);
1379 TABLES_UNLOCK();
1380
1381 if (get_traces.traces == NULL) {
1382 PyErr_NoMemory();
1383 goto error;
1384 }
1385
1386 set_reentrant(1);
1387 err = _Py_hashtable_foreach(get_traces.traces,
1388 tracemalloc_get_traces_fill, &get_traces);
1389 set_reentrant(0);
1390 if (err)
1391 goto error;
1392
1393 goto finally;
1394
1395error:
1396 Py_CLEAR(get_traces.list);
1397
1398finally:
1399 if (get_traces.tracebacks != NULL) {
1400 _Py_hashtable_foreach(get_traces.tracebacks,
Victor Stinner285cf0a2016-03-21 22:00:58 +01001401 tracemalloc_pyobject_decref_cb, NULL);
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001402 _Py_hashtable_destroy(get_traces.tracebacks);
1403 }
Victor Stinnerc9553872016-03-22 12:13:01 +01001404 if (get_traces.traces != NULL) {
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001405 _Py_hashtable_destroy(get_traces.traces);
Victor Stinnerc9553872016-03-22 12:13:01 +01001406 }
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001407
1408 return get_traces.list;
1409}
1410
Victor Stinnere492ae52016-03-22 12:58:23 +01001411
Victor Stinner0611c262016-03-15 22:22:13 +01001412static traceback_t*
Victor Stinner5ea4c062017-06-20 17:46:36 +02001413tracemalloc_get_traceback(unsigned int domain, uintptr_t ptr)
Victor Stinner0611c262016-03-15 22:22:13 +01001414{
1415 trace_t trace;
1416 int found;
1417
1418 if (!tracemalloc_config.tracing)
1419 return NULL;
1420
1421 TABLES_LOCK();
Victor Stinnere492ae52016-03-22 12:58:23 +01001422 if (tracemalloc_config.use_domain) {
Victor Stinner10b73e12016-03-22 13:39:05 +01001423 pointer_t key = {ptr, domain};
Victor Stinnere492ae52016-03-22 12:58:23 +01001424 found = _Py_HASHTABLE_GET(tracemalloc_traces, key, trace);
1425 }
1426 else {
1427 found = _Py_HASHTABLE_GET(tracemalloc_traces, ptr, trace);
1428 }
Victor Stinner0611c262016-03-15 22:22:13 +01001429 TABLES_UNLOCK();
1430
1431 if (!found)
1432 return NULL;
1433
1434 return trace.traceback;
1435}
1436
Victor Stinnere492ae52016-03-22 12:58:23 +01001437
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001438
Serhiy Storchakab451f912017-02-04 12:18:38 +02001439/*[clinic input]
1440_tracemalloc._get_object_traceback
1441
1442 obj: object
1443 /
1444
1445Get the traceback where the Python object obj was allocated.
1446
1447Return a tuple of (filename: str, lineno: int) tuples.
1448Return None if the tracemalloc module is disabled or did not
1449trace the allocation of the object.
1450[clinic start generated code]*/
1451
1452static PyObject *
1453_tracemalloc__get_object_traceback(PyObject *module, PyObject *obj)
1454/*[clinic end generated code: output=41ee0553a658b0aa input=29495f1b21c53212]*/
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001455{
1456 PyTypeObject *type;
1457 void *ptr;
Victor Stinner0611c262016-03-15 22:22:13 +01001458 traceback_t *traceback;
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001459
1460 type = Py_TYPE(obj);
1461 if (PyType_IS_GC(type))
1462 ptr = (void *)((char *)obj - sizeof(PyGC_Head));
1463 else
1464 ptr = (void *)obj;
1465
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
Benjamin Petersonca470632016-09-06 13:47:26 -07001494 traceback = tracemalloc_get_traceback(DEFAULT_DOMAIN, (uintptr_t)ptr);
Victor Stinner0611c262016-03-15 22:22:13 +01001495 if (traceback == NULL)
1496 return;
1497
1498 PUTS(fd, "Memory block allocated at (most recent call first):\n");
1499 for (i=0; i < traceback->nframe; i++) {
1500 _PyMem_DumpFrame(fd, &traceback->frames[i]);
1501 }
1502 PUTS(fd, "\n");
1503}
1504
1505#undef PUTS
1506
Victor Stinnere492ae52016-03-22 12:58:23 +01001507
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001508
Serhiy Storchakab451f912017-02-04 12:18:38 +02001509/*[clinic input]
1510_tracemalloc.start
1511
1512 nframe: Py_ssize_t = 1
1513 /
1514
1515Start tracing Python memory allocations.
1516
1517Also set the maximum number of frames stored in the traceback of a
1518trace to nframe.
1519[clinic start generated code]*/
1520
1521static PyObject *
1522_tracemalloc_start_impl(PyObject *module, Py_ssize_t nframe)
1523/*[clinic end generated code: output=0f558d2079511553 input=997841629cc441cb]*/
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001524{
Victor Stinnerf28ce602013-11-27 22:27:13 +01001525 int nframe_int;
Victor Stinner3728d6c2013-11-23 12:37:20 +01001526
Victor Stinner52aee852014-08-16 15:44:02 +02001527 if (nframe < 1 || nframe > MAX_NFRAME) {
Victor Stinner3728d6c2013-11-23 12:37:20 +01001528 PyErr_Format(PyExc_ValueError,
1529 "the number of frames must be in range [1; %i]",
Serhiy Storchakab451f912017-02-04 12:18:38 +02001530 (int)MAX_NFRAME);
Victor Stinner3728d6c2013-11-23 12:37:20 +01001531 return NULL;
1532 }
Victor Stinnerf28ce602013-11-27 22:27:13 +01001533 nframe_int = Py_SAFE_DOWNCAST(nframe, Py_ssize_t, int);
Victor Stinner3728d6c2013-11-23 12:37:20 +01001534
Victor Stinnerf9a71152016-03-22 23:54:42 +01001535 if (tracemalloc_start(nframe_int) < 0)
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001536 return NULL;
1537
1538 Py_RETURN_NONE;
1539}
1540
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001541
Serhiy Storchakab451f912017-02-04 12:18:38 +02001542/*[clinic input]
1543_tracemalloc.stop
Victor Stinnere492ae52016-03-22 12:58:23 +01001544
Serhiy Storchakab451f912017-02-04 12:18:38 +02001545Stop tracing Python memory allocations.
1546
1547Also clear traces of memory blocks allocated by Python.
1548[clinic start generated code]*/
1549
1550static PyObject *
1551_tracemalloc_stop_impl(PyObject *module)
1552/*[clinic end generated code: output=c3c42ae03e3955cd input=7478f075e51dae18]*/
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001553{
1554 tracemalloc_stop();
1555 Py_RETURN_NONE;
1556}
1557
Victor Stinnere492ae52016-03-22 12:58:23 +01001558
Serhiy Storchakab451f912017-02-04 12:18:38 +02001559/*[clinic input]
1560_tracemalloc.get_traceback_limit
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001561
Serhiy Storchakab451f912017-02-04 12:18:38 +02001562Get the maximum number of frames stored in the traceback of a trace.
1563
1564By default, a trace of an allocated memory block only stores
1565the most recent frame: the limit is 1.
1566[clinic start generated code]*/
1567
1568static PyObject *
1569_tracemalloc_get_traceback_limit_impl(PyObject *module)
1570/*[clinic end generated code: output=d556d9306ba95567 input=da3cd977fc68ae3b]*/
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001571{
1572 return PyLong_FromLong(tracemalloc_config.max_nframe);
1573}
1574
Victor Stinnere492ae52016-03-22 12:58:23 +01001575
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001576
Serhiy Storchakab451f912017-02-04 12:18:38 +02001577/*[clinic input]
1578_tracemalloc.get_tracemalloc_memory
1579
1580Get the memory usage in bytes of the tracemalloc module.
1581
1582This memory is used internally to trace memory allocations.
1583[clinic start generated code]*/
1584
1585static PyObject *
1586_tracemalloc_get_tracemalloc_memory_impl(PyObject *module)
1587/*[clinic end generated code: output=e3f14e280a55f5aa input=5d919c0f4d5132ad]*/
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001588{
1589 size_t size;
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001590
1591 size = _Py_hashtable_size(tracemalloc_tracebacks);
1592 size += _Py_hashtable_size(tracemalloc_filenames);
1593
1594 TABLES_LOCK();
1595 size += _Py_hashtable_size(tracemalloc_traces);
1596 TABLES_UNLOCK();
1597
Serhiy Storchakab451f912017-02-04 12:18:38 +02001598 return PyLong_FromSize_t(size);
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001599}
1600
Victor Stinnere492ae52016-03-22 12:58:23 +01001601
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001602
Serhiy Storchakab451f912017-02-04 12:18:38 +02001603/*[clinic input]
1604_tracemalloc.get_traced_memory
1605
1606Get the current size and peak size of memory blocks traced by tracemalloc.
1607
1608Returns a tuple: (current: int, peak: int).
1609[clinic start generated code]*/
1610
1611static PyObject *
1612_tracemalloc_get_traced_memory_impl(PyObject *module)
1613/*[clinic end generated code: output=5b167189adb9e782 input=61ddb5478400ff66]*/
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001614{
Victor Stinner3c0481d2013-11-27 21:39:49 +01001615 Py_ssize_t size, peak_size;
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001616
1617 if (!tracemalloc_config.tracing)
1618 return Py_BuildValue("ii", 0, 0);
1619
1620 TABLES_LOCK();
1621 size = tracemalloc_traced_memory;
Victor Stinner3c0481d2013-11-27 21:39:49 +01001622 peak_size = tracemalloc_peak_traced_memory;
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001623 TABLES_UNLOCK();
1624
Serhiy Storchakab451f912017-02-04 12:18:38 +02001625 return Py_BuildValue("nn", size, peak_size);
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001626}
1627
Victor Stinnere492ae52016-03-22 12:58:23 +01001628
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001629static PyMethodDef module_methods[] = {
Serhiy Storchakab451f912017-02-04 12:18:38 +02001630 _TRACEMALLOC_IS_TRACING_METHODDEF
1631 _TRACEMALLOC_CLEAR_TRACES_METHODDEF
1632 _TRACEMALLOC__GET_TRACES_METHODDEF
1633 _TRACEMALLOC__GET_OBJECT_TRACEBACK_METHODDEF
1634 _TRACEMALLOC_START_METHODDEF
1635 _TRACEMALLOC_STOP_METHODDEF
1636 _TRACEMALLOC_GET_TRACEBACK_LIMIT_METHODDEF
1637 _TRACEMALLOC_GET_TRACEMALLOC_MEMORY_METHODDEF
1638 _TRACEMALLOC_GET_TRACED_MEMORY_METHODDEF
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001639 /* sentinel */
1640 {NULL, NULL}
1641};
1642
1643PyDoc_STRVAR(module_doc,
1644"Debug module to trace memory blocks allocated by Python.");
1645
1646static struct PyModuleDef module_def = {
1647 PyModuleDef_HEAD_INIT,
1648 "_tracemalloc",
1649 module_doc,
1650 0, /* non-negative size to be able to unload the module */
1651 module_methods,
1652 NULL,
1653};
1654
1655PyMODINIT_FUNC
1656PyInit__tracemalloc(void)
1657{
1658 PyObject *m;
1659 m = PyModule_Create(&module_def);
1660 if (m == NULL)
1661 return NULL;
1662
1663 if (tracemalloc_init() < 0)
1664 return NULL;
1665
1666 return m;
1667}
1668
Victor Stinnere492ae52016-03-22 12:58:23 +01001669
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001670static int
1671parse_sys_xoptions(PyObject *value)
1672{
1673 PyObject *valuelong;
1674 long nframe;
1675
1676 if (value == Py_True)
1677 return 1;
1678
1679 assert(PyUnicode_Check(value));
1680 if (PyUnicode_GetLength(value) == 0)
1681 return -1;
1682
1683 valuelong = PyLong_FromUnicodeObject(value, 10);
1684 if (valuelong == NULL)
1685 return -1;
1686
1687 nframe = PyLong_AsLong(valuelong);
1688 Py_DECREF(valuelong);
1689 if (nframe == -1 && PyErr_Occurred())
1690 return -1;
1691
Victor Stinner52aee852014-08-16 15:44:02 +02001692 if (nframe < 1 || nframe > MAX_NFRAME)
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001693 return -1;
1694
1695 return Py_SAFE_DOWNCAST(nframe, long, int);
1696}
1697
Victor Stinnere492ae52016-03-22 12:58:23 +01001698
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001699int
1700_PyTraceMalloc_Init(void)
1701{
1702 char *p;
1703 int nframe;
1704
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001705 assert(PyGILState_Check());
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001706
1707 if ((p = Py_GETENV("PYTHONTRACEMALLOC")) && *p != '\0') {
1708 char *endptr = p;
Victor Stinnerf28ce602013-11-27 22:27:13 +01001709 long value;
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001710
Victor Stinner711e27c2013-12-16 23:06:19 +01001711 errno = 0;
Victor Stinnerf28ce602013-11-27 22:27:13 +01001712 value = strtol(p, &endptr, 10);
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001713 if (*endptr != '\0'
1714 || value < 1
Victor Stinner52aee852014-08-16 15:44:02 +02001715 || value > MAX_NFRAME
Victor Stinner711e27c2013-12-16 23:06:19 +01001716 || errno == ERANGE)
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001717 {
Victor Stinnerf28ce602013-11-27 22:27:13 +01001718 Py_FatalError("PYTHONTRACEMALLOC: invalid number of frames");
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001719 return -1;
1720 }
1721
1722 nframe = (int)value;
1723 }
1724 else {
1725 PyObject *xoptions, *key, *value;
1726
1727 xoptions = PySys_GetXOptions();
1728 if (xoptions == NULL)
1729 return -1;
1730
1731 key = PyUnicode_FromString("tracemalloc");
1732 if (key == NULL)
1733 return -1;
1734
Xiang Zhang4ed5ad72017-07-19 00:33:29 +08001735 value = PyDict_GetItemWithError(xoptions, key); /* borrowed */
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001736 Py_DECREF(key);
1737 if (value == NULL) {
1738 if (PyErr_Occurred())
1739 return -1;
1740
1741 /* -X tracemalloc is not used */
1742 return 0;
1743 }
1744
1745 nframe = parse_sys_xoptions(value);
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001746 if (nframe < 0) {
Victor Stinnerf28ce602013-11-27 22:27:13 +01001747 Py_FatalError("-X tracemalloc=NFRAME: invalid number of frames");
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001748 }
1749 }
1750
Victor Stinnerf28ce602013-11-27 22:27:13 +01001751 return tracemalloc_start(nframe);
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001752}
1753
Victor Stinnere492ae52016-03-22 12:58:23 +01001754
Victor Stinnerbe0708f2013-12-01 10:03:26 +01001755void
1756_PyTraceMalloc_Fini(void)
1757{
Victor Stinnerbe0708f2013-12-01 10:03:26 +01001758 assert(PyGILState_Check());
Victor Stinnerbe0708f2013-12-01 10:03:26 +01001759 tracemalloc_deinit();
1760}
Victor Stinner10b73e12016-03-22 13:39:05 +01001761
1762int
Victor Stinner5ea4c062017-06-20 17:46:36 +02001763PyTraceMalloc_Track(unsigned int domain, uintptr_t ptr,
1764 size_t size)
Victor Stinner10b73e12016-03-22 13:39:05 +01001765{
1766 int res;
Victor Stinner10b73e12016-03-22 13:39:05 +01001767 PyGILState_STATE gil_state;
Victor Stinner10b73e12016-03-22 13:39:05 +01001768
1769 if (!tracemalloc_config.tracing) {
1770 /* tracemalloc is not tracing: do nothing */
1771 return -2;
1772 }
1773
Victor Stinner10b73e12016-03-22 13:39:05 +01001774 gil_state = PyGILState_Ensure();
Victor Stinner10b73e12016-03-22 13:39:05 +01001775
1776 TABLES_LOCK();
1777 res = tracemalloc_add_trace(domain, ptr, size);
1778 TABLES_UNLOCK();
1779
Victor Stinner10b73e12016-03-22 13:39:05 +01001780 PyGILState_Release(gil_state);
Victor Stinner10b73e12016-03-22 13:39:05 +01001781 return res;
1782}
1783
1784
1785int
Victor Stinner5ea4c062017-06-20 17:46:36 +02001786PyTraceMalloc_Untrack(unsigned int domain, uintptr_t ptr)
Victor Stinner10b73e12016-03-22 13:39:05 +01001787{
1788 if (!tracemalloc_config.tracing) {
1789 /* tracemalloc is not tracing: do nothing */
1790 return -2;
1791 }
1792
1793 TABLES_LOCK();
1794 tracemalloc_remove_trace(domain, ptr);
1795 TABLES_UNLOCK();
1796
1797 return 0;
1798}
1799
1800
1801PyObject*
Victor Stinner5ea4c062017-06-20 17:46:36 +02001802_PyTraceMalloc_GetTraceback(unsigned int domain, uintptr_t ptr)
Victor Stinner10b73e12016-03-22 13:39:05 +01001803{
1804 traceback_t *traceback;
1805
1806 traceback = tracemalloc_get_traceback(domain, ptr);
1807 if (traceback == NULL)
1808 Py_RETURN_NONE;
1809
1810 return traceback_to_pyobject(traceback, NULL);
1811}