blob: 86cdbd28b4eb6b5378581b8ea77a0322ba21edce [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
7/* Trace memory blocks allocated by PyMem_RawMalloc() */
8#define TRACE_RAW_MALLOC
9
10/* Forward declaration */
11static void tracemalloc_stop(void);
Victor Stinnered3b0bc2013-11-23 12:27:24 +010012static void* raw_malloc(size_t size);
13static void raw_free(void *ptr);
14
15#ifdef Py_DEBUG
16# define TRACE_DEBUG
17#endif
18
Victor Stinnered3b0bc2013-11-23 12:27:24 +010019/* Protected by the GIL */
20static struct {
Victor Stinnerd8f0d922014-06-02 21:57:10 +020021 PyMemAllocatorEx mem;
22 PyMemAllocatorEx raw;
23 PyMemAllocatorEx obj;
Victor Stinnered3b0bc2013-11-23 12:27:24 +010024} allocators;
25
Victor Stinnered3b0bc2013-11-23 12:27:24 +010026static struct {
27 /* Module initialized?
28 Variable protected by the GIL */
29 enum {
30 TRACEMALLOC_NOT_INITIALIZED,
31 TRACEMALLOC_INITIALIZED,
32 TRACEMALLOC_FINALIZED
33 } initialized;
34
Victor Stinnered3b0bc2013-11-23 12:27:24 +010035 /* Is tracemalloc tracing memory allocations?
36 Variable protected by the GIL */
37 int tracing;
38
39 /* limit of the number of frames in a traceback, 1 by default.
40 Variable protected by the GIL. */
41 int max_nframe;
Victor Stinnere492ae52016-03-22 12:58:23 +010042
43 /* use domain in trace key?
44 Variable protected by the GIL. */
45 int use_domain;
Victor Stinner5e14a382016-03-23 22:03:55 +010046} tracemalloc_config = {TRACEMALLOC_NOT_INITIALIZED, 0, 1, 0};
Victor Stinnered3b0bc2013-11-23 12:27:24 +010047
48#if defined(TRACE_RAW_MALLOC) && defined(WITH_THREAD)
49/* This lock is needed because tracemalloc_free() is called without
50 the GIL held from PyMem_RawFree(). It cannot acquire the lock because it
51 would introduce a deadlock in PyThreadState_DeleteCurrent(). */
52static PyThread_type_lock tables_lock;
53# define TABLES_LOCK() PyThread_acquire_lock(tables_lock, 1)
54# define TABLES_UNLOCK() PyThread_release_lock(tables_lock)
55#else
56 /* variables are protected by the GIL */
57# define TABLES_LOCK()
58# define TABLES_UNLOCK()
59#endif
60
Victor Stinnere492ae52016-03-22 12:58:23 +010061
62#define DEFAULT_DOMAIN 0
63
Victor Stinnere492ae52016-03-22 12:58:23 +010064/* Pack the frame_t structure to reduce the memory footprint. */
65typedef struct
66#ifdef __GNUC__
67__attribute__((packed))
68#endif
69{
70 Py_uintptr_t ptr;
Victor Stinner10b73e12016-03-22 13:39:05 +010071 _PyTraceMalloc_domain_t domain;
Victor Stinnere492ae52016-03-22 12:58:23 +010072} pointer_t;
73
Victor Stinnered3b0bc2013-11-23 12:27:24 +010074/* Pack the frame_t structure to reduce the memory footprint on 64-bit
Victor Stinnere492ae52016-03-22 12:58:23 +010075 architectures: 12 bytes instead of 16. */
Victor Stinnered3b0bc2013-11-23 12:27:24 +010076typedef struct
77#ifdef __GNUC__
78__attribute__((packed))
Victor Stinnerdd382ef2014-02-01 03:43:58 +010079#elif defined(_MSC_VER)
80_declspec(align(4))
Victor Stinnered3b0bc2013-11-23 12:27:24 +010081#endif
82{
Victor Stinner7105e9f2016-03-15 14:28:04 +010083 /* filename cannot be NULL: "<unknown>" is used if the Python frame
84 filename is NULL */
Victor Stinnered3b0bc2013-11-23 12:27:24 +010085 PyObject *filename;
Victor Stinner95283342016-03-15 21:57:02 +010086 unsigned int lineno;
Victor Stinnered3b0bc2013-11-23 12:27:24 +010087} frame_t;
88
Victor Stinnere492ae52016-03-22 12:58:23 +010089
Victor Stinnered3b0bc2013-11-23 12:27:24 +010090typedef struct {
91 Py_uhash_t hash;
92 int nframe;
93 frame_t frames[1];
94} traceback_t;
95
96#define TRACEBACK_SIZE(NFRAME) \
97 (sizeof(traceback_t) + sizeof(frame_t) * (NFRAME - 1))
Victor Stinnerf28ce602013-11-27 22:27:13 +010098
99#define MAX_NFRAME \
Victor Stinner52aee852014-08-16 15:44:02 +0200100 ((INT_MAX - (int)sizeof(traceback_t)) / (int)sizeof(frame_t) + 1)
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100101
Victor Stinnere492ae52016-03-22 12:58:23 +0100102
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100103static PyObject *unknown_filename = NULL;
104static traceback_t tracemalloc_empty_traceback;
105
Victor Stinner7a5be142013-11-26 01:06:02 +0100106/* Trace of a memory block */
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100107typedef struct {
Victor Stinner7a5be142013-11-26 01:06:02 +0100108 /* Size of the memory block in bytes */
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100109 size_t size;
Victor Stinner7a5be142013-11-26 01:06:02 +0100110
111 /* Traceback where the memory block was allocated */
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100112 traceback_t *traceback;
113} trace_t;
114
Victor Stinnere492ae52016-03-22 12:58:23 +0100115
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100116/* Size in bytes of currently traced memory.
117 Protected by TABLES_LOCK(). */
118static size_t tracemalloc_traced_memory = 0;
119
Victor Stinner3c0481d2013-11-27 21:39:49 +0100120/* Peak size in bytes of traced memory.
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100121 Protected by TABLES_LOCK(). */
Victor Stinner3c0481d2013-11-27 21:39:49 +0100122static size_t tracemalloc_peak_traced_memory = 0;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100123
Serhiy Storchaka56a6d852014-12-01 18:28:43 +0200124/* Hash table used as a set to intern filenames:
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100125 PyObject* => PyObject*.
126 Protected by the GIL */
127static _Py_hashtable_t *tracemalloc_filenames = NULL;
128
Victor Stinnerf28ce602013-11-27 22:27:13 +0100129/* Buffer to store a new traceback in traceback_new().
130 Protected by the GIL. */
131static traceback_t *tracemalloc_traceback = NULL;
132
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100133/* Hash table used as a set to intern tracebacks:
134 traceback_t* => traceback_t*
135 Protected by the GIL */
136static _Py_hashtable_t *tracemalloc_tracebacks = NULL;
137
138/* pointer (void*) => trace (trace_t).
139 Protected by TABLES_LOCK(). */
140static _Py_hashtable_t *tracemalloc_traces = NULL;
141
Victor Stinnere492ae52016-03-22 12:58:23 +0100142
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100143#ifdef TRACE_DEBUG
144static void
145tracemalloc_error(const char *format, ...)
146{
147 va_list ap;
148 fprintf(stderr, "tracemalloc: ");
149 va_start(ap, format);
150 vfprintf(stderr, format, ap);
151 va_end(ap);
152 fprintf(stderr, "\n");
153 fflush(stderr);
154}
155#endif
156
Victor Stinnere492ae52016-03-22 12:58:23 +0100157
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100158#if defined(WITH_THREAD) && defined(TRACE_RAW_MALLOC)
159#define REENTRANT_THREADLOCAL
160
161/* If your OS does not provide native thread local storage, you can implement
162 it manually using a lock. Functions of thread.c cannot be used because
163 they use PyMem_RawMalloc() which leads to a reentrant call. */
164#if !(defined(_POSIX_THREADS) || defined(NT_THREADS))
165# error "need native thread local storage (TLS)"
166#endif
167
Victor Stinner4a066472016-03-22 17:45:09 +0100168static int tracemalloc_reentrant_key = -1;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100169
170/* Any non-NULL pointer can be used */
171#define REENTRANT Py_True
172
173static int
174get_reentrant(void)
175{
Victor Stinner4a066472016-03-22 17:45:09 +0100176 void *ptr;
177
178 assert(tracemalloc_reentrant_key != -1);
179 ptr = PyThread_get_key_value(tracemalloc_reentrant_key);
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100180 if (ptr != NULL) {
181 assert(ptr == REENTRANT);
182 return 1;
183 }
184 else
185 return 0;
186}
187
188static void
189set_reentrant(int reentrant)
190{
Victor Stinner2ead3d22013-11-26 01:08:53 +0100191 assert(reentrant == 0 || reentrant == 1);
Victor Stinner4a066472016-03-22 17:45:09 +0100192 assert(tracemalloc_reentrant_key != -1);
193
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100194 if (reentrant) {
Victor Stinner0cfc0582016-03-22 17:40:07 +0100195 assert(!get_reentrant());
Victor Stinner590cebe2013-12-13 11:08:56 +0100196 PyThread_set_key_value(tracemalloc_reentrant_key, REENTRANT);
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100197 }
198 else {
Victor Stinner0cfc0582016-03-22 17:40:07 +0100199 assert(get_reentrant());
Victor Stinner590cebe2013-12-13 11:08:56 +0100200 PyThread_set_key_value(tracemalloc_reentrant_key, NULL);
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100201 }
202}
203
204#else
205
206/* WITH_THREAD not defined: Python compiled without threads,
207 or TRACE_RAW_MALLOC not defined: variable protected by the GIL */
208static int tracemalloc_reentrant = 0;
209
210static int
211get_reentrant(void)
212{
213 return tracemalloc_reentrant;
214}
215
216static void
217set_reentrant(int reentrant)
218{
Victor Stinnerd5871e62016-03-23 00:17:04 +0100219 assert(reentrant != tracemalloc_reentrant);
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100220 tracemalloc_reentrant = reentrant;
221}
222#endif
223
Victor Stinnere492ae52016-03-22 12:58:23 +0100224
Victor Stinner285cf0a2016-03-21 22:00:58 +0100225static Py_uhash_t
Victor Stinner5dacbd42016-03-23 09:52:13 +0100226hashtable_hash_pyobject(_Py_hashtable_t *ht, const void *pkey)
Victor Stinner51b846c2016-03-18 21:52:22 +0100227{
Victor Stinner285cf0a2016-03-21 22:00:58 +0100228 PyObject *obj;
229
Victor Stinner5dacbd42016-03-23 09:52:13 +0100230 _Py_HASHTABLE_READ_KEY(ht, pkey, obj);
Victor Stinner285cf0a2016-03-21 22:00:58 +0100231 return PyObject_Hash(obj);
232}
233
Victor Stinnere492ae52016-03-22 12:58:23 +0100234
Victor Stinner285cf0a2016-03-21 22:00:58 +0100235static int
Victor Stinner5dacbd42016-03-23 09:52:13 +0100236hashtable_compare_unicode(_Py_hashtable_t *ht, const void *pkey,
Victor Stinner285cf0a2016-03-21 22:00:58 +0100237 const _Py_hashtable_entry_t *entry)
238{
Victor Stinnere492ae52016-03-22 12:58:23 +0100239 PyObject *key1, *key2;
Victor Stinner285cf0a2016-03-21 22:00:58 +0100240
Victor Stinner5dacbd42016-03-23 09:52:13 +0100241 _Py_HASHTABLE_READ_KEY(ht, pkey, key1);
242 _Py_HASHTABLE_ENTRY_READ_KEY(ht, entry, key2);
Victor Stinner285cf0a2016-03-21 22:00:58 +0100243
Victor Stinnere492ae52016-03-22 12:58:23 +0100244 if (key1 != NULL && key2 != NULL)
245 return (PyUnicode_Compare(key1, key2) == 0);
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100246 else
Victor Stinnere492ae52016-03-22 12:58:23 +0100247 return key1 == key2;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100248}
249
Victor Stinnere492ae52016-03-22 12:58:23 +0100250
251static Py_uhash_t
Victor Stinner5dacbd42016-03-23 09:52:13 +0100252hashtable_hash_pointer_t(_Py_hashtable_t *ht, const void *pkey)
Victor Stinnere492ae52016-03-22 12:58:23 +0100253{
254 pointer_t ptr;
255 Py_uhash_t hash;
256
Victor Stinner5dacbd42016-03-23 09:52:13 +0100257 _Py_HASHTABLE_READ_KEY(ht, pkey, ptr);
Victor Stinnere492ae52016-03-22 12:58:23 +0100258
259 hash = (Py_uhash_t)_Py_HashPointer((void*)ptr.ptr);
260 hash ^= ptr.domain;
261 return hash;
262}
263
264
265int
Victor Stinner5dacbd42016-03-23 09:52:13 +0100266hashtable_compare_pointer_t(_Py_hashtable_t *ht, const void *pkey,
Victor Stinnere492ae52016-03-22 12:58:23 +0100267 const _Py_hashtable_entry_t *entry)
268{
269 pointer_t ptr1, ptr2;
270
Victor Stinner5dacbd42016-03-23 09:52:13 +0100271 _Py_HASHTABLE_READ_KEY(ht, pkey, ptr1);
272 _Py_HASHTABLE_ENTRY_READ_KEY(ht, entry, ptr2);
Victor Stinnere492ae52016-03-22 12:58:23 +0100273
274 /* compare pointer before domain, because pointer is more likely to be
275 different */
276 return (ptr1.ptr == ptr2.ptr && ptr1.domain == ptr2.domain);
277
278}
279
280
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100281static _Py_hashtable_t *
Victor Stinner285cf0a2016-03-21 22:00:58 +0100282hashtable_new(size_t key_size, size_t data_size,
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100283 _Py_hashtable_hash_func hash_func,
284 _Py_hashtable_compare_func compare_func)
285{
Victor Stinnerc9553872016-03-22 12:13:01 +0100286 _Py_hashtable_allocator_t hashtable_alloc = {malloc, free};
Victor Stinner285cf0a2016-03-21 22:00:58 +0100287 return _Py_hashtable_new_full(key_size, data_size, 0,
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100288 hash_func, compare_func,
Victor Stinnerc9553872016-03-22 12:13:01 +0100289 &hashtable_alloc);
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100290}
291
Victor Stinnere492ae52016-03-22 12:58:23 +0100292
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100293static void*
294raw_malloc(size_t size)
295{
296 return allocators.raw.malloc(allocators.raw.ctx, size);
297}
298
299static void
300raw_free(void *ptr)
301{
302 allocators.raw.free(allocators.raw.ctx, ptr);
303}
304
Victor Stinnere492ae52016-03-22 12:58:23 +0100305
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100306static Py_uhash_t
Victor Stinner5dacbd42016-03-23 09:52:13 +0100307hashtable_hash_traceback(_Py_hashtable_t *ht, const void *pkey)
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100308{
Victor Stinnerb32a7ed2016-03-21 23:05:08 +0100309 traceback_t *traceback;
Victor Stinner285cf0a2016-03-21 22:00:58 +0100310
Victor Stinner5dacbd42016-03-23 09:52:13 +0100311 _Py_HASHTABLE_READ_KEY(ht, pkey, traceback);
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100312 return traceback->hash;
313}
314
Victor Stinnere492ae52016-03-22 12:58:23 +0100315
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100316static int
Victor Stinner5dacbd42016-03-23 09:52:13 +0100317hashtable_compare_traceback(_Py_hashtable_t *ht, const void *pkey,
318 const _Py_hashtable_entry_t *entry)
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100319{
Victor Stinner285cf0a2016-03-21 22:00:58 +0100320 traceback_t *traceback1, *traceback2;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100321 const frame_t *frame1, *frame2;
322 int i;
323
Victor Stinner5dacbd42016-03-23 09:52:13 +0100324 _Py_HASHTABLE_READ_KEY(ht, pkey, traceback1);
325 _Py_HASHTABLE_ENTRY_READ_KEY(ht, entry, traceback2);
Victor Stinner285cf0a2016-03-21 22:00:58 +0100326
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100327 if (traceback1->nframe != traceback2->nframe)
328 return 0;
329
330 for (i=0; i < traceback1->nframe; i++) {
331 frame1 = &traceback1->frames[i];
332 frame2 = &traceback2->frames[i];
333
334 if (frame1->lineno != frame2->lineno)
335 return 0;
336
337 if (frame1->filename != frame2->filename) {
338 assert(PyUnicode_Compare(frame1->filename, frame2->filename) != 0);
339 return 0;
340 }
341 }
342 return 1;
343}
344
Victor Stinnere492ae52016-03-22 12:58:23 +0100345
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100346static void
347tracemalloc_get_frame(PyFrameObject *pyframe, frame_t *frame)
348{
349 PyCodeObject *code;
350 PyObject *filename;
351 _Py_hashtable_entry_t *entry;
Victor Stinner95283342016-03-15 21:57:02 +0100352 int lineno;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100353
354 frame->filename = unknown_filename;
Victor Stinner95283342016-03-15 21:57:02 +0100355 lineno = PyFrame_GetLineNumber(pyframe);
356 if (lineno < 0)
357 lineno = 0;
358 frame->lineno = (unsigned int)lineno;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100359
360 code = pyframe->f_code;
361 if (code == NULL) {
362#ifdef TRACE_DEBUG
Victor Stinner4dc74202013-11-26 01:18:52 +0100363 tracemalloc_error("failed to get the code object of the frame");
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100364#endif
365 return;
366 }
367
368 if (code->co_filename == NULL) {
369#ifdef TRACE_DEBUG
370 tracemalloc_error("failed to get the filename of the code object");
371#endif
372 return;
373 }
374
375 filename = code->co_filename;
376 assert(filename != NULL);
377 if (filename == NULL)
378 return;
379
380 if (!PyUnicode_Check(filename)) {
381#ifdef TRACE_DEBUG
Martin Panter6245cb32016-04-15 02:14:19 +0000382 tracemalloc_error("filename is not a unicode string");
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100383#endif
384 return;
385 }
386 if (!PyUnicode_IS_READY(filename)) {
387 /* Don't make a Unicode string ready to avoid reentrant calls
388 to tracemalloc_malloc() or tracemalloc_realloc() */
389#ifdef TRACE_DEBUG
390 tracemalloc_error("filename is not a ready unicode string");
391#endif
392 return;
393 }
394
395 /* intern the filename */
Victor Stinner285cf0a2016-03-21 22:00:58 +0100396 entry = _Py_HASHTABLE_GET_ENTRY(tracemalloc_filenames, filename);
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100397 if (entry != NULL) {
Victor Stinner5dacbd42016-03-23 09:52:13 +0100398 _Py_HASHTABLE_ENTRY_READ_KEY(tracemalloc_filenames, entry, filename);
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100399 }
400 else {
401 /* tracemalloc_filenames is responsible to keep a reference
402 to the filename */
403 Py_INCREF(filename);
Victor Stinner285cf0a2016-03-21 22:00:58 +0100404 if (_Py_HASHTABLE_SET_NODATA(tracemalloc_filenames, filename) < 0) {
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100405 Py_DECREF(filename);
406#ifdef TRACE_DEBUG
407 tracemalloc_error("failed to intern the filename");
408#endif
409 return;
410 }
411 }
412
413 /* the tracemalloc_filenames table keeps a reference to the filename */
414 frame->filename = filename;
415}
416
Victor Stinnere492ae52016-03-22 12:58:23 +0100417
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100418static Py_uhash_t
419traceback_hash(traceback_t *traceback)
420{
421 /* code based on tuplehash() of Objects/tupleobject.c */
Victor Stinner4d8c29c2013-12-16 23:05:13 +0100422 Py_uhash_t x, y; /* Unsigned for defined overflow behavior. */
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100423 int len = traceback->nframe;
424 Py_uhash_t mult = _PyHASH_MULTIPLIER;
425 frame_t *frame;
426
427 x = 0x345678UL;
428 frame = traceback->frames;
429 while (--len >= 0) {
Victor Stinner4d8c29c2013-12-16 23:05:13 +0100430 y = (Py_uhash_t)PyObject_Hash(frame->filename);
431 y ^= (Py_uhash_t)frame->lineno;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100432 frame++;
433
434 x = (x ^ y) * mult;
435 /* the cast might truncate len; that doesn't change hash stability */
Victor Stinner4d8c29c2013-12-16 23:05:13 +0100436 mult += (Py_uhash_t)(82520UL + len + len);
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100437 }
438 x += 97531UL;
439 return x;
440}
441
Victor Stinnere492ae52016-03-22 12:58:23 +0100442
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100443static void
444traceback_get_frames(traceback_t *traceback)
445{
446 PyThreadState *tstate;
447 PyFrameObject *pyframe;
448
449#ifdef WITH_THREAD
450 tstate = PyGILState_GetThisThreadState();
451#else
452 tstate = PyThreadState_Get();
453#endif
454 if (tstate == NULL) {
455#ifdef TRACE_DEBUG
456 tracemalloc_error("failed to get the current thread state");
457#endif
458 return;
459 }
460
461 for (pyframe = tstate->frame; pyframe != NULL; pyframe = pyframe->f_back) {
462 tracemalloc_get_frame(pyframe, &traceback->frames[traceback->nframe]);
463 assert(traceback->frames[traceback->nframe].filename != NULL);
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100464 traceback->nframe++;
465 if (traceback->nframe == tracemalloc_config.max_nframe)
466 break;
467 }
468}
469
Victor Stinnere492ae52016-03-22 12:58:23 +0100470
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100471static traceback_t *
472traceback_new(void)
473{
Victor Stinnerf28ce602013-11-27 22:27:13 +0100474 traceback_t *traceback;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100475 _Py_hashtable_entry_t *entry;
476
477#ifdef WITH_THREAD
478 assert(PyGILState_Check());
479#endif
480
481 /* get frames */
Victor Stinnerf28ce602013-11-27 22:27:13 +0100482 traceback = tracemalloc_traceback;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100483 traceback->nframe = 0;
484 traceback_get_frames(traceback);
485 if (traceback->nframe == 0)
486 return &tracemalloc_empty_traceback;
487 traceback->hash = traceback_hash(traceback);
488
489 /* intern the traceback */
Victor Stinner285cf0a2016-03-21 22:00:58 +0100490 entry = _Py_HASHTABLE_GET_ENTRY(tracemalloc_tracebacks, traceback);
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100491 if (entry != NULL) {
Victor Stinner5dacbd42016-03-23 09:52:13 +0100492 _Py_HASHTABLE_ENTRY_READ_KEY(tracemalloc_tracebacks, entry, traceback);
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100493 }
494 else {
495 traceback_t *copy;
496 size_t traceback_size;
497
498 traceback_size = TRACEBACK_SIZE(traceback->nframe);
499
500 copy = raw_malloc(traceback_size);
501 if (copy == NULL) {
502#ifdef TRACE_DEBUG
503 tracemalloc_error("failed to intern the traceback: malloc failed");
504#endif
505 return NULL;
506 }
507 memcpy(copy, traceback, traceback_size);
508
Victor Stinner285cf0a2016-03-21 22:00:58 +0100509 if (_Py_HASHTABLE_SET_NODATA(tracemalloc_tracebacks, copy) < 0) {
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100510 raw_free(copy);
511#ifdef TRACE_DEBUG
512 tracemalloc_error("failed to intern the traceback: putdata failed");
513#endif
514 return NULL;
515 }
516 traceback = copy;
517 }
518 return traceback;
519}
520
Victor Stinnere492ae52016-03-22 12:58:23 +0100521
Victor Stinner5e14a382016-03-23 22:03:55 +0100522static int
523tracemalloc_use_domain_cb(_Py_hashtable_t *old_traces,
524 _Py_hashtable_entry_t *entry, void *user_data)
525{
526 Py_uintptr_t ptr;
527 pointer_t key;
528 _Py_hashtable_t *new_traces = (_Py_hashtable_t *)user_data;
529 const void *pdata = _Py_HASHTABLE_ENTRY_PDATA(old_traces, entry);
530
531 _Py_HASHTABLE_ENTRY_READ_KEY(old_traces, entry, ptr);
532 key.ptr = ptr;
533 key.domain = DEFAULT_DOMAIN;
534
535 return _Py_hashtable_set(new_traces,
536 sizeof(key), &key,
537 old_traces->data_size, pdata);
538}
539
540
541/* Convert tracemalloc_traces from compact key (Py_uintptr_t) to pointer_t key.
542 * Return 0 on success, -1 on error. */
543static int
544tracemalloc_use_domain(void)
545{
546 _Py_hashtable_t *new_traces = NULL;
547
548 assert(!tracemalloc_config.use_domain);
549
550 new_traces = hashtable_new(sizeof(pointer_t),
551 sizeof(trace_t),
552 hashtable_hash_pointer_t,
553 hashtable_compare_pointer_t);
554 if (new_traces == NULL) {
555 return -1;
556 }
557
558 if (_Py_hashtable_foreach(tracemalloc_traces, tracemalloc_use_domain_cb,
559 new_traces) < 0)
560 {
561 _Py_hashtable_destroy(new_traces);
562 return -1;
563 }
564
565 _Py_hashtable_destroy(tracemalloc_traces);
566 tracemalloc_traces = new_traces;
567
568 tracemalloc_config.use_domain = 1;
569
570 return 0;
571}
572
573
Victor Stinnere492ae52016-03-22 12:58:23 +0100574static void
Victor Stinner10b73e12016-03-22 13:39:05 +0100575tracemalloc_remove_trace(_PyTraceMalloc_domain_t domain, Py_uintptr_t ptr)
Victor Stinnere492ae52016-03-22 12:58:23 +0100576{
577 trace_t trace;
578 int removed;
579
Victor Stinner10b73e12016-03-22 13:39:05 +0100580 assert(tracemalloc_config.tracing);
581
Victor Stinnere492ae52016-03-22 12:58:23 +0100582 if (tracemalloc_config.use_domain) {
583 pointer_t key = {ptr, domain};
584 removed = _Py_HASHTABLE_POP(tracemalloc_traces, key, trace);
585 }
586 else {
587 removed = _Py_HASHTABLE_POP(tracemalloc_traces, ptr, trace);
588 }
589 if (!removed) {
590 return;
591 }
592
593 assert(tracemalloc_traced_memory >= trace.size);
594 tracemalloc_traced_memory -= trace.size;
595}
596
597#define REMOVE_TRACE(ptr) \
598 tracemalloc_remove_trace(DEFAULT_DOMAIN, (Py_uintptr_t)(ptr))
599
600
Victor Stinner52968672013-11-24 11:37:15 +0100601static int
Victor Stinner10b73e12016-03-22 13:39:05 +0100602tracemalloc_add_trace(_PyTraceMalloc_domain_t domain, Py_uintptr_t ptr,
603 size_t size)
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100604{
Victor Stinnerca79ccd2016-03-23 09:38:54 +0100605 pointer_t key = {ptr, domain};
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100606 traceback_t *traceback;
607 trace_t trace;
Victor Stinnerca79ccd2016-03-23 09:38:54 +0100608 _Py_hashtable_entry_t* entry;
Victor Stinner52968672013-11-24 11:37:15 +0100609 int res;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100610
Victor Stinner10b73e12016-03-22 13:39:05 +0100611 assert(tracemalloc_config.tracing);
612
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100613 traceback = traceback_new();
Victor Stinnere492ae52016-03-22 12:58:23 +0100614 if (traceback == NULL) {
Victor Stinner52968672013-11-24 11:37:15 +0100615 return -1;
Victor Stinnere492ae52016-03-22 12:58:23 +0100616 }
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100617
Victor Stinner5e14a382016-03-23 22:03:55 +0100618 if (!tracemalloc_config.use_domain && domain != DEFAULT_DOMAIN) {
619 /* first trace using a non-zero domain whereas traces use compact
620 (Py_uintptr_t) keys: switch to pointer_t keys. */
621 if (tracemalloc_use_domain() < 0) {
622 return -1;
623 }
624 }
625
Victor Stinnere492ae52016-03-22 12:58:23 +0100626 if (tracemalloc_config.use_domain) {
Victor Stinnerca79ccd2016-03-23 09:38:54 +0100627 entry = _Py_HASHTABLE_GET_ENTRY(tracemalloc_traces, key);
Victor Stinnere492ae52016-03-22 12:58:23 +0100628 }
629 else {
Victor Stinnerca79ccd2016-03-23 09:38:54 +0100630 entry = _Py_HASHTABLE_GET_ENTRY(tracemalloc_traces, ptr);
Victor Stinnerd606ba72013-11-24 11:28:20 +0100631 }
Victor Stinner52968672013-11-24 11:37:15 +0100632
Victor Stinnerca79ccd2016-03-23 09:38:54 +0100633 if (entry != NULL) {
634 /* the memory block is already tracked */
635 _Py_HASHTABLE_ENTRY_READ_DATA(tracemalloc_traces, entry, trace);
636 assert(tracemalloc_traced_memory >= trace.size);
637 tracemalloc_traced_memory -= trace.size;
638
639 trace.size = size;
640 trace.traceback = traceback;
641 _Py_HASHTABLE_ENTRY_WRITE_DATA(tracemalloc_traces, entry, trace);
642 }
643 else {
644 trace.size = size;
645 trace.traceback = traceback;
646
647 if (tracemalloc_config.use_domain) {
648 res = _Py_HASHTABLE_SET(tracemalloc_traces, key, trace);
649 }
650 else {
651 res = _Py_HASHTABLE_SET(tracemalloc_traces, ptr, trace);
652 }
653 if (res != 0) {
654 return res;
655 }
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100656 }
Victor Stinnere492ae52016-03-22 12:58:23 +0100657
658 assert(tracemalloc_traced_memory <= PY_SIZE_MAX - size);
659 tracemalloc_traced_memory += size;
660 if (tracemalloc_traced_memory > tracemalloc_peak_traced_memory)
661 tracemalloc_peak_traced_memory = tracemalloc_traced_memory;
662 return 0;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100663}
664
Victor Stinnere492ae52016-03-22 12:58:23 +0100665#define ADD_TRACE(ptr, size) \
666 tracemalloc_add_trace(DEFAULT_DOMAIN, (Py_uintptr_t)(ptr), size)
667
668
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100669static void*
Victor Stinnerdb067af2014-05-02 22:31:14 +0200670tracemalloc_alloc(int use_calloc, void *ctx, size_t nelem, size_t elsize)
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100671{
Victor Stinnerd8f0d922014-06-02 21:57:10 +0200672 PyMemAllocatorEx *alloc = (PyMemAllocatorEx *)ctx;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100673 void *ptr;
674
Victor Stinneraa0e7af2014-06-02 21:40:22 +0200675 assert(elsize == 0 || nelem <= PY_SIZE_MAX / elsize);
Victor Stinnerdb067af2014-05-02 22:31:14 +0200676
677 if (use_calloc)
678 ptr = alloc->calloc(alloc->ctx, nelem, elsize);
679 else
680 ptr = alloc->malloc(alloc->ctx, nelem * elsize);
Victor Stinner15116802013-12-04 01:29:35 +0100681 if (ptr == NULL)
682 return NULL;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100683
Victor Stinner88c29872013-12-04 01:47:46 +0100684 TABLES_LOCK();
Victor Stinnere492ae52016-03-22 12:58:23 +0100685 if (ADD_TRACE(ptr, nelem * elsize) < 0) {
Victor Stinner15116802013-12-04 01:29:35 +0100686 /* Failed to allocate a trace for the new memory block */
Victor Stinner88c29872013-12-04 01:47:46 +0100687 TABLES_UNLOCK();
Victor Stinner15116802013-12-04 01:29:35 +0100688 alloc->free(alloc->ctx, ptr);
689 return NULL;
Victor Stinner52968672013-11-24 11:37:15 +0100690 }
Victor Stinner88c29872013-12-04 01:47:46 +0100691 TABLES_UNLOCK();
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100692 return ptr;
693}
694
Victor Stinnere492ae52016-03-22 12:58:23 +0100695
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100696static void*
Victor Stinner15116802013-12-04 01:29:35 +0100697tracemalloc_realloc(void *ctx, void *ptr, size_t new_size)
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100698{
Victor Stinnerd8f0d922014-06-02 21:57:10 +0200699 PyMemAllocatorEx *alloc = (PyMemAllocatorEx *)ctx;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100700 void *ptr2;
701
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100702 ptr2 = alloc->realloc(alloc->ctx, ptr, new_size);
Victor Stinner15116802013-12-04 01:29:35 +0100703 if (ptr2 == NULL)
704 return NULL;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100705
Victor Stinner15116802013-12-04 01:29:35 +0100706 if (ptr != NULL) {
707 /* an existing memory block has been resized */
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100708
Victor Stinner88c29872013-12-04 01:47:46 +0100709 TABLES_LOCK();
Victor Stinner42bcf372016-03-23 09:08:08 +0100710
711 /* tracemalloc_add_trace() updates the trace if there is already
712 a trace at address (domain, ptr2) */
713 if (ptr2 != ptr) {
714 REMOVE_TRACE(ptr);
715 }
Victor Stinner08facd22013-11-24 12:27:59 +0100716
Victor Stinnere492ae52016-03-22 12:58:23 +0100717 if (ADD_TRACE(ptr2, new_size) < 0) {
Victor Stinner15116802013-12-04 01:29:35 +0100718 /* Memory allocation failed. The error cannot be reported to
719 the caller, because realloc() may already have shrinked the
720 memory block and so removed bytes.
721
Victor Stinner88c29872013-12-04 01:47:46 +0100722 This case is very unlikely: an hash entry has just been
723 released, so the hash table should have at least one free entry.
724
725 The GIL and the table lock ensures that only one thread is
726 allocating memory. */
727 assert(0 && "should never happen");
Victor Stinner52968672013-11-24 11:37:15 +0100728 }
Victor Stinner88c29872013-12-04 01:47:46 +0100729 TABLES_UNLOCK();
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100730 }
Victor Stinner15116802013-12-04 01:29:35 +0100731 else {
732 /* new allocation */
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100733
Victor Stinner88c29872013-12-04 01:47:46 +0100734 TABLES_LOCK();
Victor Stinnere492ae52016-03-22 12:58:23 +0100735 if (ADD_TRACE(ptr2, new_size) < 0) {
Victor Stinner15116802013-12-04 01:29:35 +0100736 /* Failed to allocate a trace for the new memory block */
Victor Stinner88c29872013-12-04 01:47:46 +0100737 TABLES_UNLOCK();
Victor Stinner15116802013-12-04 01:29:35 +0100738 alloc->free(alloc->ctx, ptr2);
739 return NULL;
740 }
Victor Stinner88c29872013-12-04 01:47:46 +0100741 TABLES_UNLOCK();
Victor Stinner15116802013-12-04 01:29:35 +0100742 }
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100743 return ptr2;
744}
745
Victor Stinnere492ae52016-03-22 12:58:23 +0100746
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100747static void
748tracemalloc_free(void *ctx, void *ptr)
749{
Victor Stinnerd8f0d922014-06-02 21:57:10 +0200750 PyMemAllocatorEx *alloc = (PyMemAllocatorEx *)ctx;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100751
752 if (ptr == NULL)
753 return;
754
755 /* GIL cannot be locked in PyMem_RawFree() because it would introduce
756 a deadlock in PyThreadState_DeleteCurrent(). */
757
758 alloc->free(alloc->ctx, ptr);
Victor Stinner88c29872013-12-04 01:47:46 +0100759
760 TABLES_LOCK();
Victor Stinnere492ae52016-03-22 12:58:23 +0100761 REMOVE_TRACE(ptr);
Victor Stinner88c29872013-12-04 01:47:46 +0100762 TABLES_UNLOCK();
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100763}
764
Victor Stinnere492ae52016-03-22 12:58:23 +0100765
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100766static void*
Victor Stinnerdb067af2014-05-02 22:31:14 +0200767tracemalloc_alloc_gil(int use_calloc, void *ctx, size_t nelem, size_t elsize)
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100768{
Victor Stinner15116802013-12-04 01:29:35 +0100769 void *ptr;
770
771 if (get_reentrant()) {
Victor Stinnerd8f0d922014-06-02 21:57:10 +0200772 PyMemAllocatorEx *alloc = (PyMemAllocatorEx *)ctx;
Victor Stinnerdb067af2014-05-02 22:31:14 +0200773 if (use_calloc)
774 return alloc->calloc(alloc->ctx, nelem, elsize);
775 else
776 return alloc->malloc(alloc->ctx, nelem * elsize);
Victor Stinner15116802013-12-04 01:29:35 +0100777 }
778
779 /* Ignore reentrant call. PyObjet_Malloc() calls PyMem_Malloc() for
780 allocations larger than 512 bytes, don't trace the same memory
781 allocation twice. */
782 set_reentrant(1);
783
Victor Stinnerdb067af2014-05-02 22:31:14 +0200784 ptr = tracemalloc_alloc(use_calloc, ctx, nelem, elsize);
Victor Stinner15116802013-12-04 01:29:35 +0100785
786 set_reentrant(0);
787 return ptr;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100788}
789
Victor Stinnere492ae52016-03-22 12:58:23 +0100790
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100791static void*
Victor Stinnerdb067af2014-05-02 22:31:14 +0200792tracemalloc_malloc_gil(void *ctx, size_t size)
793{
794 return tracemalloc_alloc_gil(0, ctx, 1, size);
795}
796
Victor Stinnere492ae52016-03-22 12:58:23 +0100797
Victor Stinnerdb067af2014-05-02 22:31:14 +0200798static void*
799tracemalloc_calloc_gil(void *ctx, size_t nelem, size_t elsize)
800{
801 return tracemalloc_alloc_gil(1, ctx, nelem, elsize);
802}
803
Victor Stinnere492ae52016-03-22 12:58:23 +0100804
Victor Stinnerdb067af2014-05-02 22:31:14 +0200805static void*
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100806tracemalloc_realloc_gil(void *ctx, void *ptr, size_t new_size)
807{
Victor Stinner15116802013-12-04 01:29:35 +0100808 void *ptr2;
809
810 if (get_reentrant()) {
811 /* Reentrant call to PyMem_Realloc() and PyMem_RawRealloc().
812 Example: PyMem_RawRealloc() is called internally by pymalloc
813 (_PyObject_Malloc() and _PyObject_Realloc()) to allocate a new
814 arena (new_arena()). */
Victor Stinnerd8f0d922014-06-02 21:57:10 +0200815 PyMemAllocatorEx *alloc = (PyMemAllocatorEx *)ctx;
Victor Stinner15116802013-12-04 01:29:35 +0100816
817 ptr2 = alloc->realloc(alloc->ctx, ptr, new_size);
Victor Stinner88c29872013-12-04 01:47:46 +0100818 if (ptr2 != NULL && ptr != NULL) {
819 TABLES_LOCK();
Victor Stinnere492ae52016-03-22 12:58:23 +0100820 REMOVE_TRACE(ptr);
Victor Stinner88c29872013-12-04 01:47:46 +0100821 TABLES_UNLOCK();
822 }
Victor Stinner15116802013-12-04 01:29:35 +0100823 return ptr2;
824 }
825
826 /* Ignore reentrant call. PyObjet_Realloc() calls PyMem_Realloc() for
827 allocations larger than 512 bytes. Don't trace the same memory
828 allocation twice. */
829 set_reentrant(1);
830
831 ptr2 = tracemalloc_realloc(ctx, ptr, new_size);
832
833 set_reentrant(0);
834 return ptr2;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100835}
836
Victor Stinnere492ae52016-03-22 12:58:23 +0100837
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100838#ifdef TRACE_RAW_MALLOC
839static void*
Victor Stinnerdb067af2014-05-02 22:31:14 +0200840tracemalloc_raw_alloc(int use_calloc, void *ctx, size_t nelem, size_t elsize)
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100841{
Victor Stinner15116802013-12-04 01:29:35 +0100842#ifdef WITH_THREAD
843 PyGILState_STATE gil_state;
844#endif
845 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
860#ifdef WITH_THREAD
861 gil_state = PyGILState_Ensure();
Victor Stinnerdb067af2014-05-02 22:31:14 +0200862 ptr = tracemalloc_alloc(use_calloc, ctx, nelem, elsize);
Victor Stinner15116802013-12-04 01:29:35 +0100863 PyGILState_Release(gil_state);
864#else
Victor Stinnerdb067af2014-05-02 22:31:14 +0200865 ptr = tracemalloc_alloc(use_calloc, ctx, nelem, elsize);
Victor Stinner15116802013-12-04 01:29:35 +0100866#endif
867
868 set_reentrant(0);
869 return ptr;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100870}
871
Victor Stinnere492ae52016-03-22 12:58:23 +0100872
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100873static void*
Victor Stinnerdb067af2014-05-02 22:31:14 +0200874tracemalloc_raw_malloc(void *ctx, size_t size)
875{
876 return tracemalloc_raw_alloc(0, ctx, 1, size);
877}
878
Victor Stinnere492ae52016-03-22 12:58:23 +0100879
Victor Stinnerdb067af2014-05-02 22:31:14 +0200880static void*
881tracemalloc_raw_calloc(void *ctx, size_t nelem, size_t elsize)
882{
883 return tracemalloc_raw_alloc(1, ctx, nelem, elsize);
884}
885
Victor Stinnere492ae52016-03-22 12:58:23 +0100886
Victor Stinnerdb067af2014-05-02 22:31:14 +0200887static void*
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100888tracemalloc_raw_realloc(void *ctx, void *ptr, size_t new_size)
889{
Victor Stinner15116802013-12-04 01:29:35 +0100890#ifdef WITH_THREAD
891 PyGILState_STATE gil_state;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100892#endif
Victor Stinner15116802013-12-04 01:29:35 +0100893 void *ptr2;
894
895 if (get_reentrant()) {
896 /* Reentrant call to PyMem_RawRealloc(). */
Victor Stinnerd8f0d922014-06-02 21:57:10 +0200897 PyMemAllocatorEx *alloc = (PyMemAllocatorEx *)ctx;
Victor Stinner15116802013-12-04 01:29:35 +0100898
899 ptr2 = alloc->realloc(alloc->ctx, ptr, new_size);
Victor Stinner15116802013-12-04 01:29:35 +0100900
Victor Stinner88c29872013-12-04 01:47:46 +0100901 if (ptr2 != NULL && ptr != NULL) {
902 TABLES_LOCK();
Victor Stinnere492ae52016-03-22 12:58:23 +0100903 REMOVE_TRACE(ptr);
Victor Stinner88c29872013-12-04 01:47:46 +0100904 TABLES_UNLOCK();
905 }
Victor Stinner15116802013-12-04 01:29:35 +0100906 return ptr2;
907 }
908
909 /* Ignore reentrant call. PyGILState_Ensure() may call PyMem_RawMalloc()
910 indirectly which would call PyGILState_Ensure() if reentrant calls are
911 not disabled. */
912 set_reentrant(1);
913
914#ifdef WITH_THREAD
915 gil_state = PyGILState_Ensure();
916 ptr2 = tracemalloc_realloc(ctx, ptr, new_size);
917 PyGILState_Release(gil_state);
918#else
919 ptr2 = tracemalloc_realloc(ctx, ptr, new_size);
920#endif
921
922 set_reentrant(0);
923 return ptr2;
924}
925#endif /* TRACE_RAW_MALLOC */
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100926
Victor Stinnere492ae52016-03-22 12:58:23 +0100927
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100928static int
Victor Stinner285cf0a2016-03-21 22:00:58 +0100929tracemalloc_clear_filename(_Py_hashtable_t *ht, _Py_hashtable_entry_t *entry,
930 void *user_data)
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100931{
Victor Stinner285cf0a2016-03-21 22:00:58 +0100932 PyObject *filename;
933
Victor Stinner5dacbd42016-03-23 09:52:13 +0100934 _Py_HASHTABLE_ENTRY_READ_KEY(ht, entry, filename);
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100935 Py_DECREF(filename);
936 return 0;
937}
938
Victor Stinnere492ae52016-03-22 12:58:23 +0100939
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100940static int
Victor Stinner285cf0a2016-03-21 22:00:58 +0100941traceback_free_traceback(_Py_hashtable_t *ht, _Py_hashtable_entry_t *entry,
942 void *user_data)
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100943{
Victor Stinner285cf0a2016-03-21 22:00:58 +0100944 traceback_t *traceback;
945
Victor Stinner5dacbd42016-03-23 09:52:13 +0100946 _Py_HASHTABLE_ENTRY_READ_KEY(ht, entry, traceback);
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100947 raw_free(traceback);
948 return 0;
949}
950
Victor Stinnere492ae52016-03-22 12:58:23 +0100951
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100952/* reentrant flag must be set to call this function and GIL must be held */
953static void
954tracemalloc_clear_traces(void)
955{
956#ifdef WITH_THREAD
957 /* The GIL protects variables againt concurrent access */
958 assert(PyGILState_Check());
959#endif
960
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100961 TABLES_LOCK();
962 _Py_hashtable_clear(tracemalloc_traces);
963 tracemalloc_traced_memory = 0;
Victor Stinner3c0481d2013-11-27 21:39:49 +0100964 tracemalloc_peak_traced_memory = 0;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100965 TABLES_UNLOCK();
966
967 _Py_hashtable_foreach(tracemalloc_tracebacks, traceback_free_traceback, NULL);
968 _Py_hashtable_clear(tracemalloc_tracebacks);
969
970 _Py_hashtable_foreach(tracemalloc_filenames, tracemalloc_clear_filename, NULL);
971 _Py_hashtable_clear(tracemalloc_filenames);
972}
973
Victor Stinnere492ae52016-03-22 12:58:23 +0100974
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100975static int
976tracemalloc_init(void)
977{
978 if (tracemalloc_config.initialized == TRACEMALLOC_FINALIZED) {
979 PyErr_SetString(PyExc_RuntimeError,
980 "the tracemalloc module has been unloaded");
981 return -1;
982 }
983
Victor Stinnerf9a71152016-03-22 23:54:42 +0100984 if (tracemalloc_config.initialized == TRACEMALLOC_INITIALIZED)
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100985 return 0;
986
987 PyMem_GetAllocator(PYMEM_DOMAIN_RAW, &allocators.raw);
988
989#ifdef REENTRANT_THREADLOCAL
990 tracemalloc_reentrant_key = PyThread_create_key();
991 if (tracemalloc_reentrant_key == -1) {
992#ifdef MS_WINDOWS
993 PyErr_SetFromWindowsErr(0);
994#else
995 PyErr_SetFromErrno(PyExc_OSError);
996#endif
997 return -1;
998 }
999#endif
1000
1001#if defined(WITH_THREAD) && defined(TRACE_RAW_MALLOC)
1002 if (tables_lock == NULL) {
1003 tables_lock = PyThread_allocate_lock();
1004 if (tables_lock == NULL) {
1005 PyErr_SetString(PyExc_RuntimeError, "cannot allocate lock");
1006 return -1;
1007 }
1008 }
1009#endif
1010
Victor Stinner285cf0a2016-03-21 22:00:58 +01001011 tracemalloc_filenames = hashtable_new(sizeof(PyObject *), 0,
1012 hashtable_hash_pyobject,
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001013 hashtable_compare_unicode);
1014
Victor Stinner285cf0a2016-03-21 22:00:58 +01001015 tracemalloc_tracebacks = hashtable_new(sizeof(traceback_t *), 0,
1016 hashtable_hash_traceback,
1017 hashtable_compare_traceback);
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001018
Victor Stinnere492ae52016-03-22 12:58:23 +01001019 if (tracemalloc_config.use_domain) {
1020 tracemalloc_traces = hashtable_new(sizeof(pointer_t),
1021 sizeof(trace_t),
1022 hashtable_hash_pointer_t,
1023 hashtable_compare_pointer_t);
1024 }
1025 else {
1026 tracemalloc_traces = hashtable_new(sizeof(Py_uintptr_t),
1027 sizeof(trace_t),
1028 _Py_hashtable_hash_ptr,
1029 _Py_hashtable_compare_direct);
1030 }
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001031
1032 if (tracemalloc_filenames == NULL || tracemalloc_tracebacks == NULL
Victor Stinner285cf0a2016-03-21 22:00:58 +01001033 || tracemalloc_traces == NULL) {
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001034 PyErr_NoMemory();
1035 return -1;
1036 }
1037
1038 unknown_filename = PyUnicode_FromString("<unknown>");
1039 if (unknown_filename == NULL)
1040 return -1;
1041 PyUnicode_InternInPlace(&unknown_filename);
1042
1043 tracemalloc_empty_traceback.nframe = 1;
1044 /* borrowed reference */
1045 tracemalloc_empty_traceback.frames[0].filename = unknown_filename;
1046 tracemalloc_empty_traceback.frames[0].lineno = 0;
1047 tracemalloc_empty_traceback.hash = traceback_hash(&tracemalloc_empty_traceback);
1048
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001049 tracemalloc_config.initialized = TRACEMALLOC_INITIALIZED;
1050 return 0;
1051}
1052
Victor Stinnere492ae52016-03-22 12:58:23 +01001053
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001054static void
1055tracemalloc_deinit(void)
1056{
Victor Stinnerf9a71152016-03-22 23:54:42 +01001057 if (tracemalloc_config.initialized != TRACEMALLOC_INITIALIZED)
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001058 return;
1059 tracemalloc_config.initialized = TRACEMALLOC_FINALIZED;
1060
1061 tracemalloc_stop();
1062
1063 /* destroy hash tables */
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001064 _Py_hashtable_destroy(tracemalloc_tracebacks);
1065 _Py_hashtable_destroy(tracemalloc_filenames);
Victor Stinner285cf0a2016-03-21 22:00:58 +01001066 _Py_hashtable_destroy(tracemalloc_traces);
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001067
1068#if defined(WITH_THREAD) && defined(TRACE_RAW_MALLOC)
1069 if (tables_lock != NULL) {
1070 PyThread_free_lock(tables_lock);
1071 tables_lock = NULL;
1072 }
1073#endif
1074
1075#ifdef REENTRANT_THREADLOCAL
1076 PyThread_delete_key(tracemalloc_reentrant_key);
Victor Stinner4a066472016-03-22 17:45:09 +01001077 tracemalloc_reentrant_key = -1;
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001078#endif
1079
1080 Py_XDECREF(unknown_filename);
1081}
1082
Victor Stinnere492ae52016-03-22 12:58:23 +01001083
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001084static int
Victor Stinnerf28ce602013-11-27 22:27:13 +01001085tracemalloc_start(int max_nframe)
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001086{
Victor Stinnerd8f0d922014-06-02 21:57:10 +02001087 PyMemAllocatorEx alloc;
Victor Stinnerf28ce602013-11-27 22:27:13 +01001088 size_t size;
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001089
Victor Stinnerf9a71152016-03-22 23:54:42 +01001090 if (tracemalloc_init() < 0)
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001091 return -1;
1092
1093 if (tracemalloc_config.tracing) {
1094 /* hook already installed: do nothing */
1095 return 0;
1096 }
1097
Victor Stinner52aee852014-08-16 15:44:02 +02001098 assert(1 <= max_nframe && max_nframe <= MAX_NFRAME);
Victor Stinnerf28ce602013-11-27 22:27:13 +01001099 tracemalloc_config.max_nframe = max_nframe;
1100
1101 /* allocate a buffer to store a new traceback */
1102 size = TRACEBACK_SIZE(max_nframe);
1103 assert(tracemalloc_traceback == NULL);
1104 tracemalloc_traceback = raw_malloc(size);
1105 if (tracemalloc_traceback == NULL) {
1106 PyErr_NoMemory();
1107 return -1;
1108 }
1109
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001110#ifdef TRACE_RAW_MALLOC
1111 alloc.malloc = tracemalloc_raw_malloc;
Victor Stinnerdb067af2014-05-02 22:31:14 +02001112 alloc.calloc = tracemalloc_raw_calloc;
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001113 alloc.realloc = tracemalloc_raw_realloc;
1114 alloc.free = tracemalloc_free;
1115
1116 alloc.ctx = &allocators.raw;
1117 PyMem_GetAllocator(PYMEM_DOMAIN_RAW, &allocators.raw);
1118 PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &alloc);
1119#endif
1120
1121 alloc.malloc = tracemalloc_malloc_gil;
Victor Stinnerdb067af2014-05-02 22:31:14 +02001122 alloc.calloc = tracemalloc_calloc_gil;
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001123 alloc.realloc = tracemalloc_realloc_gil;
1124 alloc.free = tracemalloc_free;
1125
1126 alloc.ctx = &allocators.mem;
1127 PyMem_GetAllocator(PYMEM_DOMAIN_MEM, &allocators.mem);
1128 PyMem_SetAllocator(PYMEM_DOMAIN_MEM, &alloc);
1129
1130 alloc.ctx = &allocators.obj;
1131 PyMem_GetAllocator(PYMEM_DOMAIN_OBJ, &allocators.obj);
1132 PyMem_SetAllocator(PYMEM_DOMAIN_OBJ, &alloc);
1133
1134 /* everything is ready: start tracing Python memory allocations */
1135 tracemalloc_config.tracing = 1;
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001136
1137 return 0;
1138}
1139
Victor Stinnere492ae52016-03-22 12:58:23 +01001140
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001141static void
1142tracemalloc_stop(void)
1143{
Victor Stinnerf9a71152016-03-22 23:54:42 +01001144 if (!tracemalloc_config.tracing)
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001145 return;
1146
1147 /* stop tracing Python memory allocations */
1148 tracemalloc_config.tracing = 0;
1149
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001150 /* unregister the hook on memory allocators */
1151#ifdef TRACE_RAW_MALLOC
1152 PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &allocators.raw);
1153#endif
1154 PyMem_SetAllocator(PYMEM_DOMAIN_MEM, &allocators.mem);
1155 PyMem_SetAllocator(PYMEM_DOMAIN_OBJ, &allocators.obj);
1156
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001157 tracemalloc_clear_traces();
Victor Stinner285cf0a2016-03-21 22:00:58 +01001158
1159 /* release memory */
Victor Stinnerf28ce602013-11-27 22:27:13 +01001160 raw_free(tracemalloc_traceback);
1161 tracemalloc_traceback = NULL;
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001162}
1163
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001164PyDoc_STRVAR(tracemalloc_is_tracing_doc,
1165 "is_tracing()->bool\n"
1166 "\n"
1167 "True if the tracemalloc module is tracing Python memory allocations,\n"
1168 "False otherwise.");
1169
Victor Stinnere492ae52016-03-22 12:58:23 +01001170
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001171static PyObject*
1172py_tracemalloc_is_tracing(PyObject *self)
1173{
1174 return PyBool_FromLong(tracemalloc_config.tracing);
1175}
1176
1177PyDoc_STRVAR(tracemalloc_clear_traces_doc,
1178 "clear_traces()\n"
1179 "\n"
1180 "Clear traces of memory blocks allocated by Python.");
1181
Victor Stinnere492ae52016-03-22 12:58:23 +01001182
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001183static PyObject*
1184py_tracemalloc_clear_traces(PyObject *self)
1185{
1186 if (!tracemalloc_config.tracing)
1187 Py_RETURN_NONE;
1188
1189 set_reentrant(1);
1190 tracemalloc_clear_traces();
1191 set_reentrant(0);
1192
1193 Py_RETURN_NONE;
1194}
1195
Victor Stinnere492ae52016-03-22 12:58:23 +01001196
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001197static PyObject*
1198frame_to_pyobject(frame_t *frame)
1199{
1200 PyObject *frame_obj, *lineno_obj;
1201
1202 frame_obj = PyTuple_New(2);
1203 if (frame_obj == NULL)
1204 return NULL;
1205
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001206 Py_INCREF(frame->filename);
1207 PyTuple_SET_ITEM(frame_obj, 0, frame->filename);
1208
Victor Stinner95283342016-03-15 21:57:02 +01001209 lineno_obj = PyLong_FromUnsignedLong(frame->lineno);
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001210 if (lineno_obj == NULL) {
1211 Py_DECREF(frame_obj);
1212 return NULL;
1213 }
1214 PyTuple_SET_ITEM(frame_obj, 1, lineno_obj);
1215
1216 return frame_obj;
1217}
1218
Victor Stinnere492ae52016-03-22 12:58:23 +01001219
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001220static PyObject*
1221traceback_to_pyobject(traceback_t *traceback, _Py_hashtable_t *intern_table)
1222{
1223 int i;
1224 PyObject *frames, *frame;
1225
1226 if (intern_table != NULL) {
1227 if (_Py_HASHTABLE_GET(intern_table, traceback, frames)) {
1228 Py_INCREF(frames);
1229 return frames;
1230 }
1231 }
1232
1233 frames = PyTuple_New(traceback->nframe);
1234 if (frames == NULL)
1235 return NULL;
1236
1237 for (i=0; i < traceback->nframe; i++) {
1238 frame = frame_to_pyobject(&traceback->frames[i]);
1239 if (frame == NULL) {
1240 Py_DECREF(frames);
1241 return NULL;
1242 }
1243 PyTuple_SET_ITEM(frames, i, frame);
1244 }
1245
1246 if (intern_table != NULL) {
1247 if (_Py_HASHTABLE_SET(intern_table, traceback, frames) < 0) {
1248 Py_DECREF(frames);
1249 PyErr_NoMemory();
1250 return NULL;
1251 }
1252 /* intern_table keeps a new reference to frames */
1253 Py_INCREF(frames);
1254 }
1255 return frames;
1256}
1257
Victor Stinnere492ae52016-03-22 12:58:23 +01001258
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001259static PyObject*
Victor Stinner10b73e12016-03-22 13:39:05 +01001260trace_to_pyobject(_PyTraceMalloc_domain_t domain, trace_t *trace,
Victor Stinnere492ae52016-03-22 12:58:23 +01001261 _Py_hashtable_t *intern_tracebacks)
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001262{
1263 PyObject *trace_obj = NULL;
Victor Stinnere492ae52016-03-22 12:58:23 +01001264 PyObject *obj;
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001265
Victor Stinnere492ae52016-03-22 12:58:23 +01001266 trace_obj = PyTuple_New(3);
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001267 if (trace_obj == NULL)
1268 return NULL;
1269
Victor Stinnere492ae52016-03-22 12:58:23 +01001270 obj = PyLong_FromSize_t(domain);
1271 if (obj == NULL) {
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001272 Py_DECREF(trace_obj);
1273 return NULL;
1274 }
Victor Stinnere492ae52016-03-22 12:58:23 +01001275 PyTuple_SET_ITEM(trace_obj, 0, obj);
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001276
Victor Stinnere492ae52016-03-22 12:58:23 +01001277 obj = PyLong_FromSize_t(trace->size);
1278 if (obj == NULL) {
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001279 Py_DECREF(trace_obj);
1280 return NULL;
1281 }
Victor Stinnere492ae52016-03-22 12:58:23 +01001282 PyTuple_SET_ITEM(trace_obj, 1, obj);
1283
1284 obj = traceback_to_pyobject(trace->traceback, intern_tracebacks);
1285 if (obj == NULL) {
1286 Py_DECREF(trace_obj);
1287 return NULL;
1288 }
1289 PyTuple_SET_ITEM(trace_obj, 2, obj);
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001290
1291 return trace_obj;
1292}
1293
Victor Stinnere492ae52016-03-22 12:58:23 +01001294
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001295typedef struct {
1296 _Py_hashtable_t *traces;
1297 _Py_hashtable_t *tracebacks;
1298 PyObject *list;
1299} get_traces_t;
1300
1301static int
Victor Stinner285cf0a2016-03-21 22:00:58 +01001302tracemalloc_get_traces_fill(_Py_hashtable_t *traces, _Py_hashtable_entry_t *entry,
1303 void *user_data)
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001304{
1305 get_traces_t *get_traces = user_data;
Victor Stinner10b73e12016-03-22 13:39:05 +01001306 _PyTraceMalloc_domain_t domain;
Victor Stinner5dacbd42016-03-23 09:52:13 +01001307 trace_t trace;
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001308 PyObject *tracemalloc_obj;
1309 int res;
1310
Victor Stinnere492ae52016-03-22 12:58:23 +01001311 if (tracemalloc_config.use_domain) {
1312 pointer_t key;
Victor Stinner5dacbd42016-03-23 09:52:13 +01001313 _Py_HASHTABLE_ENTRY_READ_KEY(traces, entry, key);
Victor Stinnere492ae52016-03-22 12:58:23 +01001314 domain = key.domain;
1315 }
1316 else {
1317 domain = DEFAULT_DOMAIN;
1318 }
Victor Stinner5dacbd42016-03-23 09:52:13 +01001319 _Py_HASHTABLE_ENTRY_READ_DATA(traces, entry, trace);
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001320
Victor Stinner5dacbd42016-03-23 09:52:13 +01001321 tracemalloc_obj = trace_to_pyobject(domain, &trace, get_traces->tracebacks);
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001322 if (tracemalloc_obj == NULL)
1323 return 1;
1324
1325 res = PyList_Append(get_traces->list, tracemalloc_obj);
1326 Py_DECREF(tracemalloc_obj);
1327 if (res < 0)
1328 return 1;
1329
1330 return 0;
1331}
1332
Victor Stinnere492ae52016-03-22 12:58:23 +01001333
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001334static int
Victor Stinner285cf0a2016-03-21 22:00:58 +01001335tracemalloc_pyobject_decref_cb(_Py_hashtable_t *tracebacks,
1336 _Py_hashtable_entry_t *entry,
1337 void *user_data)
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001338{
Victor Stinnerc9553872016-03-22 12:13:01 +01001339 PyObject *obj;
Victor Stinnere8c6b2f2016-03-23 09:25:01 +01001340 _Py_HASHTABLE_ENTRY_READ_DATA(tracebacks, entry, obj);
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001341 Py_DECREF(obj);
1342 return 0;
1343}
1344
Victor Stinnere492ae52016-03-22 12:58:23 +01001345
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001346PyDoc_STRVAR(tracemalloc_get_traces_doc,
Victor Stinner4fbefdb2013-11-25 09:33:18 +01001347 "_get_traces() -> list\n"
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001348 "\n"
1349 "Get traces of all memory blocks allocated by Python.\n"
1350 "Return a list of (size: int, traceback: tuple) tuples.\n"
1351 "traceback is a tuple of (filename: str, lineno: int) tuples.\n"
1352 "\n"
1353 "Return an empty list if the tracemalloc module is disabled.");
1354
1355static PyObject*
1356py_tracemalloc_get_traces(PyObject *self, PyObject *obj)
1357{
1358 get_traces_t get_traces;
1359 int err;
1360
1361 get_traces.traces = NULL;
1362 get_traces.tracebacks = NULL;
1363 get_traces.list = PyList_New(0);
1364 if (get_traces.list == NULL)
1365 goto error;
1366
1367 if (!tracemalloc_config.tracing)
1368 return get_traces.list;
1369
Victor Stinnerde2f1322013-11-26 00:26:23 +01001370 /* the traceback hash table is used temporarily to intern traceback tuple
1371 of (filename, lineno) tuples */
Victor Stinnerc9553872016-03-22 12:13:01 +01001372 get_traces.tracebacks = hashtable_new(sizeof(traceback_t *),
1373 sizeof(PyObject *),
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001374 _Py_hashtable_hash_ptr,
1375 _Py_hashtable_compare_direct);
1376 if (get_traces.tracebacks == NULL) {
1377 PyErr_NoMemory();
1378 goto error;
1379 }
1380
1381 TABLES_LOCK();
1382 get_traces.traces = _Py_hashtable_copy(tracemalloc_traces);
1383 TABLES_UNLOCK();
1384
1385 if (get_traces.traces == NULL) {
1386 PyErr_NoMemory();
1387 goto error;
1388 }
1389
1390 set_reentrant(1);
1391 err = _Py_hashtable_foreach(get_traces.traces,
1392 tracemalloc_get_traces_fill, &get_traces);
1393 set_reentrant(0);
1394 if (err)
1395 goto error;
1396
1397 goto finally;
1398
1399error:
1400 Py_CLEAR(get_traces.list);
1401
1402finally:
1403 if (get_traces.tracebacks != NULL) {
1404 _Py_hashtable_foreach(get_traces.tracebacks,
Victor Stinner285cf0a2016-03-21 22:00:58 +01001405 tracemalloc_pyobject_decref_cb, NULL);
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001406 _Py_hashtable_destroy(get_traces.tracebacks);
1407 }
Victor Stinnerc9553872016-03-22 12:13:01 +01001408 if (get_traces.traces != NULL) {
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001409 _Py_hashtable_destroy(get_traces.traces);
Victor Stinnerc9553872016-03-22 12:13:01 +01001410 }
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001411
1412 return get_traces.list;
1413}
1414
Victor Stinnere492ae52016-03-22 12:58:23 +01001415
Victor Stinner0611c262016-03-15 22:22:13 +01001416static traceback_t*
Victor Stinner10b73e12016-03-22 13:39:05 +01001417tracemalloc_get_traceback(_PyTraceMalloc_domain_t domain, Py_uintptr_t ptr)
Victor Stinner0611c262016-03-15 22:22:13 +01001418{
1419 trace_t trace;
1420 int found;
1421
1422 if (!tracemalloc_config.tracing)
1423 return NULL;
1424
1425 TABLES_LOCK();
Victor Stinnere492ae52016-03-22 12:58:23 +01001426 if (tracemalloc_config.use_domain) {
Victor Stinner10b73e12016-03-22 13:39:05 +01001427 pointer_t key = {ptr, domain};
Victor Stinnere492ae52016-03-22 12:58:23 +01001428 found = _Py_HASHTABLE_GET(tracemalloc_traces, key, trace);
1429 }
1430 else {
1431 found = _Py_HASHTABLE_GET(tracemalloc_traces, ptr, trace);
1432 }
Victor Stinner0611c262016-03-15 22:22:13 +01001433 TABLES_UNLOCK();
1434
1435 if (!found)
1436 return NULL;
1437
1438 return trace.traceback;
1439}
1440
Victor Stinnere492ae52016-03-22 12:58:23 +01001441
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001442PyDoc_STRVAR(tracemalloc_get_object_traceback_doc,
Victor Stinner4fbefdb2013-11-25 09:33:18 +01001443 "_get_object_traceback(obj)\n"
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001444 "\n"
1445 "Get the traceback where the Python object obj was allocated.\n"
1446 "Return a tuple of (filename: str, lineno: int) tuples.\n"
1447 "\n"
1448 "Return None if the tracemalloc module is disabled or did not\n"
1449 "trace the allocation of the object.");
1450
1451static PyObject*
1452py_tracemalloc_get_object_traceback(PyObject *self, PyObject *obj)
1453{
1454 PyTypeObject *type;
1455 void *ptr;
Victor Stinner0611c262016-03-15 22:22:13 +01001456 traceback_t *traceback;
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001457
1458 type = Py_TYPE(obj);
1459 if (PyType_IS_GC(type))
1460 ptr = (void *)((char *)obj - sizeof(PyGC_Head));
1461 else
1462 ptr = (void *)obj;
1463
Victor Stinner10b73e12016-03-22 13:39:05 +01001464 traceback = tracemalloc_get_traceback(DEFAULT_DOMAIN, (Py_uintptr_t)ptr);
Victor Stinner0611c262016-03-15 22:22:13 +01001465 if (traceback == NULL)
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001466 Py_RETURN_NONE;
1467
Victor Stinner0611c262016-03-15 22:22:13 +01001468 return traceback_to_pyobject(traceback, NULL);
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001469}
1470
Victor Stinnere492ae52016-03-22 12:58:23 +01001471
Victor Stinner0611c262016-03-15 22:22:13 +01001472#define PUTS(fd, str) _Py_write_noraise(fd, str, (int)strlen(str))
1473
1474static void
1475_PyMem_DumpFrame(int fd, frame_t * frame)
1476{
1477 PUTS(fd, " File \"");
1478 _Py_DumpASCII(fd, frame->filename);
1479 PUTS(fd, "\", line ");
1480 _Py_DumpDecimal(fd, frame->lineno);
1481 PUTS(fd, "\n");
1482}
1483
1484/* Dump the traceback where a memory block was allocated into file descriptor
1485 fd. The function may block on TABLES_LOCK() but it is unlikely. */
1486void
1487_PyMem_DumpTraceback(int fd, const void *ptr)
1488{
1489 traceback_t *traceback;
1490 int i;
1491
Victor Stinner10b73e12016-03-22 13:39:05 +01001492 traceback = tracemalloc_get_traceback(DEFAULT_DOMAIN, (Py_uintptr_t)ptr);
Victor Stinner0611c262016-03-15 22:22:13 +01001493 if (traceback == NULL)
1494 return;
1495
1496 PUTS(fd, "Memory block allocated at (most recent call first):\n");
1497 for (i=0; i < traceback->nframe; i++) {
1498 _PyMem_DumpFrame(fd, &traceback->frames[i]);
1499 }
1500 PUTS(fd, "\n");
1501}
1502
1503#undef PUTS
1504
Victor Stinnere492ae52016-03-22 12:58:23 +01001505
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001506PyDoc_STRVAR(tracemalloc_start_doc,
Victor Stinner3728d6c2013-11-23 12:37:20 +01001507 "start(nframe: int=1)\n"
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001508 "\n"
Victor Stinner3728d6c2013-11-23 12:37:20 +01001509 "Start tracing Python memory allocations. Set also the maximum number \n"
1510 "of frames stored in the traceback of a trace to nframe.");
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001511
1512static PyObject*
Victor Stinner3728d6c2013-11-23 12:37:20 +01001513py_tracemalloc_start(PyObject *self, PyObject *args)
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001514{
Victor Stinner3728d6c2013-11-23 12:37:20 +01001515 Py_ssize_t nframe = 1;
Victor Stinnerf28ce602013-11-27 22:27:13 +01001516 int nframe_int;
Victor Stinner3728d6c2013-11-23 12:37:20 +01001517
1518 if (!PyArg_ParseTuple(args, "|n:start", &nframe))
1519 return NULL;
1520
Victor Stinner52aee852014-08-16 15:44:02 +02001521 if (nframe < 1 || nframe > MAX_NFRAME) {
Victor Stinner3728d6c2013-11-23 12:37:20 +01001522 PyErr_Format(PyExc_ValueError,
1523 "the number of frames must be in range [1; %i]",
Victor Stinner52aee852014-08-16 15:44:02 +02001524 MAX_NFRAME);
Victor Stinner3728d6c2013-11-23 12:37:20 +01001525 return NULL;
1526 }
Victor Stinnerf28ce602013-11-27 22:27:13 +01001527 nframe_int = Py_SAFE_DOWNCAST(nframe, Py_ssize_t, int);
Victor Stinner3728d6c2013-11-23 12:37:20 +01001528
Victor Stinnerf9a71152016-03-22 23:54:42 +01001529 if (tracemalloc_start(nframe_int) < 0)
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001530 return NULL;
1531
1532 Py_RETURN_NONE;
1533}
1534
1535PyDoc_STRVAR(tracemalloc_stop_doc,
1536 "stop()\n"
1537 "\n"
1538 "Stop tracing Python memory allocations and clear traces\n"
1539 "of memory blocks allocated by Python.");
1540
Victor Stinnere492ae52016-03-22 12:58:23 +01001541
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001542static PyObject*
1543py_tracemalloc_stop(PyObject *self)
1544{
1545 tracemalloc_stop();
1546 Py_RETURN_NONE;
1547}
1548
Victor Stinnere492ae52016-03-22 12:58:23 +01001549
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001550PyDoc_STRVAR(tracemalloc_get_traceback_limit_doc,
1551 "get_traceback_limit() -> int\n"
1552 "\n"
1553 "Get the maximum number of frames stored in the traceback\n"
1554 "of a trace.\n"
1555 "\n"
1556 "By default, a trace of an allocated memory block only stores\n"
1557 "the most recent frame: the limit is 1.");
1558
1559static PyObject*
1560py_tracemalloc_get_traceback_limit(PyObject *self)
1561{
1562 return PyLong_FromLong(tracemalloc_config.max_nframe);
1563}
1564
Victor Stinnere492ae52016-03-22 12:58:23 +01001565
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001566PyDoc_STRVAR(tracemalloc_get_tracemalloc_memory_doc,
1567 "get_tracemalloc_memory() -> int\n"
1568 "\n"
1569 "Get the memory usage in bytes of the tracemalloc module\n"
1570 "used internally to trace memory allocations.");
1571
1572static PyObject*
1573tracemalloc_get_tracemalloc_memory(PyObject *self)
1574{
1575 size_t size;
1576 PyObject *size_obj;
1577
1578 size = _Py_hashtable_size(tracemalloc_tracebacks);
1579 size += _Py_hashtable_size(tracemalloc_filenames);
1580
1581 TABLES_LOCK();
1582 size += _Py_hashtable_size(tracemalloc_traces);
1583 TABLES_UNLOCK();
1584
1585 size_obj = PyLong_FromSize_t(size);
1586 return Py_BuildValue("N", size_obj);
1587}
1588
Victor Stinnere492ae52016-03-22 12:58:23 +01001589
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001590PyDoc_STRVAR(tracemalloc_get_traced_memory_doc,
Victor Stinner59463d82013-11-26 10:46:06 +01001591 "get_traced_memory() -> (int, int)\n"
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001592 "\n"
Victor Stinner3c0481d2013-11-27 21:39:49 +01001593 "Get the current size and peak size of memory blocks traced\n"
1594 "by the tracemalloc module as a tuple: (current: int, peak: int).");
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001595
1596static PyObject*
1597tracemalloc_get_traced_memory(PyObject *self)
1598{
Victor Stinner3c0481d2013-11-27 21:39:49 +01001599 Py_ssize_t size, peak_size;
1600 PyObject *size_obj, *peak_size_obj;
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001601
1602 if (!tracemalloc_config.tracing)
1603 return Py_BuildValue("ii", 0, 0);
1604
1605 TABLES_LOCK();
1606 size = tracemalloc_traced_memory;
Victor Stinner3c0481d2013-11-27 21:39:49 +01001607 peak_size = tracemalloc_peak_traced_memory;
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001608 TABLES_UNLOCK();
1609
1610 size_obj = PyLong_FromSize_t(size);
Victor Stinner3c0481d2013-11-27 21:39:49 +01001611 peak_size_obj = PyLong_FromSize_t(peak_size);
1612 return Py_BuildValue("NN", size_obj, peak_size_obj);
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001613}
1614
Victor Stinnere492ae52016-03-22 12:58:23 +01001615
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001616static PyMethodDef module_methods[] = {
1617 {"is_tracing", (PyCFunction)py_tracemalloc_is_tracing,
1618 METH_NOARGS, tracemalloc_is_tracing_doc},
1619 {"clear_traces", (PyCFunction)py_tracemalloc_clear_traces,
1620 METH_NOARGS, tracemalloc_clear_traces_doc},
1621 {"_get_traces", (PyCFunction)py_tracemalloc_get_traces,
1622 METH_NOARGS, tracemalloc_get_traces_doc},
1623 {"_get_object_traceback", (PyCFunction)py_tracemalloc_get_object_traceback,
1624 METH_O, tracemalloc_get_object_traceback_doc},
1625 {"start", (PyCFunction)py_tracemalloc_start,
Victor Stinner3728d6c2013-11-23 12:37:20 +01001626 METH_VARARGS, tracemalloc_start_doc},
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001627 {"stop", (PyCFunction)py_tracemalloc_stop,
1628 METH_NOARGS, tracemalloc_stop_doc},
1629 {"get_traceback_limit", (PyCFunction)py_tracemalloc_get_traceback_limit,
1630 METH_NOARGS, tracemalloc_get_traceback_limit_doc},
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001631 {"get_tracemalloc_memory", (PyCFunction)tracemalloc_get_tracemalloc_memory,
1632 METH_NOARGS, tracemalloc_get_tracemalloc_memory_doc},
1633 {"get_traced_memory", (PyCFunction)tracemalloc_get_traced_memory,
1634 METH_NOARGS, tracemalloc_get_traced_memory_doc},
1635
1636 /* sentinel */
1637 {NULL, NULL}
1638};
1639
1640PyDoc_STRVAR(module_doc,
1641"Debug module to trace memory blocks allocated by Python.");
1642
1643static struct PyModuleDef module_def = {
1644 PyModuleDef_HEAD_INIT,
1645 "_tracemalloc",
1646 module_doc,
1647 0, /* non-negative size to be able to unload the module */
1648 module_methods,
1649 NULL,
1650};
1651
1652PyMODINIT_FUNC
1653PyInit__tracemalloc(void)
1654{
1655 PyObject *m;
1656 m = PyModule_Create(&module_def);
1657 if (m == NULL)
1658 return NULL;
1659
1660 if (tracemalloc_init() < 0)
1661 return NULL;
1662
1663 return m;
1664}
1665
Victor Stinnere492ae52016-03-22 12:58:23 +01001666
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001667static int
1668parse_sys_xoptions(PyObject *value)
1669{
1670 PyObject *valuelong;
1671 long nframe;
1672
1673 if (value == Py_True)
1674 return 1;
1675
1676 assert(PyUnicode_Check(value));
1677 if (PyUnicode_GetLength(value) == 0)
1678 return -1;
1679
1680 valuelong = PyLong_FromUnicodeObject(value, 10);
1681 if (valuelong == NULL)
1682 return -1;
1683
1684 nframe = PyLong_AsLong(valuelong);
1685 Py_DECREF(valuelong);
1686 if (nframe == -1 && PyErr_Occurred())
1687 return -1;
1688
Victor Stinner52aee852014-08-16 15:44:02 +02001689 if (nframe < 1 || nframe > MAX_NFRAME)
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001690 return -1;
1691
1692 return Py_SAFE_DOWNCAST(nframe, long, int);
1693}
1694
Victor Stinnere492ae52016-03-22 12:58:23 +01001695
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001696int
1697_PyTraceMalloc_Init(void)
1698{
1699 char *p;
1700 int nframe;
1701
1702#ifdef WITH_THREAD
1703 assert(PyGILState_Check());
1704#endif
1705
1706 if ((p = Py_GETENV("PYTHONTRACEMALLOC")) && *p != '\0') {
1707 char *endptr = p;
Victor Stinnerf28ce602013-11-27 22:27:13 +01001708 long value;
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001709
Victor Stinner711e27c2013-12-16 23:06:19 +01001710 errno = 0;
Victor Stinnerf28ce602013-11-27 22:27:13 +01001711 value = strtol(p, &endptr, 10);
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001712 if (*endptr != '\0'
1713 || value < 1
Victor Stinner52aee852014-08-16 15:44:02 +02001714 || value > MAX_NFRAME
Victor Stinner711e27c2013-12-16 23:06:19 +01001715 || errno == ERANGE)
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001716 {
Victor Stinnerf28ce602013-11-27 22:27:13 +01001717 Py_FatalError("PYTHONTRACEMALLOC: invalid number of frames");
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001718 return -1;
1719 }
1720
1721 nframe = (int)value;
1722 }
1723 else {
1724 PyObject *xoptions, *key, *value;
1725
1726 xoptions = PySys_GetXOptions();
1727 if (xoptions == NULL)
1728 return -1;
1729
1730 key = PyUnicode_FromString("tracemalloc");
1731 if (key == NULL)
1732 return -1;
1733
1734 value = PyDict_GetItemWithError(xoptions, key);
1735 Py_DECREF(key);
1736 if (value == NULL) {
1737 if (PyErr_Occurred())
1738 return -1;
1739
1740 /* -X tracemalloc is not used */
1741 return 0;
1742 }
1743
1744 nframe = parse_sys_xoptions(value);
1745 Py_DECREF(value);
1746 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{
1758#ifdef WITH_THREAD
1759 assert(PyGILState_Check());
1760#endif
1761 tracemalloc_deinit();
1762}
Victor Stinner10b73e12016-03-22 13:39:05 +01001763
1764int
1765_PyTraceMalloc_Track(_PyTraceMalloc_domain_t domain, Py_uintptr_t ptr,
1766 size_t size)
1767{
1768 int res;
1769#ifdef WITH_THREAD
1770 PyGILState_STATE gil_state;
1771#endif
1772
1773 if (!tracemalloc_config.tracing) {
1774 /* tracemalloc is not tracing: do nothing */
1775 return -2;
1776 }
1777
1778#ifdef WITH_THREAD
1779 gil_state = PyGILState_Ensure();
1780#endif
1781
1782 TABLES_LOCK();
1783 res = tracemalloc_add_trace(domain, ptr, size);
1784 TABLES_UNLOCK();
1785
1786#ifdef WITH_THREAD
1787 PyGILState_Release(gil_state);
1788#endif
1789 return res;
1790}
1791
1792
1793int
1794_PyTraceMalloc_Untrack(_PyTraceMalloc_domain_t domain, Py_uintptr_t ptr)
1795{
1796 if (!tracemalloc_config.tracing) {
1797 /* tracemalloc is not tracing: do nothing */
1798 return -2;
1799 }
1800
1801 TABLES_LOCK();
1802 tracemalloc_remove_trace(domain, ptr);
1803 TABLES_UNLOCK();
1804
1805 return 0;
1806}
1807
1808
1809PyObject*
1810_PyTraceMalloc_GetTraceback(_PyTraceMalloc_domain_t domain, Py_uintptr_t ptr)
1811{
1812 traceback_t *traceback;
1813
1814 traceback = tracemalloc_get_traceback(domain, ptr);
1815 if (traceback == NULL)
1816 Py_RETURN_NONE;
1817
1818 return traceback_to_pyobject(traceback, NULL);
1819}