blob: 00d354240907dc35cdd77c0b9855679636a5e0a0 [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
54#if defined(TRACE_RAW_MALLOC) && defined(WITH_THREAD)
55/* 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)
86_declspec(align(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;
94
Victor Stinnere492ae52016-03-22 12:58:23 +010095
Victor Stinnered3b0bc2013-11-23 12:27:24 +010096typedef struct {
97 Py_uhash_t hash;
98 int nframe;
99 frame_t frames[1];
100} traceback_t;
101
102#define TRACEBACK_SIZE(NFRAME) \
103 (sizeof(traceback_t) + sizeof(frame_t) * (NFRAME - 1))
Victor Stinnerf28ce602013-11-27 22:27:13 +0100104
105#define MAX_NFRAME \
Victor Stinner52aee852014-08-16 15:44:02 +0200106 ((INT_MAX - (int)sizeof(traceback_t)) / (int)sizeof(frame_t) + 1)
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100107
Victor Stinnere492ae52016-03-22 12:58:23 +0100108
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100109static PyObject *unknown_filename = NULL;
110static traceback_t tracemalloc_empty_traceback;
111
Victor Stinner7a5be142013-11-26 01:06:02 +0100112/* Trace of a memory block */
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100113typedef struct {
Victor Stinner7a5be142013-11-26 01:06:02 +0100114 /* Size of the memory block in bytes */
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100115 size_t size;
Victor Stinner7a5be142013-11-26 01:06:02 +0100116
117 /* Traceback where the memory block was allocated */
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100118 traceback_t *traceback;
119} trace_t;
120
Victor Stinnere492ae52016-03-22 12:58:23 +0100121
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100122/* Size in bytes of currently traced memory.
123 Protected by TABLES_LOCK(). */
124static size_t tracemalloc_traced_memory = 0;
125
Victor Stinner3c0481d2013-11-27 21:39:49 +0100126/* Peak size in bytes of traced memory.
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100127 Protected by TABLES_LOCK(). */
Victor Stinner3c0481d2013-11-27 21:39:49 +0100128static size_t tracemalloc_peak_traced_memory = 0;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100129
Serhiy Storchaka56a6d852014-12-01 18:28:43 +0200130/* Hash table used as a set to intern filenames:
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100131 PyObject* => PyObject*.
132 Protected by the GIL */
133static _Py_hashtable_t *tracemalloc_filenames = NULL;
134
Victor Stinnerf28ce602013-11-27 22:27:13 +0100135/* Buffer to store a new traceback in traceback_new().
136 Protected by the GIL. */
137static traceback_t *tracemalloc_traceback = NULL;
138
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100139/* Hash table used as a set to intern tracebacks:
140 traceback_t* => traceback_t*
141 Protected by the GIL */
142static _Py_hashtable_t *tracemalloc_tracebacks = NULL;
143
144/* pointer (void*) => trace (trace_t).
145 Protected by TABLES_LOCK(). */
146static _Py_hashtable_t *tracemalloc_traces = NULL;
147
Victor Stinnere492ae52016-03-22 12:58:23 +0100148
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100149#ifdef TRACE_DEBUG
150static void
151tracemalloc_error(const char *format, ...)
152{
153 va_list ap;
154 fprintf(stderr, "tracemalloc: ");
155 va_start(ap, format);
156 vfprintf(stderr, format, ap);
157 va_end(ap);
158 fprintf(stderr, "\n");
159 fflush(stderr);
160}
161#endif
162
Victor Stinnere492ae52016-03-22 12:58:23 +0100163
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100164#if defined(WITH_THREAD) && defined(TRACE_RAW_MALLOC)
165#define REENTRANT_THREADLOCAL
166
167/* If your OS does not provide native thread local storage, you can implement
168 it manually using a lock. Functions of thread.c cannot be used because
169 they use PyMem_RawMalloc() which leads to a reentrant call. */
170#if !(defined(_POSIX_THREADS) || defined(NT_THREADS))
171# error "need native thread local storage (TLS)"
172#endif
173
Victor Stinner4a066472016-03-22 17:45:09 +0100174static int tracemalloc_reentrant_key = -1;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100175
176/* Any non-NULL pointer can be used */
177#define REENTRANT Py_True
178
179static int
180get_reentrant(void)
181{
Victor Stinner4a066472016-03-22 17:45:09 +0100182 void *ptr;
183
184 assert(tracemalloc_reentrant_key != -1);
185 ptr = PyThread_get_key_value(tracemalloc_reentrant_key);
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100186 if (ptr != NULL) {
187 assert(ptr == REENTRANT);
188 return 1;
189 }
190 else
191 return 0;
192}
193
194static void
195set_reentrant(int reentrant)
196{
Victor Stinner2ead3d22013-11-26 01:08:53 +0100197 assert(reentrant == 0 || reentrant == 1);
Victor Stinner4a066472016-03-22 17:45:09 +0100198 assert(tracemalloc_reentrant_key != -1);
199
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100200 if (reentrant) {
Victor Stinner0cfc0582016-03-22 17:40:07 +0100201 assert(!get_reentrant());
Victor Stinner590cebe2013-12-13 11:08:56 +0100202 PyThread_set_key_value(tracemalloc_reentrant_key, REENTRANT);
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100203 }
204 else {
Victor Stinner0cfc0582016-03-22 17:40:07 +0100205 assert(get_reentrant());
Victor Stinner590cebe2013-12-13 11:08:56 +0100206 PyThread_set_key_value(tracemalloc_reentrant_key, NULL);
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100207 }
208}
209
210#else
211
212/* WITH_THREAD not defined: Python compiled without threads,
213 or TRACE_RAW_MALLOC not defined: variable protected by the GIL */
214static int tracemalloc_reentrant = 0;
215
216static int
217get_reentrant(void)
218{
219 return tracemalloc_reentrant;
220}
221
222static void
223set_reentrant(int reentrant)
224{
Victor Stinnerd5871e62016-03-23 00:17:04 +0100225 assert(reentrant != tracemalloc_reentrant);
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100226 tracemalloc_reentrant = reentrant;
227}
228#endif
229
Victor Stinnere492ae52016-03-22 12:58:23 +0100230
Victor Stinner285cf0a2016-03-21 22:00:58 +0100231static Py_uhash_t
Victor Stinner5dacbd42016-03-23 09:52:13 +0100232hashtable_hash_pyobject(_Py_hashtable_t *ht, const void *pkey)
Victor Stinner51b846c2016-03-18 21:52:22 +0100233{
Victor Stinner285cf0a2016-03-21 22:00:58 +0100234 PyObject *obj;
235
Victor Stinner5dacbd42016-03-23 09:52:13 +0100236 _Py_HASHTABLE_READ_KEY(ht, pkey, obj);
Victor Stinner285cf0a2016-03-21 22:00:58 +0100237 return PyObject_Hash(obj);
238}
239
Victor Stinnere492ae52016-03-22 12:58:23 +0100240
Victor Stinner285cf0a2016-03-21 22:00:58 +0100241static int
Victor Stinner5dacbd42016-03-23 09:52:13 +0100242hashtable_compare_unicode(_Py_hashtable_t *ht, const void *pkey,
Victor Stinner285cf0a2016-03-21 22:00:58 +0100243 const _Py_hashtable_entry_t *entry)
244{
Victor Stinnere492ae52016-03-22 12:58:23 +0100245 PyObject *key1, *key2;
Victor Stinner285cf0a2016-03-21 22:00:58 +0100246
Victor Stinner5dacbd42016-03-23 09:52:13 +0100247 _Py_HASHTABLE_READ_KEY(ht, pkey, key1);
248 _Py_HASHTABLE_ENTRY_READ_KEY(ht, entry, key2);
Victor Stinner285cf0a2016-03-21 22:00:58 +0100249
Victor Stinnere492ae52016-03-22 12:58:23 +0100250 if (key1 != NULL && key2 != NULL)
251 return (PyUnicode_Compare(key1, key2) == 0);
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100252 else
Victor Stinnere492ae52016-03-22 12:58:23 +0100253 return key1 == key2;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100254}
255
Victor Stinnere492ae52016-03-22 12:58:23 +0100256
257static Py_uhash_t
Victor Stinner5dacbd42016-03-23 09:52:13 +0100258hashtable_hash_pointer_t(_Py_hashtable_t *ht, const void *pkey)
Victor Stinnere492ae52016-03-22 12:58:23 +0100259{
260 pointer_t ptr;
261 Py_uhash_t hash;
262
Victor Stinner5dacbd42016-03-23 09:52:13 +0100263 _Py_HASHTABLE_READ_KEY(ht, pkey, ptr);
Victor Stinnere492ae52016-03-22 12:58:23 +0100264
265 hash = (Py_uhash_t)_Py_HashPointer((void*)ptr.ptr);
266 hash ^= ptr.domain;
267 return hash;
268}
269
270
doko@ubuntu.combc731502016-05-18 01:06:01 +0200271static int
Victor Stinner5dacbd42016-03-23 09:52:13 +0100272hashtable_compare_pointer_t(_Py_hashtable_t *ht, const void *pkey,
Victor Stinnere492ae52016-03-22 12:58:23 +0100273 const _Py_hashtable_entry_t *entry)
274{
275 pointer_t ptr1, ptr2;
276
Victor Stinner5dacbd42016-03-23 09:52:13 +0100277 _Py_HASHTABLE_READ_KEY(ht, pkey, ptr1);
278 _Py_HASHTABLE_ENTRY_READ_KEY(ht, entry, ptr2);
Victor Stinnere492ae52016-03-22 12:58:23 +0100279
280 /* compare pointer before domain, because pointer is more likely to be
281 different */
282 return (ptr1.ptr == ptr2.ptr && ptr1.domain == ptr2.domain);
283
284}
285
286
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100287static _Py_hashtable_t *
Victor Stinner285cf0a2016-03-21 22:00:58 +0100288hashtable_new(size_t key_size, size_t data_size,
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100289 _Py_hashtable_hash_func hash_func,
290 _Py_hashtable_compare_func compare_func)
291{
Victor Stinnerc9553872016-03-22 12:13:01 +0100292 _Py_hashtable_allocator_t hashtable_alloc = {malloc, free};
Victor Stinner285cf0a2016-03-21 22:00:58 +0100293 return _Py_hashtable_new_full(key_size, data_size, 0,
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100294 hash_func, compare_func,
Victor Stinnerc9553872016-03-22 12:13:01 +0100295 &hashtable_alloc);
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100296}
297
Victor Stinnere492ae52016-03-22 12:58:23 +0100298
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100299static void*
300raw_malloc(size_t size)
301{
302 return allocators.raw.malloc(allocators.raw.ctx, size);
303}
304
305static void
306raw_free(void *ptr)
307{
308 allocators.raw.free(allocators.raw.ctx, ptr);
309}
310
Victor Stinnere492ae52016-03-22 12:58:23 +0100311
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100312static Py_uhash_t
Victor Stinner5dacbd42016-03-23 09:52:13 +0100313hashtable_hash_traceback(_Py_hashtable_t *ht, const void *pkey)
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100314{
Victor Stinnerb32a7ed2016-03-21 23:05:08 +0100315 traceback_t *traceback;
Victor Stinner285cf0a2016-03-21 22:00:58 +0100316
Victor Stinner5dacbd42016-03-23 09:52:13 +0100317 _Py_HASHTABLE_READ_KEY(ht, pkey, traceback);
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100318 return traceback->hash;
319}
320
Victor Stinnere492ae52016-03-22 12:58:23 +0100321
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100322static int
Victor Stinner5dacbd42016-03-23 09:52:13 +0100323hashtable_compare_traceback(_Py_hashtable_t *ht, const void *pkey,
324 const _Py_hashtable_entry_t *entry)
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100325{
Victor Stinner285cf0a2016-03-21 22:00:58 +0100326 traceback_t *traceback1, *traceback2;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100327 const frame_t *frame1, *frame2;
328 int i;
329
Victor Stinner5dacbd42016-03-23 09:52:13 +0100330 _Py_HASHTABLE_READ_KEY(ht, pkey, traceback1);
331 _Py_HASHTABLE_ENTRY_READ_KEY(ht, entry, traceback2);
Victor Stinner285cf0a2016-03-21 22:00:58 +0100332
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100333 if (traceback1->nframe != traceback2->nframe)
334 return 0;
335
336 for (i=0; i < traceback1->nframe; i++) {
337 frame1 = &traceback1->frames[i];
338 frame2 = &traceback2->frames[i];
339
340 if (frame1->lineno != frame2->lineno)
341 return 0;
342
343 if (frame1->filename != frame2->filename) {
344 assert(PyUnicode_Compare(frame1->filename, frame2->filename) != 0);
345 return 0;
346 }
347 }
348 return 1;
349}
350
Victor Stinnere492ae52016-03-22 12:58:23 +0100351
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100352static void
353tracemalloc_get_frame(PyFrameObject *pyframe, frame_t *frame)
354{
355 PyCodeObject *code;
356 PyObject *filename;
357 _Py_hashtable_entry_t *entry;
Victor Stinner95283342016-03-15 21:57:02 +0100358 int lineno;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100359
360 frame->filename = unknown_filename;
Victor Stinner95283342016-03-15 21:57:02 +0100361 lineno = PyFrame_GetLineNumber(pyframe);
362 if (lineno < 0)
363 lineno = 0;
364 frame->lineno = (unsigned int)lineno;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100365
366 code = pyframe->f_code;
367 if (code == NULL) {
368#ifdef TRACE_DEBUG
Victor Stinner4dc74202013-11-26 01:18:52 +0100369 tracemalloc_error("failed to get the code object of the frame");
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100370#endif
371 return;
372 }
373
374 if (code->co_filename == NULL) {
375#ifdef TRACE_DEBUG
376 tracemalloc_error("failed to get the filename of the code object");
377#endif
378 return;
379 }
380
381 filename = code->co_filename;
382 assert(filename != NULL);
383 if (filename == NULL)
384 return;
385
386 if (!PyUnicode_Check(filename)) {
387#ifdef TRACE_DEBUG
Martin Panter6245cb32016-04-15 02:14:19 +0000388 tracemalloc_error("filename is not a unicode string");
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100389#endif
390 return;
391 }
392 if (!PyUnicode_IS_READY(filename)) {
393 /* Don't make a Unicode string ready to avoid reentrant calls
394 to tracemalloc_malloc() or tracemalloc_realloc() */
395#ifdef TRACE_DEBUG
396 tracemalloc_error("filename is not a ready unicode string");
397#endif
398 return;
399 }
400
401 /* intern the filename */
Victor Stinner285cf0a2016-03-21 22:00:58 +0100402 entry = _Py_HASHTABLE_GET_ENTRY(tracemalloc_filenames, filename);
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100403 if (entry != NULL) {
Victor Stinner5dacbd42016-03-23 09:52:13 +0100404 _Py_HASHTABLE_ENTRY_READ_KEY(tracemalloc_filenames, entry, filename);
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100405 }
406 else {
407 /* tracemalloc_filenames is responsible to keep a reference
408 to the filename */
409 Py_INCREF(filename);
Victor Stinner285cf0a2016-03-21 22:00:58 +0100410 if (_Py_HASHTABLE_SET_NODATA(tracemalloc_filenames, filename) < 0) {
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100411 Py_DECREF(filename);
412#ifdef TRACE_DEBUG
413 tracemalloc_error("failed to intern the filename");
414#endif
415 return;
416 }
417 }
418
419 /* the tracemalloc_filenames table keeps a reference to the filename */
420 frame->filename = filename;
421}
422
Victor Stinnere492ae52016-03-22 12:58:23 +0100423
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100424static Py_uhash_t
425traceback_hash(traceback_t *traceback)
426{
427 /* code based on tuplehash() of Objects/tupleobject.c */
Victor Stinner4d8c29c2013-12-16 23:05:13 +0100428 Py_uhash_t x, y; /* Unsigned for defined overflow behavior. */
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100429 int len = traceback->nframe;
430 Py_uhash_t mult = _PyHASH_MULTIPLIER;
431 frame_t *frame;
432
433 x = 0x345678UL;
434 frame = traceback->frames;
435 while (--len >= 0) {
Victor Stinner4d8c29c2013-12-16 23:05:13 +0100436 y = (Py_uhash_t)PyObject_Hash(frame->filename);
437 y ^= (Py_uhash_t)frame->lineno;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100438 frame++;
439
440 x = (x ^ y) * mult;
441 /* the cast might truncate len; that doesn't change hash stability */
Victor Stinner4d8c29c2013-12-16 23:05:13 +0100442 mult += (Py_uhash_t)(82520UL + len + len);
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100443 }
444 x += 97531UL;
445 return x;
446}
447
Victor Stinnere492ae52016-03-22 12:58:23 +0100448
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100449static void
450traceback_get_frames(traceback_t *traceback)
451{
452 PyThreadState *tstate;
453 PyFrameObject *pyframe;
454
455#ifdef WITH_THREAD
456 tstate = PyGILState_GetThisThreadState();
457#else
458 tstate = PyThreadState_Get();
459#endif
460 if (tstate == NULL) {
461#ifdef TRACE_DEBUG
462 tracemalloc_error("failed to get the current thread state");
463#endif
464 return;
465 }
466
467 for (pyframe = tstate->frame; pyframe != NULL; pyframe = pyframe->f_back) {
468 tracemalloc_get_frame(pyframe, &traceback->frames[traceback->nframe]);
469 assert(traceback->frames[traceback->nframe].filename != NULL);
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100470 traceback->nframe++;
471 if (traceback->nframe == tracemalloc_config.max_nframe)
472 break;
473 }
474}
475
Victor Stinnere492ae52016-03-22 12:58:23 +0100476
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100477static traceback_t *
478traceback_new(void)
479{
Victor Stinnerf28ce602013-11-27 22:27:13 +0100480 traceback_t *traceback;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100481 _Py_hashtable_entry_t *entry;
482
483#ifdef WITH_THREAD
484 assert(PyGILState_Check());
485#endif
486
487 /* get frames */
Victor Stinnerf28ce602013-11-27 22:27:13 +0100488 traceback = tracemalloc_traceback;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100489 traceback->nframe = 0;
490 traceback_get_frames(traceback);
491 if (traceback->nframe == 0)
492 return &tracemalloc_empty_traceback;
493 traceback->hash = traceback_hash(traceback);
494
495 /* intern the traceback */
Victor Stinner285cf0a2016-03-21 22:00:58 +0100496 entry = _Py_HASHTABLE_GET_ENTRY(tracemalloc_tracebacks, traceback);
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100497 if (entry != NULL) {
Victor Stinner5dacbd42016-03-23 09:52:13 +0100498 _Py_HASHTABLE_ENTRY_READ_KEY(tracemalloc_tracebacks, entry, traceback);
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100499 }
500 else {
501 traceback_t *copy;
502 size_t traceback_size;
503
504 traceback_size = TRACEBACK_SIZE(traceback->nframe);
505
506 copy = raw_malloc(traceback_size);
507 if (copy == NULL) {
508#ifdef TRACE_DEBUG
509 tracemalloc_error("failed to intern the traceback: malloc failed");
510#endif
511 return NULL;
512 }
513 memcpy(copy, traceback, traceback_size);
514
Victor Stinner285cf0a2016-03-21 22:00:58 +0100515 if (_Py_HASHTABLE_SET_NODATA(tracemalloc_tracebacks, copy) < 0) {
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100516 raw_free(copy);
517#ifdef TRACE_DEBUG
518 tracemalloc_error("failed to intern the traceback: putdata failed");
519#endif
520 return NULL;
521 }
522 traceback = copy;
523 }
524 return traceback;
525}
526
Victor Stinnere492ae52016-03-22 12:58:23 +0100527
Victor Stinner5e14a382016-03-23 22:03:55 +0100528static int
529tracemalloc_use_domain_cb(_Py_hashtable_t *old_traces,
530 _Py_hashtable_entry_t *entry, void *user_data)
531{
Benjamin Petersonca470632016-09-06 13:47:26 -0700532 uintptr_t ptr;
Victor Stinner5e14a382016-03-23 22:03:55 +0100533 pointer_t key;
534 _Py_hashtable_t *new_traces = (_Py_hashtable_t *)user_data;
535 const void *pdata = _Py_HASHTABLE_ENTRY_PDATA(old_traces, entry);
536
537 _Py_HASHTABLE_ENTRY_READ_KEY(old_traces, entry, ptr);
538 key.ptr = ptr;
539 key.domain = DEFAULT_DOMAIN;
540
541 return _Py_hashtable_set(new_traces,
542 sizeof(key), &key,
543 old_traces->data_size, pdata);
544}
545
546
Benjamin Petersonca470632016-09-06 13:47:26 -0700547/* Convert tracemalloc_traces from compact key (uintptr_t) to pointer_t key.
Victor Stinner5e14a382016-03-23 22:03:55 +0100548 * Return 0 on success, -1 on error. */
549static int
550tracemalloc_use_domain(void)
551{
552 _Py_hashtable_t *new_traces = NULL;
553
554 assert(!tracemalloc_config.use_domain);
555
556 new_traces = hashtable_new(sizeof(pointer_t),
557 sizeof(trace_t),
558 hashtable_hash_pointer_t,
559 hashtable_compare_pointer_t);
560 if (new_traces == NULL) {
561 return -1;
562 }
563
564 if (_Py_hashtable_foreach(tracemalloc_traces, tracemalloc_use_domain_cb,
565 new_traces) < 0)
566 {
567 _Py_hashtable_destroy(new_traces);
568 return -1;
569 }
570
571 _Py_hashtable_destroy(tracemalloc_traces);
572 tracemalloc_traces = new_traces;
573
574 tracemalloc_config.use_domain = 1;
575
576 return 0;
577}
578
579
Victor Stinnere492ae52016-03-22 12:58:23 +0100580static void
Victor Stinner5ea4c062017-06-20 17:46:36 +0200581tracemalloc_remove_trace(unsigned int domain, uintptr_t ptr)
Victor Stinnere492ae52016-03-22 12:58:23 +0100582{
583 trace_t trace;
584 int removed;
585
Victor Stinner10b73e12016-03-22 13:39:05 +0100586 assert(tracemalloc_config.tracing);
587
Victor Stinnere492ae52016-03-22 12:58:23 +0100588 if (tracemalloc_config.use_domain) {
589 pointer_t key = {ptr, domain};
590 removed = _Py_HASHTABLE_POP(tracemalloc_traces, key, trace);
591 }
592 else {
593 removed = _Py_HASHTABLE_POP(tracemalloc_traces, ptr, trace);
594 }
595 if (!removed) {
596 return;
597 }
598
599 assert(tracemalloc_traced_memory >= trace.size);
600 tracemalloc_traced_memory -= trace.size;
601}
602
603#define REMOVE_TRACE(ptr) \
Benjamin Petersonca470632016-09-06 13:47:26 -0700604 tracemalloc_remove_trace(DEFAULT_DOMAIN, (uintptr_t)(ptr))
Victor Stinnere492ae52016-03-22 12:58:23 +0100605
606
Victor Stinner52968672013-11-24 11:37:15 +0100607static int
Victor Stinner5ea4c062017-06-20 17:46:36 +0200608tracemalloc_add_trace(unsigned int domain, uintptr_t ptr,
Victor Stinner10b73e12016-03-22 13:39:05 +0100609 size_t size)
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100610{
Victor Stinnerca79ccd2016-03-23 09:38:54 +0100611 pointer_t key = {ptr, domain};
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100612 traceback_t *traceback;
613 trace_t trace;
Victor Stinnerca79ccd2016-03-23 09:38:54 +0100614 _Py_hashtable_entry_t* entry;
Victor Stinner52968672013-11-24 11:37:15 +0100615 int res;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100616
Victor Stinner10b73e12016-03-22 13:39:05 +0100617 assert(tracemalloc_config.tracing);
618
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100619 traceback = traceback_new();
Victor Stinnere492ae52016-03-22 12:58:23 +0100620 if (traceback == NULL) {
Victor Stinner52968672013-11-24 11:37:15 +0100621 return -1;
Victor Stinnere492ae52016-03-22 12:58:23 +0100622 }
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100623
Victor Stinner5e14a382016-03-23 22:03:55 +0100624 if (!tracemalloc_config.use_domain && domain != DEFAULT_DOMAIN) {
625 /* first trace using a non-zero domain whereas traces use compact
Benjamin Petersonca470632016-09-06 13:47:26 -0700626 (uintptr_t) keys: switch to pointer_t keys. */
Victor Stinner5e14a382016-03-23 22:03:55 +0100627 if (tracemalloc_use_domain() < 0) {
628 return -1;
629 }
630 }
631
Victor Stinnere492ae52016-03-22 12:58:23 +0100632 if (tracemalloc_config.use_domain) {
Victor Stinnerca79ccd2016-03-23 09:38:54 +0100633 entry = _Py_HASHTABLE_GET_ENTRY(tracemalloc_traces, key);
Victor Stinnere492ae52016-03-22 12:58:23 +0100634 }
635 else {
Victor Stinnerca79ccd2016-03-23 09:38:54 +0100636 entry = _Py_HASHTABLE_GET_ENTRY(tracemalloc_traces, ptr);
Victor Stinnerd606ba72013-11-24 11:28:20 +0100637 }
Victor Stinner52968672013-11-24 11:37:15 +0100638
Victor Stinnerca79ccd2016-03-23 09:38:54 +0100639 if (entry != NULL) {
640 /* the memory block is already tracked */
641 _Py_HASHTABLE_ENTRY_READ_DATA(tracemalloc_traces, entry, trace);
642 assert(tracemalloc_traced_memory >= trace.size);
643 tracemalloc_traced_memory -= trace.size;
644
645 trace.size = size;
646 trace.traceback = traceback;
647 _Py_HASHTABLE_ENTRY_WRITE_DATA(tracemalloc_traces, entry, trace);
648 }
649 else {
650 trace.size = size;
651 trace.traceback = traceback;
652
653 if (tracemalloc_config.use_domain) {
654 res = _Py_HASHTABLE_SET(tracemalloc_traces, key, trace);
655 }
656 else {
657 res = _Py_HASHTABLE_SET(tracemalloc_traces, ptr, trace);
658 }
659 if (res != 0) {
660 return res;
661 }
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100662 }
Victor Stinnere492ae52016-03-22 12:58:23 +0100663
Benjamin Peterson2f8bfef2016-09-07 09:26:18 -0700664 assert(tracemalloc_traced_memory <= SIZE_MAX - size);
Victor Stinnere492ae52016-03-22 12:58:23 +0100665 tracemalloc_traced_memory += size;
666 if (tracemalloc_traced_memory > tracemalloc_peak_traced_memory)
667 tracemalloc_peak_traced_memory = tracemalloc_traced_memory;
668 return 0;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100669}
670
Victor Stinnere492ae52016-03-22 12:58:23 +0100671#define ADD_TRACE(ptr, size) \
Benjamin Petersonca470632016-09-06 13:47:26 -0700672 tracemalloc_add_trace(DEFAULT_DOMAIN, (uintptr_t)(ptr), size)
Victor Stinnere492ae52016-03-22 12:58:23 +0100673
674
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100675static void*
Victor Stinnerdb067af2014-05-02 22:31:14 +0200676tracemalloc_alloc(int use_calloc, void *ctx, size_t nelem, size_t elsize)
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100677{
Victor Stinnerd8f0d922014-06-02 21:57:10 +0200678 PyMemAllocatorEx *alloc = (PyMemAllocatorEx *)ctx;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100679 void *ptr;
680
Benjamin Peterson2f8bfef2016-09-07 09:26:18 -0700681 assert(elsize == 0 || nelem <= SIZE_MAX / elsize);
Victor Stinnerdb067af2014-05-02 22:31:14 +0200682
683 if (use_calloc)
684 ptr = alloc->calloc(alloc->ctx, nelem, elsize);
685 else
686 ptr = alloc->malloc(alloc->ctx, nelem * elsize);
Victor Stinner15116802013-12-04 01:29:35 +0100687 if (ptr == NULL)
688 return NULL;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100689
Victor Stinner88c29872013-12-04 01:47:46 +0100690 TABLES_LOCK();
Victor Stinnere492ae52016-03-22 12:58:23 +0100691 if (ADD_TRACE(ptr, nelem * elsize) < 0) {
Victor Stinner15116802013-12-04 01:29:35 +0100692 /* Failed to allocate a trace for the new memory block */
Victor Stinner88c29872013-12-04 01:47:46 +0100693 TABLES_UNLOCK();
Victor Stinner15116802013-12-04 01:29:35 +0100694 alloc->free(alloc->ctx, ptr);
695 return NULL;
Victor Stinner52968672013-11-24 11:37:15 +0100696 }
Victor Stinner88c29872013-12-04 01:47:46 +0100697 TABLES_UNLOCK();
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100698 return ptr;
699}
700
Victor Stinnere492ae52016-03-22 12:58:23 +0100701
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100702static void*
Victor Stinner15116802013-12-04 01:29:35 +0100703tracemalloc_realloc(void *ctx, void *ptr, size_t new_size)
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100704{
Victor Stinnerd8f0d922014-06-02 21:57:10 +0200705 PyMemAllocatorEx *alloc = (PyMemAllocatorEx *)ctx;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100706 void *ptr2;
707
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100708 ptr2 = alloc->realloc(alloc->ctx, ptr, new_size);
Victor Stinner15116802013-12-04 01:29:35 +0100709 if (ptr2 == NULL)
710 return NULL;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100711
Victor Stinner15116802013-12-04 01:29:35 +0100712 if (ptr != NULL) {
713 /* an existing memory block has been resized */
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100714
Victor Stinner88c29872013-12-04 01:47:46 +0100715 TABLES_LOCK();
Victor Stinner42bcf372016-03-23 09:08:08 +0100716
717 /* tracemalloc_add_trace() updates the trace if there is already
718 a trace at address (domain, ptr2) */
719 if (ptr2 != ptr) {
720 REMOVE_TRACE(ptr);
721 }
Victor Stinner08facd22013-11-24 12:27:59 +0100722
Victor Stinnere492ae52016-03-22 12:58:23 +0100723 if (ADD_TRACE(ptr2, new_size) < 0) {
Victor Stinner15116802013-12-04 01:29:35 +0100724 /* Memory allocation failed. The error cannot be reported to
Raymond Hettinger15f44ab2016-08-30 10:47:49 -0700725 the caller, because realloc() may already have shrunk the
Victor Stinner15116802013-12-04 01:29:35 +0100726 memory block and so removed bytes.
727
Serhiy Storchaka6a7b3a72016-04-17 08:32:47 +0300728 This case is very unlikely: a hash entry has just been
Victor Stinner88c29872013-12-04 01:47:46 +0100729 released, so the hash table should have at least one free entry.
730
731 The GIL and the table lock ensures that only one thread is
732 allocating memory. */
733 assert(0 && "should never happen");
Victor Stinner52968672013-11-24 11:37:15 +0100734 }
Victor Stinner88c29872013-12-04 01:47:46 +0100735 TABLES_UNLOCK();
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100736 }
Victor Stinner15116802013-12-04 01:29:35 +0100737 else {
738 /* new allocation */
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100739
Victor Stinner88c29872013-12-04 01:47:46 +0100740 TABLES_LOCK();
Victor Stinnere492ae52016-03-22 12:58:23 +0100741 if (ADD_TRACE(ptr2, new_size) < 0) {
Victor Stinner15116802013-12-04 01:29:35 +0100742 /* Failed to allocate a trace for the new memory block */
Victor Stinner88c29872013-12-04 01:47:46 +0100743 TABLES_UNLOCK();
Victor Stinner15116802013-12-04 01:29:35 +0100744 alloc->free(alloc->ctx, ptr2);
745 return NULL;
746 }
Victor Stinner88c29872013-12-04 01:47:46 +0100747 TABLES_UNLOCK();
Victor Stinner15116802013-12-04 01:29:35 +0100748 }
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100749 return ptr2;
750}
751
Victor Stinnere492ae52016-03-22 12:58:23 +0100752
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100753static void
754tracemalloc_free(void *ctx, void *ptr)
755{
Victor Stinnerd8f0d922014-06-02 21:57:10 +0200756 PyMemAllocatorEx *alloc = (PyMemAllocatorEx *)ctx;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100757
758 if (ptr == NULL)
759 return;
760
761 /* GIL cannot be locked in PyMem_RawFree() because it would introduce
762 a deadlock in PyThreadState_DeleteCurrent(). */
763
764 alloc->free(alloc->ctx, ptr);
Victor Stinner88c29872013-12-04 01:47:46 +0100765
766 TABLES_LOCK();
Victor Stinnere492ae52016-03-22 12:58:23 +0100767 REMOVE_TRACE(ptr);
Victor Stinner88c29872013-12-04 01:47:46 +0100768 TABLES_UNLOCK();
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100769}
770
Victor Stinnere492ae52016-03-22 12:58:23 +0100771
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100772static void*
Victor Stinnerdb067af2014-05-02 22:31:14 +0200773tracemalloc_alloc_gil(int use_calloc, void *ctx, size_t nelem, size_t elsize)
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100774{
Victor Stinner15116802013-12-04 01:29:35 +0100775 void *ptr;
776
777 if (get_reentrant()) {
Victor Stinnerd8f0d922014-06-02 21:57:10 +0200778 PyMemAllocatorEx *alloc = (PyMemAllocatorEx *)ctx;
Victor Stinnerdb067af2014-05-02 22:31:14 +0200779 if (use_calloc)
780 return alloc->calloc(alloc->ctx, nelem, elsize);
781 else
782 return alloc->malloc(alloc->ctx, nelem * elsize);
Victor Stinner15116802013-12-04 01:29:35 +0100783 }
784
785 /* Ignore reentrant call. PyObjet_Malloc() calls PyMem_Malloc() for
786 allocations larger than 512 bytes, don't trace the same memory
787 allocation twice. */
788 set_reentrant(1);
789
Victor Stinnerdb067af2014-05-02 22:31:14 +0200790 ptr = tracemalloc_alloc(use_calloc, ctx, nelem, elsize);
Victor Stinner15116802013-12-04 01:29:35 +0100791
792 set_reentrant(0);
793 return ptr;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100794}
795
Victor Stinnere492ae52016-03-22 12:58:23 +0100796
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100797static void*
Victor Stinnerdb067af2014-05-02 22:31:14 +0200798tracemalloc_malloc_gil(void *ctx, size_t size)
799{
800 return tracemalloc_alloc_gil(0, ctx, 1, size);
801}
802
Victor Stinnere492ae52016-03-22 12:58:23 +0100803
Victor Stinnerdb067af2014-05-02 22:31:14 +0200804static void*
805tracemalloc_calloc_gil(void *ctx, size_t nelem, size_t elsize)
806{
807 return tracemalloc_alloc_gil(1, ctx, nelem, elsize);
808}
809
Victor Stinnere492ae52016-03-22 12:58:23 +0100810
Victor Stinnerdb067af2014-05-02 22:31:14 +0200811static void*
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100812tracemalloc_realloc_gil(void *ctx, void *ptr, size_t new_size)
813{
Victor Stinner15116802013-12-04 01:29:35 +0100814 void *ptr2;
815
816 if (get_reentrant()) {
817 /* Reentrant call to PyMem_Realloc() and PyMem_RawRealloc().
818 Example: PyMem_RawRealloc() is called internally by pymalloc
819 (_PyObject_Malloc() and _PyObject_Realloc()) to allocate a new
820 arena (new_arena()). */
Victor Stinnerd8f0d922014-06-02 21:57:10 +0200821 PyMemAllocatorEx *alloc = (PyMemAllocatorEx *)ctx;
Victor Stinner15116802013-12-04 01:29:35 +0100822
823 ptr2 = alloc->realloc(alloc->ctx, ptr, new_size);
Victor Stinner88c29872013-12-04 01:47:46 +0100824 if (ptr2 != NULL && ptr != NULL) {
825 TABLES_LOCK();
Victor Stinnere492ae52016-03-22 12:58:23 +0100826 REMOVE_TRACE(ptr);
Victor Stinner88c29872013-12-04 01:47:46 +0100827 TABLES_UNLOCK();
828 }
Victor Stinner15116802013-12-04 01:29:35 +0100829 return ptr2;
830 }
831
832 /* Ignore reentrant call. PyObjet_Realloc() calls PyMem_Realloc() for
833 allocations larger than 512 bytes. Don't trace the same memory
834 allocation twice. */
835 set_reentrant(1);
836
837 ptr2 = tracemalloc_realloc(ctx, ptr, new_size);
838
839 set_reentrant(0);
840 return ptr2;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100841}
842
Victor Stinnere492ae52016-03-22 12:58:23 +0100843
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100844#ifdef TRACE_RAW_MALLOC
845static void*
Victor Stinnerdb067af2014-05-02 22:31:14 +0200846tracemalloc_raw_alloc(int use_calloc, void *ctx, size_t nelem, size_t elsize)
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100847{
Victor Stinner15116802013-12-04 01:29:35 +0100848#ifdef WITH_THREAD
849 PyGILState_STATE gil_state;
850#endif
851 void *ptr;
852
853 if (get_reentrant()) {
Victor Stinnerd8f0d922014-06-02 21:57:10 +0200854 PyMemAllocatorEx *alloc = (PyMemAllocatorEx *)ctx;
Victor Stinnerdb067af2014-05-02 22:31:14 +0200855 if (use_calloc)
856 return alloc->calloc(alloc->ctx, nelem, elsize);
857 else
858 return alloc->malloc(alloc->ctx, nelem * elsize);
Victor Stinner15116802013-12-04 01:29:35 +0100859 }
860
861 /* Ignore reentrant call. PyGILState_Ensure() may call PyMem_RawMalloc()
862 indirectly which would call PyGILState_Ensure() if reentrant are not
863 disabled. */
864 set_reentrant(1);
865
866#ifdef WITH_THREAD
867 gil_state = PyGILState_Ensure();
Victor Stinnerdb067af2014-05-02 22:31:14 +0200868 ptr = tracemalloc_alloc(use_calloc, ctx, nelem, elsize);
Victor Stinner15116802013-12-04 01:29:35 +0100869 PyGILState_Release(gil_state);
870#else
Victor Stinnerdb067af2014-05-02 22:31:14 +0200871 ptr = tracemalloc_alloc(use_calloc, ctx, nelem, elsize);
Victor Stinner15116802013-12-04 01:29:35 +0100872#endif
873
874 set_reentrant(0);
875 return ptr;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100876}
877
Victor Stinnere492ae52016-03-22 12:58:23 +0100878
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100879static void*
Victor Stinnerdb067af2014-05-02 22:31:14 +0200880tracemalloc_raw_malloc(void *ctx, size_t size)
881{
882 return tracemalloc_raw_alloc(0, ctx, 1, size);
883}
884
Victor Stinnere492ae52016-03-22 12:58:23 +0100885
Victor Stinnerdb067af2014-05-02 22:31:14 +0200886static void*
887tracemalloc_raw_calloc(void *ctx, size_t nelem, size_t elsize)
888{
889 return tracemalloc_raw_alloc(1, ctx, nelem, elsize);
890}
891
Victor Stinnere492ae52016-03-22 12:58:23 +0100892
Victor Stinnerdb067af2014-05-02 22:31:14 +0200893static void*
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100894tracemalloc_raw_realloc(void *ctx, void *ptr, size_t new_size)
895{
Victor Stinner15116802013-12-04 01:29:35 +0100896#ifdef WITH_THREAD
897 PyGILState_STATE gil_state;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100898#endif
Victor Stinner15116802013-12-04 01:29:35 +0100899 void *ptr2;
900
901 if (get_reentrant()) {
902 /* Reentrant call to PyMem_RawRealloc(). */
Victor Stinnerd8f0d922014-06-02 21:57:10 +0200903 PyMemAllocatorEx *alloc = (PyMemAllocatorEx *)ctx;
Victor Stinner15116802013-12-04 01:29:35 +0100904
905 ptr2 = alloc->realloc(alloc->ctx, ptr, new_size);
Victor Stinner15116802013-12-04 01:29:35 +0100906
Victor Stinner88c29872013-12-04 01:47:46 +0100907 if (ptr2 != NULL && ptr != NULL) {
908 TABLES_LOCK();
Victor Stinnere492ae52016-03-22 12:58:23 +0100909 REMOVE_TRACE(ptr);
Victor Stinner88c29872013-12-04 01:47:46 +0100910 TABLES_UNLOCK();
911 }
Victor Stinner15116802013-12-04 01:29:35 +0100912 return ptr2;
913 }
914
915 /* Ignore reentrant call. PyGILState_Ensure() may call PyMem_RawMalloc()
916 indirectly which would call PyGILState_Ensure() if reentrant calls are
917 not disabled. */
918 set_reentrant(1);
919
920#ifdef WITH_THREAD
921 gil_state = PyGILState_Ensure();
922 ptr2 = tracemalloc_realloc(ctx, ptr, new_size);
923 PyGILState_Release(gil_state);
924#else
925 ptr2 = tracemalloc_realloc(ctx, ptr, new_size);
926#endif
927
928 set_reentrant(0);
929 return ptr2;
930}
931#endif /* TRACE_RAW_MALLOC */
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100932
Victor Stinnere492ae52016-03-22 12:58:23 +0100933
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100934static int
Victor Stinner285cf0a2016-03-21 22:00:58 +0100935tracemalloc_clear_filename(_Py_hashtable_t *ht, _Py_hashtable_entry_t *entry,
936 void *user_data)
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100937{
Victor Stinner285cf0a2016-03-21 22:00:58 +0100938 PyObject *filename;
939
Victor Stinner5dacbd42016-03-23 09:52:13 +0100940 _Py_HASHTABLE_ENTRY_READ_KEY(ht, entry, filename);
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100941 Py_DECREF(filename);
942 return 0;
943}
944
Victor Stinnere492ae52016-03-22 12:58:23 +0100945
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100946static int
Victor Stinner285cf0a2016-03-21 22:00:58 +0100947traceback_free_traceback(_Py_hashtable_t *ht, _Py_hashtable_entry_t *entry,
948 void *user_data)
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100949{
Victor Stinner285cf0a2016-03-21 22:00:58 +0100950 traceback_t *traceback;
951
Victor Stinner5dacbd42016-03-23 09:52:13 +0100952 _Py_HASHTABLE_ENTRY_READ_KEY(ht, entry, traceback);
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100953 raw_free(traceback);
954 return 0;
955}
956
Victor Stinnere492ae52016-03-22 12:58:23 +0100957
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100958/* reentrant flag must be set to call this function and GIL must be held */
959static void
960tracemalloc_clear_traces(void)
961{
962#ifdef WITH_THREAD
963 /* The GIL protects variables againt concurrent access */
964 assert(PyGILState_Check());
965#endif
966
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100967 TABLES_LOCK();
968 _Py_hashtable_clear(tracemalloc_traces);
969 tracemalloc_traced_memory = 0;
Victor Stinner3c0481d2013-11-27 21:39:49 +0100970 tracemalloc_peak_traced_memory = 0;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100971 TABLES_UNLOCK();
972
973 _Py_hashtable_foreach(tracemalloc_tracebacks, traceback_free_traceback, NULL);
974 _Py_hashtable_clear(tracemalloc_tracebacks);
975
976 _Py_hashtable_foreach(tracemalloc_filenames, tracemalloc_clear_filename, NULL);
977 _Py_hashtable_clear(tracemalloc_filenames);
978}
979
Victor Stinnere492ae52016-03-22 12:58:23 +0100980
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100981static int
982tracemalloc_init(void)
983{
984 if (tracemalloc_config.initialized == TRACEMALLOC_FINALIZED) {
985 PyErr_SetString(PyExc_RuntimeError,
986 "the tracemalloc module has been unloaded");
987 return -1;
988 }
989
Victor Stinnerf9a71152016-03-22 23:54:42 +0100990 if (tracemalloc_config.initialized == TRACEMALLOC_INITIALIZED)
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100991 return 0;
992
993 PyMem_GetAllocator(PYMEM_DOMAIN_RAW, &allocators.raw);
994
995#ifdef REENTRANT_THREADLOCAL
996 tracemalloc_reentrant_key = PyThread_create_key();
997 if (tracemalloc_reentrant_key == -1) {
998#ifdef MS_WINDOWS
999 PyErr_SetFromWindowsErr(0);
1000#else
1001 PyErr_SetFromErrno(PyExc_OSError);
1002#endif
1003 return -1;
1004 }
1005#endif
1006
1007#if defined(WITH_THREAD) && defined(TRACE_RAW_MALLOC)
1008 if (tables_lock == NULL) {
1009 tables_lock = PyThread_allocate_lock();
1010 if (tables_lock == NULL) {
1011 PyErr_SetString(PyExc_RuntimeError, "cannot allocate lock");
1012 return -1;
1013 }
1014 }
1015#endif
1016
Victor Stinner285cf0a2016-03-21 22:00:58 +01001017 tracemalloc_filenames = hashtable_new(sizeof(PyObject *), 0,
1018 hashtable_hash_pyobject,
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001019 hashtable_compare_unicode);
1020
Victor Stinner285cf0a2016-03-21 22:00:58 +01001021 tracemalloc_tracebacks = hashtable_new(sizeof(traceback_t *), 0,
1022 hashtable_hash_traceback,
1023 hashtable_compare_traceback);
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001024
Victor Stinnere492ae52016-03-22 12:58:23 +01001025 if (tracemalloc_config.use_domain) {
1026 tracemalloc_traces = hashtable_new(sizeof(pointer_t),
1027 sizeof(trace_t),
1028 hashtable_hash_pointer_t,
1029 hashtable_compare_pointer_t);
1030 }
1031 else {
Benjamin Petersonca470632016-09-06 13:47:26 -07001032 tracemalloc_traces = hashtable_new(sizeof(uintptr_t),
Victor Stinnere492ae52016-03-22 12:58:23 +01001033 sizeof(trace_t),
1034 _Py_hashtable_hash_ptr,
1035 _Py_hashtable_compare_direct);
1036 }
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001037
1038 if (tracemalloc_filenames == NULL || tracemalloc_tracebacks == NULL
Victor Stinner285cf0a2016-03-21 22:00:58 +01001039 || tracemalloc_traces == NULL) {
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001040 PyErr_NoMemory();
1041 return -1;
1042 }
1043
1044 unknown_filename = PyUnicode_FromString("<unknown>");
1045 if (unknown_filename == NULL)
1046 return -1;
1047 PyUnicode_InternInPlace(&unknown_filename);
1048
1049 tracemalloc_empty_traceback.nframe = 1;
1050 /* borrowed reference */
1051 tracemalloc_empty_traceback.frames[0].filename = unknown_filename;
1052 tracemalloc_empty_traceback.frames[0].lineno = 0;
1053 tracemalloc_empty_traceback.hash = traceback_hash(&tracemalloc_empty_traceback);
1054
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001055 tracemalloc_config.initialized = TRACEMALLOC_INITIALIZED;
1056 return 0;
1057}
1058
Victor Stinnere492ae52016-03-22 12:58:23 +01001059
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001060static void
1061tracemalloc_deinit(void)
1062{
Victor Stinnerf9a71152016-03-22 23:54:42 +01001063 if (tracemalloc_config.initialized != TRACEMALLOC_INITIALIZED)
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001064 return;
1065 tracemalloc_config.initialized = TRACEMALLOC_FINALIZED;
1066
1067 tracemalloc_stop();
1068
1069 /* destroy hash tables */
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001070 _Py_hashtable_destroy(tracemalloc_tracebacks);
1071 _Py_hashtable_destroy(tracemalloc_filenames);
Victor Stinner285cf0a2016-03-21 22:00:58 +01001072 _Py_hashtable_destroy(tracemalloc_traces);
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001073
1074#if defined(WITH_THREAD) && defined(TRACE_RAW_MALLOC)
1075 if (tables_lock != NULL) {
1076 PyThread_free_lock(tables_lock);
1077 tables_lock = NULL;
1078 }
1079#endif
1080
1081#ifdef REENTRANT_THREADLOCAL
1082 PyThread_delete_key(tracemalloc_reentrant_key);
Victor Stinner4a066472016-03-22 17:45:09 +01001083 tracemalloc_reentrant_key = -1;
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001084#endif
1085
1086 Py_XDECREF(unknown_filename);
1087}
1088
Victor Stinnere492ae52016-03-22 12:58:23 +01001089
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001090static int
Victor Stinnerf28ce602013-11-27 22:27:13 +01001091tracemalloc_start(int max_nframe)
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001092{
Victor Stinnerd8f0d922014-06-02 21:57:10 +02001093 PyMemAllocatorEx alloc;
Victor Stinnerf28ce602013-11-27 22:27:13 +01001094 size_t size;
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001095
Victor Stinnerf9a71152016-03-22 23:54:42 +01001096 if (tracemalloc_init() < 0)
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001097 return -1;
1098
1099 if (tracemalloc_config.tracing) {
1100 /* hook already installed: do nothing */
1101 return 0;
1102 }
1103
Victor Stinner52aee852014-08-16 15:44:02 +02001104 assert(1 <= max_nframe && max_nframe <= MAX_NFRAME);
Victor Stinnerf28ce602013-11-27 22:27:13 +01001105 tracemalloc_config.max_nframe = max_nframe;
1106
1107 /* allocate a buffer to store a new traceback */
1108 size = TRACEBACK_SIZE(max_nframe);
1109 assert(tracemalloc_traceback == NULL);
1110 tracemalloc_traceback = raw_malloc(size);
1111 if (tracemalloc_traceback == NULL) {
1112 PyErr_NoMemory();
1113 return -1;
1114 }
1115
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001116#ifdef TRACE_RAW_MALLOC
1117 alloc.malloc = tracemalloc_raw_malloc;
Victor Stinnerdb067af2014-05-02 22:31:14 +02001118 alloc.calloc = tracemalloc_raw_calloc;
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001119 alloc.realloc = tracemalloc_raw_realloc;
1120 alloc.free = tracemalloc_free;
1121
1122 alloc.ctx = &allocators.raw;
1123 PyMem_GetAllocator(PYMEM_DOMAIN_RAW, &allocators.raw);
1124 PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &alloc);
1125#endif
1126
1127 alloc.malloc = tracemalloc_malloc_gil;
Victor Stinnerdb067af2014-05-02 22:31:14 +02001128 alloc.calloc = tracemalloc_calloc_gil;
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001129 alloc.realloc = tracemalloc_realloc_gil;
1130 alloc.free = tracemalloc_free;
1131
1132 alloc.ctx = &allocators.mem;
1133 PyMem_GetAllocator(PYMEM_DOMAIN_MEM, &allocators.mem);
1134 PyMem_SetAllocator(PYMEM_DOMAIN_MEM, &alloc);
1135
1136 alloc.ctx = &allocators.obj;
1137 PyMem_GetAllocator(PYMEM_DOMAIN_OBJ, &allocators.obj);
1138 PyMem_SetAllocator(PYMEM_DOMAIN_OBJ, &alloc);
1139
1140 /* everything is ready: start tracing Python memory allocations */
1141 tracemalloc_config.tracing = 1;
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001142
1143 return 0;
1144}
1145
Victor Stinnere492ae52016-03-22 12:58:23 +01001146
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001147static void
1148tracemalloc_stop(void)
1149{
Victor Stinnerf9a71152016-03-22 23:54:42 +01001150 if (!tracemalloc_config.tracing)
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001151 return;
1152
1153 /* stop tracing Python memory allocations */
1154 tracemalloc_config.tracing = 0;
1155
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001156 /* unregister the hook on memory allocators */
1157#ifdef TRACE_RAW_MALLOC
1158 PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &allocators.raw);
1159#endif
1160 PyMem_SetAllocator(PYMEM_DOMAIN_MEM, &allocators.mem);
1161 PyMem_SetAllocator(PYMEM_DOMAIN_OBJ, &allocators.obj);
1162
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001163 tracemalloc_clear_traces();
Victor Stinner285cf0a2016-03-21 22:00:58 +01001164
1165 /* release memory */
Victor Stinnerf28ce602013-11-27 22:27:13 +01001166 raw_free(tracemalloc_traceback);
1167 tracemalloc_traceback = NULL;
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001168}
1169
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001170
Victor Stinnere492ae52016-03-22 12:58:23 +01001171
Serhiy Storchakab451f912017-02-04 12:18:38 +02001172/*[clinic input]
1173_tracemalloc.is_tracing
1174
1175Return True if the tracemalloc module is tracing Python memory allocations.
1176[clinic start generated code]*/
1177
1178static PyObject *
1179_tracemalloc_is_tracing_impl(PyObject *module)
Serhiy Storchaka97353842017-02-05 22:58:46 +02001180/*[clinic end generated code: output=2d763b42601cd3ef input=af104b0a00192f63]*/
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001181{
1182 return PyBool_FromLong(tracemalloc_config.tracing);
1183}
1184
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001185
Serhiy Storchakab451f912017-02-04 12:18:38 +02001186/*[clinic input]
1187_tracemalloc.clear_traces
Victor Stinnere492ae52016-03-22 12:58:23 +01001188
Serhiy Storchakab451f912017-02-04 12:18:38 +02001189Clear traces of memory blocks allocated by Python.
1190[clinic start generated code]*/
1191
1192static PyObject *
1193_tracemalloc_clear_traces_impl(PyObject *module)
1194/*[clinic end generated code: output=a86080ee41b84197 input=0dab5b6c785183a5]*/
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001195{
1196 if (!tracemalloc_config.tracing)
1197 Py_RETURN_NONE;
1198
1199 set_reentrant(1);
1200 tracemalloc_clear_traces();
1201 set_reentrant(0);
1202
1203 Py_RETURN_NONE;
1204}
1205
Victor Stinnere492ae52016-03-22 12:58:23 +01001206
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001207static PyObject*
1208frame_to_pyobject(frame_t *frame)
1209{
1210 PyObject *frame_obj, *lineno_obj;
1211
1212 frame_obj = PyTuple_New(2);
1213 if (frame_obj == NULL)
1214 return NULL;
1215
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001216 Py_INCREF(frame->filename);
1217 PyTuple_SET_ITEM(frame_obj, 0, frame->filename);
1218
Victor Stinner95283342016-03-15 21:57:02 +01001219 lineno_obj = PyLong_FromUnsignedLong(frame->lineno);
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001220 if (lineno_obj == NULL) {
1221 Py_DECREF(frame_obj);
1222 return NULL;
1223 }
1224 PyTuple_SET_ITEM(frame_obj, 1, lineno_obj);
1225
1226 return frame_obj;
1227}
1228
Victor Stinnere492ae52016-03-22 12:58:23 +01001229
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001230static PyObject*
1231traceback_to_pyobject(traceback_t *traceback, _Py_hashtable_t *intern_table)
1232{
1233 int i;
1234 PyObject *frames, *frame;
1235
1236 if (intern_table != NULL) {
1237 if (_Py_HASHTABLE_GET(intern_table, traceback, frames)) {
1238 Py_INCREF(frames);
1239 return frames;
1240 }
1241 }
1242
1243 frames = PyTuple_New(traceback->nframe);
1244 if (frames == NULL)
1245 return NULL;
1246
1247 for (i=0; i < traceback->nframe; i++) {
1248 frame = frame_to_pyobject(&traceback->frames[i]);
1249 if (frame == NULL) {
1250 Py_DECREF(frames);
1251 return NULL;
1252 }
1253 PyTuple_SET_ITEM(frames, i, frame);
1254 }
1255
1256 if (intern_table != NULL) {
1257 if (_Py_HASHTABLE_SET(intern_table, traceback, frames) < 0) {
1258 Py_DECREF(frames);
1259 PyErr_NoMemory();
1260 return NULL;
1261 }
1262 /* intern_table keeps a new reference to frames */
1263 Py_INCREF(frames);
1264 }
1265 return frames;
1266}
1267
Victor Stinnere492ae52016-03-22 12:58:23 +01001268
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001269static PyObject*
Victor Stinner5ea4c062017-06-20 17:46:36 +02001270trace_to_pyobject(unsigned int domain, trace_t *trace,
Victor Stinnere492ae52016-03-22 12:58:23 +01001271 _Py_hashtable_t *intern_tracebacks)
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001272{
1273 PyObject *trace_obj = NULL;
Victor Stinnere492ae52016-03-22 12:58:23 +01001274 PyObject *obj;
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001275
Victor Stinnere492ae52016-03-22 12:58:23 +01001276 trace_obj = PyTuple_New(3);
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001277 if (trace_obj == NULL)
1278 return NULL;
1279
Victor Stinnere492ae52016-03-22 12:58:23 +01001280 obj = PyLong_FromSize_t(domain);
1281 if (obj == NULL) {
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001282 Py_DECREF(trace_obj);
1283 return NULL;
1284 }
Victor Stinnere492ae52016-03-22 12:58:23 +01001285 PyTuple_SET_ITEM(trace_obj, 0, obj);
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001286
Victor Stinnere492ae52016-03-22 12:58:23 +01001287 obj = PyLong_FromSize_t(trace->size);
1288 if (obj == NULL) {
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001289 Py_DECREF(trace_obj);
1290 return NULL;
1291 }
Victor Stinnere492ae52016-03-22 12:58:23 +01001292 PyTuple_SET_ITEM(trace_obj, 1, obj);
1293
1294 obj = traceback_to_pyobject(trace->traceback, intern_tracebacks);
1295 if (obj == NULL) {
1296 Py_DECREF(trace_obj);
1297 return NULL;
1298 }
1299 PyTuple_SET_ITEM(trace_obj, 2, obj);
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001300
1301 return trace_obj;
1302}
1303
Victor Stinnere492ae52016-03-22 12:58:23 +01001304
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001305typedef struct {
1306 _Py_hashtable_t *traces;
1307 _Py_hashtable_t *tracebacks;
1308 PyObject *list;
1309} get_traces_t;
1310
1311static int
Victor Stinner285cf0a2016-03-21 22:00:58 +01001312tracemalloc_get_traces_fill(_Py_hashtable_t *traces, _Py_hashtable_entry_t *entry,
1313 void *user_data)
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001314{
1315 get_traces_t *get_traces = user_data;
Victor Stinner5ea4c062017-06-20 17:46:36 +02001316 unsigned int domain;
Victor Stinner5dacbd42016-03-23 09:52:13 +01001317 trace_t trace;
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001318 PyObject *tracemalloc_obj;
1319 int res;
1320
Victor Stinnere492ae52016-03-22 12:58:23 +01001321 if (tracemalloc_config.use_domain) {
1322 pointer_t key;
Victor Stinner5dacbd42016-03-23 09:52:13 +01001323 _Py_HASHTABLE_ENTRY_READ_KEY(traces, entry, key);
Victor Stinnere492ae52016-03-22 12:58:23 +01001324 domain = key.domain;
1325 }
1326 else {
1327 domain = DEFAULT_DOMAIN;
1328 }
Victor Stinner5dacbd42016-03-23 09:52:13 +01001329 _Py_HASHTABLE_ENTRY_READ_DATA(traces, entry, trace);
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001330
Victor Stinner5dacbd42016-03-23 09:52:13 +01001331 tracemalloc_obj = trace_to_pyobject(domain, &trace, get_traces->tracebacks);
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001332 if (tracemalloc_obj == NULL)
1333 return 1;
1334
1335 res = PyList_Append(get_traces->list, tracemalloc_obj);
1336 Py_DECREF(tracemalloc_obj);
1337 if (res < 0)
1338 return 1;
1339
1340 return 0;
1341}
1342
Victor Stinnere492ae52016-03-22 12:58:23 +01001343
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001344static int
Victor Stinner285cf0a2016-03-21 22:00:58 +01001345tracemalloc_pyobject_decref_cb(_Py_hashtable_t *tracebacks,
1346 _Py_hashtable_entry_t *entry,
1347 void *user_data)
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001348{
Victor Stinnerc9553872016-03-22 12:13:01 +01001349 PyObject *obj;
Victor Stinnere8c6b2f2016-03-23 09:25:01 +01001350 _Py_HASHTABLE_ENTRY_READ_DATA(tracebacks, entry, obj);
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001351 Py_DECREF(obj);
1352 return 0;
1353}
1354
Victor Stinnere492ae52016-03-22 12:58:23 +01001355
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001356
Serhiy Storchakab451f912017-02-04 12:18:38 +02001357/*[clinic input]
1358_tracemalloc._get_traces
1359
1360Get traces of all memory blocks allocated by Python.
1361
1362Return a list of (size: int, traceback: tuple) tuples.
1363traceback is a tuple of (filename: str, lineno: int) tuples.
1364
1365Return an empty list if the tracemalloc module is disabled.
1366[clinic start generated code]*/
1367
1368static PyObject *
1369_tracemalloc__get_traces_impl(PyObject *module)
1370/*[clinic end generated code: output=e9929876ced4b5cc input=6c7d2230b24255aa]*/
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001371{
1372 get_traces_t get_traces;
1373 int err;
1374
1375 get_traces.traces = NULL;
1376 get_traces.tracebacks = NULL;
1377 get_traces.list = PyList_New(0);
1378 if (get_traces.list == NULL)
1379 goto error;
1380
1381 if (!tracemalloc_config.tracing)
1382 return get_traces.list;
1383
Victor Stinnerde2f1322013-11-26 00:26:23 +01001384 /* the traceback hash table is used temporarily to intern traceback tuple
1385 of (filename, lineno) tuples */
Victor Stinnerc9553872016-03-22 12:13:01 +01001386 get_traces.tracebacks = hashtable_new(sizeof(traceback_t *),
1387 sizeof(PyObject *),
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001388 _Py_hashtable_hash_ptr,
1389 _Py_hashtable_compare_direct);
1390 if (get_traces.tracebacks == NULL) {
1391 PyErr_NoMemory();
1392 goto error;
1393 }
1394
1395 TABLES_LOCK();
1396 get_traces.traces = _Py_hashtable_copy(tracemalloc_traces);
1397 TABLES_UNLOCK();
1398
1399 if (get_traces.traces == NULL) {
1400 PyErr_NoMemory();
1401 goto error;
1402 }
1403
1404 set_reentrant(1);
1405 err = _Py_hashtable_foreach(get_traces.traces,
1406 tracemalloc_get_traces_fill, &get_traces);
1407 set_reentrant(0);
1408 if (err)
1409 goto error;
1410
1411 goto finally;
1412
1413error:
1414 Py_CLEAR(get_traces.list);
1415
1416finally:
1417 if (get_traces.tracebacks != NULL) {
1418 _Py_hashtable_foreach(get_traces.tracebacks,
Victor Stinner285cf0a2016-03-21 22:00:58 +01001419 tracemalloc_pyobject_decref_cb, NULL);
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001420 _Py_hashtable_destroy(get_traces.tracebacks);
1421 }
Victor Stinnerc9553872016-03-22 12:13:01 +01001422 if (get_traces.traces != NULL) {
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001423 _Py_hashtable_destroy(get_traces.traces);
Victor Stinnerc9553872016-03-22 12:13:01 +01001424 }
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001425
1426 return get_traces.list;
1427}
1428
Victor Stinnere492ae52016-03-22 12:58:23 +01001429
Victor Stinner0611c262016-03-15 22:22:13 +01001430static traceback_t*
Victor Stinner5ea4c062017-06-20 17:46:36 +02001431tracemalloc_get_traceback(unsigned int domain, uintptr_t ptr)
Victor Stinner0611c262016-03-15 22:22:13 +01001432{
1433 trace_t trace;
1434 int found;
1435
1436 if (!tracemalloc_config.tracing)
1437 return NULL;
1438
1439 TABLES_LOCK();
Victor Stinnere492ae52016-03-22 12:58:23 +01001440 if (tracemalloc_config.use_domain) {
Victor Stinner10b73e12016-03-22 13:39:05 +01001441 pointer_t key = {ptr, domain};
Victor Stinnere492ae52016-03-22 12:58:23 +01001442 found = _Py_HASHTABLE_GET(tracemalloc_traces, key, trace);
1443 }
1444 else {
1445 found = _Py_HASHTABLE_GET(tracemalloc_traces, ptr, trace);
1446 }
Victor Stinner0611c262016-03-15 22:22:13 +01001447 TABLES_UNLOCK();
1448
1449 if (!found)
1450 return NULL;
1451
1452 return trace.traceback;
1453}
1454
Victor Stinnere492ae52016-03-22 12:58:23 +01001455
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001456
Serhiy Storchakab451f912017-02-04 12:18:38 +02001457/*[clinic input]
1458_tracemalloc._get_object_traceback
1459
1460 obj: object
1461 /
1462
1463Get the traceback where the Python object obj was allocated.
1464
1465Return a tuple of (filename: str, lineno: int) tuples.
1466Return None if the tracemalloc module is disabled or did not
1467trace the allocation of the object.
1468[clinic start generated code]*/
1469
1470static PyObject *
1471_tracemalloc__get_object_traceback(PyObject *module, PyObject *obj)
1472/*[clinic end generated code: output=41ee0553a658b0aa input=29495f1b21c53212]*/
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001473{
1474 PyTypeObject *type;
1475 void *ptr;
Victor Stinner0611c262016-03-15 22:22:13 +01001476 traceback_t *traceback;
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001477
1478 type = Py_TYPE(obj);
1479 if (PyType_IS_GC(type))
1480 ptr = (void *)((char *)obj - sizeof(PyGC_Head));
1481 else
1482 ptr = (void *)obj;
1483
Benjamin Petersonca470632016-09-06 13:47:26 -07001484 traceback = tracemalloc_get_traceback(DEFAULT_DOMAIN, (uintptr_t)ptr);
Victor Stinner0611c262016-03-15 22:22:13 +01001485 if (traceback == NULL)
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001486 Py_RETURN_NONE;
1487
Victor Stinner0611c262016-03-15 22:22:13 +01001488 return traceback_to_pyobject(traceback, NULL);
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001489}
1490
Victor Stinnere492ae52016-03-22 12:58:23 +01001491
Victor Stinner0611c262016-03-15 22:22:13 +01001492#define PUTS(fd, str) _Py_write_noraise(fd, str, (int)strlen(str))
1493
1494static void
1495_PyMem_DumpFrame(int fd, frame_t * frame)
1496{
1497 PUTS(fd, " File \"");
1498 _Py_DumpASCII(fd, frame->filename);
1499 PUTS(fd, "\", line ");
1500 _Py_DumpDecimal(fd, frame->lineno);
1501 PUTS(fd, "\n");
1502}
1503
1504/* Dump the traceback where a memory block was allocated into file descriptor
1505 fd. The function may block on TABLES_LOCK() but it is unlikely. */
1506void
1507_PyMem_DumpTraceback(int fd, const void *ptr)
1508{
1509 traceback_t *traceback;
1510 int i;
1511
Benjamin Petersonca470632016-09-06 13:47:26 -07001512 traceback = tracemalloc_get_traceback(DEFAULT_DOMAIN, (uintptr_t)ptr);
Victor Stinner0611c262016-03-15 22:22:13 +01001513 if (traceback == NULL)
1514 return;
1515
1516 PUTS(fd, "Memory block allocated at (most recent call first):\n");
1517 for (i=0; i < traceback->nframe; i++) {
1518 _PyMem_DumpFrame(fd, &traceback->frames[i]);
1519 }
1520 PUTS(fd, "\n");
1521}
1522
1523#undef PUTS
1524
Victor Stinnere492ae52016-03-22 12:58:23 +01001525
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001526
Serhiy Storchakab451f912017-02-04 12:18:38 +02001527/*[clinic input]
1528_tracemalloc.start
1529
1530 nframe: Py_ssize_t = 1
1531 /
1532
1533Start tracing Python memory allocations.
1534
1535Also set the maximum number of frames stored in the traceback of a
1536trace to nframe.
1537[clinic start generated code]*/
1538
1539static PyObject *
1540_tracemalloc_start_impl(PyObject *module, Py_ssize_t nframe)
1541/*[clinic end generated code: output=0f558d2079511553 input=997841629cc441cb]*/
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001542{
Victor Stinnerf28ce602013-11-27 22:27:13 +01001543 int nframe_int;
Victor Stinner3728d6c2013-11-23 12:37:20 +01001544
Victor Stinner52aee852014-08-16 15:44:02 +02001545 if (nframe < 1 || nframe > MAX_NFRAME) {
Victor Stinner3728d6c2013-11-23 12:37:20 +01001546 PyErr_Format(PyExc_ValueError,
1547 "the number of frames must be in range [1; %i]",
Serhiy Storchakab451f912017-02-04 12:18:38 +02001548 (int)MAX_NFRAME);
Victor Stinner3728d6c2013-11-23 12:37:20 +01001549 return NULL;
1550 }
Victor Stinnerf28ce602013-11-27 22:27:13 +01001551 nframe_int = Py_SAFE_DOWNCAST(nframe, Py_ssize_t, int);
Victor Stinner3728d6c2013-11-23 12:37:20 +01001552
Victor Stinnerf9a71152016-03-22 23:54:42 +01001553 if (tracemalloc_start(nframe_int) < 0)
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001554 return NULL;
1555
1556 Py_RETURN_NONE;
1557}
1558
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001559
Serhiy Storchakab451f912017-02-04 12:18:38 +02001560/*[clinic input]
1561_tracemalloc.stop
Victor Stinnere492ae52016-03-22 12:58:23 +01001562
Serhiy Storchakab451f912017-02-04 12:18:38 +02001563Stop tracing Python memory allocations.
1564
1565Also clear traces of memory blocks allocated by Python.
1566[clinic start generated code]*/
1567
1568static PyObject *
1569_tracemalloc_stop_impl(PyObject *module)
1570/*[clinic end generated code: output=c3c42ae03e3955cd input=7478f075e51dae18]*/
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001571{
1572 tracemalloc_stop();
1573 Py_RETURN_NONE;
1574}
1575
Victor Stinnere492ae52016-03-22 12:58:23 +01001576
Serhiy Storchakab451f912017-02-04 12:18:38 +02001577/*[clinic input]
1578_tracemalloc.get_traceback_limit
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001579
Serhiy Storchakab451f912017-02-04 12:18:38 +02001580Get the maximum number of frames stored in the traceback of a trace.
1581
1582By default, a trace of an allocated memory block only stores
1583the most recent frame: the limit is 1.
1584[clinic start generated code]*/
1585
1586static PyObject *
1587_tracemalloc_get_traceback_limit_impl(PyObject *module)
1588/*[clinic end generated code: output=d556d9306ba95567 input=da3cd977fc68ae3b]*/
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001589{
1590 return PyLong_FromLong(tracemalloc_config.max_nframe);
1591}
1592
Victor Stinnere492ae52016-03-22 12:58:23 +01001593
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001594
Serhiy Storchakab451f912017-02-04 12:18:38 +02001595/*[clinic input]
1596_tracemalloc.get_tracemalloc_memory
1597
1598Get the memory usage in bytes of the tracemalloc module.
1599
1600This memory is used internally to trace memory allocations.
1601[clinic start generated code]*/
1602
1603static PyObject *
1604_tracemalloc_get_tracemalloc_memory_impl(PyObject *module)
1605/*[clinic end generated code: output=e3f14e280a55f5aa input=5d919c0f4d5132ad]*/
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001606{
1607 size_t size;
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001608
1609 size = _Py_hashtable_size(tracemalloc_tracebacks);
1610 size += _Py_hashtable_size(tracemalloc_filenames);
1611
1612 TABLES_LOCK();
1613 size += _Py_hashtable_size(tracemalloc_traces);
1614 TABLES_UNLOCK();
1615
Serhiy Storchakab451f912017-02-04 12:18:38 +02001616 return PyLong_FromSize_t(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 +01001620
Serhiy Storchakab451f912017-02-04 12:18:38 +02001621/*[clinic input]
1622_tracemalloc.get_traced_memory
1623
1624Get the current size and peak size of memory blocks traced by tracemalloc.
1625
1626Returns a tuple: (current: int, peak: int).
1627[clinic start generated code]*/
1628
1629static PyObject *
1630_tracemalloc_get_traced_memory_impl(PyObject *module)
1631/*[clinic end generated code: output=5b167189adb9e782 input=61ddb5478400ff66]*/
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001632{
Victor Stinner3c0481d2013-11-27 21:39:49 +01001633 Py_ssize_t size, peak_size;
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001634
1635 if (!tracemalloc_config.tracing)
1636 return Py_BuildValue("ii", 0, 0);
1637
1638 TABLES_LOCK();
1639 size = tracemalloc_traced_memory;
Victor Stinner3c0481d2013-11-27 21:39:49 +01001640 peak_size = tracemalloc_peak_traced_memory;
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001641 TABLES_UNLOCK();
1642
Serhiy Storchakab451f912017-02-04 12:18:38 +02001643 return Py_BuildValue("nn", size, peak_size);
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001644}
1645
Victor Stinnere492ae52016-03-22 12:58:23 +01001646
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001647static PyMethodDef module_methods[] = {
Serhiy Storchakab451f912017-02-04 12:18:38 +02001648 _TRACEMALLOC_IS_TRACING_METHODDEF
1649 _TRACEMALLOC_CLEAR_TRACES_METHODDEF
1650 _TRACEMALLOC__GET_TRACES_METHODDEF
1651 _TRACEMALLOC__GET_OBJECT_TRACEBACK_METHODDEF
1652 _TRACEMALLOC_START_METHODDEF
1653 _TRACEMALLOC_STOP_METHODDEF
1654 _TRACEMALLOC_GET_TRACEBACK_LIMIT_METHODDEF
1655 _TRACEMALLOC_GET_TRACEMALLOC_MEMORY_METHODDEF
1656 _TRACEMALLOC_GET_TRACED_MEMORY_METHODDEF
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001657 /* sentinel */
1658 {NULL, NULL}
1659};
1660
1661PyDoc_STRVAR(module_doc,
1662"Debug module to trace memory blocks allocated by Python.");
1663
1664static struct PyModuleDef module_def = {
1665 PyModuleDef_HEAD_INIT,
1666 "_tracemalloc",
1667 module_doc,
1668 0, /* non-negative size to be able to unload the module */
1669 module_methods,
1670 NULL,
1671};
1672
1673PyMODINIT_FUNC
1674PyInit__tracemalloc(void)
1675{
1676 PyObject *m;
1677 m = PyModule_Create(&module_def);
1678 if (m == NULL)
1679 return NULL;
1680
1681 if (tracemalloc_init() < 0)
1682 return NULL;
1683
1684 return m;
1685}
1686
Victor Stinnere492ae52016-03-22 12:58:23 +01001687
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001688static int
1689parse_sys_xoptions(PyObject *value)
1690{
1691 PyObject *valuelong;
1692 long nframe;
1693
1694 if (value == Py_True)
1695 return 1;
1696
1697 assert(PyUnicode_Check(value));
1698 if (PyUnicode_GetLength(value) == 0)
1699 return -1;
1700
1701 valuelong = PyLong_FromUnicodeObject(value, 10);
1702 if (valuelong == NULL)
1703 return -1;
1704
1705 nframe = PyLong_AsLong(valuelong);
1706 Py_DECREF(valuelong);
1707 if (nframe == -1 && PyErr_Occurred())
1708 return -1;
1709
Victor Stinner52aee852014-08-16 15:44:02 +02001710 if (nframe < 1 || nframe > MAX_NFRAME)
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001711 return -1;
1712
1713 return Py_SAFE_DOWNCAST(nframe, long, int);
1714}
1715
Victor Stinnere492ae52016-03-22 12:58:23 +01001716
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001717int
1718_PyTraceMalloc_Init(void)
1719{
1720 char *p;
1721 int nframe;
1722
1723#ifdef WITH_THREAD
1724 assert(PyGILState_Check());
1725#endif
1726
1727 if ((p = Py_GETENV("PYTHONTRACEMALLOC")) && *p != '\0') {
1728 char *endptr = p;
Victor Stinnerf28ce602013-11-27 22:27:13 +01001729 long value;
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001730
Victor Stinner711e27c2013-12-16 23:06:19 +01001731 errno = 0;
Victor Stinnerf28ce602013-11-27 22:27:13 +01001732 value = strtol(p, &endptr, 10);
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001733 if (*endptr != '\0'
1734 || value < 1
Victor Stinner52aee852014-08-16 15:44:02 +02001735 || value > MAX_NFRAME
Victor Stinner711e27c2013-12-16 23:06:19 +01001736 || errno == ERANGE)
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001737 {
Victor Stinnerf28ce602013-11-27 22:27:13 +01001738 Py_FatalError("PYTHONTRACEMALLOC: invalid number of frames");
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001739 return -1;
1740 }
1741
1742 nframe = (int)value;
1743 }
1744 else {
1745 PyObject *xoptions, *key, *value;
1746
1747 xoptions = PySys_GetXOptions();
1748 if (xoptions == NULL)
1749 return -1;
1750
1751 key = PyUnicode_FromString("tracemalloc");
1752 if (key == NULL)
1753 return -1;
1754
1755 value = PyDict_GetItemWithError(xoptions, key);
1756 Py_DECREF(key);
1757 if (value == NULL) {
1758 if (PyErr_Occurred())
1759 return -1;
1760
1761 /* -X tracemalloc is not used */
1762 return 0;
1763 }
1764
1765 nframe = parse_sys_xoptions(value);
1766 Py_DECREF(value);
1767 if (nframe < 0) {
Victor Stinnerf28ce602013-11-27 22:27:13 +01001768 Py_FatalError("-X tracemalloc=NFRAME: invalid number of frames");
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001769 }
1770 }
1771
Victor Stinnerf28ce602013-11-27 22:27:13 +01001772 return tracemalloc_start(nframe);
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001773}
1774
Victor Stinnere492ae52016-03-22 12:58:23 +01001775
Victor Stinnerbe0708f2013-12-01 10:03:26 +01001776void
1777_PyTraceMalloc_Fini(void)
1778{
1779#ifdef WITH_THREAD
1780 assert(PyGILState_Check());
1781#endif
1782 tracemalloc_deinit();
1783}
Victor Stinner10b73e12016-03-22 13:39:05 +01001784
1785int
Victor Stinner5ea4c062017-06-20 17:46:36 +02001786PyTraceMalloc_Track(unsigned int domain, uintptr_t ptr,
1787 size_t size)
Victor Stinner10b73e12016-03-22 13:39:05 +01001788{
1789 int res;
1790#ifdef WITH_THREAD
1791 PyGILState_STATE gil_state;
1792#endif
1793
1794 if (!tracemalloc_config.tracing) {
1795 /* tracemalloc is not tracing: do nothing */
1796 return -2;
1797 }
1798
1799#ifdef WITH_THREAD
1800 gil_state = PyGILState_Ensure();
1801#endif
1802
1803 TABLES_LOCK();
1804 res = tracemalloc_add_trace(domain, ptr, size);
1805 TABLES_UNLOCK();
1806
1807#ifdef WITH_THREAD
1808 PyGILState_Release(gil_state);
1809#endif
1810 return res;
1811}
1812
1813
1814int
Victor Stinner5ea4c062017-06-20 17:46:36 +02001815PyTraceMalloc_Untrack(unsigned int domain, uintptr_t ptr)
Victor Stinner10b73e12016-03-22 13:39:05 +01001816{
1817 if (!tracemalloc_config.tracing) {
1818 /* tracemalloc is not tracing: do nothing */
1819 return -2;
1820 }
1821
1822 TABLES_LOCK();
1823 tracemalloc_remove_trace(domain, ptr);
1824 TABLES_UNLOCK();
1825
1826 return 0;
1827}
1828
1829
1830PyObject*
Victor Stinner5ea4c062017-06-20 17:46:36 +02001831_PyTraceMalloc_GetTraceback(unsigned int domain, uintptr_t ptr)
Victor Stinner10b73e12016-03-22 13:39:05 +01001832{
1833 traceback_t *traceback;
1834
1835 traceback = tracemalloc_get_traceback(domain, ptr);
1836 if (traceback == NULL)
1837 Py_RETURN_NONE;
1838
1839 return traceback_to_pyobject(traceback, NULL);
1840}