blob: 6966b86a48ad40e5831644fec4031a6be326c02b [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)
Segev Finer39243772017-07-25 11:47:43 +030086#pragma pack(push, 4)
Victor Stinnered3b0bc2013-11-23 12:27:24 +010087#endif
88{
Victor Stinner7105e9f2016-03-15 14:28:04 +010089 /* filename cannot be NULL: "<unknown>" is used if the Python frame
90 filename is NULL */
Victor Stinnered3b0bc2013-11-23 12:27:24 +010091 PyObject *filename;
Victor Stinner95283342016-03-15 21:57:02 +010092 unsigned int lineno;
Victor Stinnered3b0bc2013-11-23 12:27:24 +010093} frame_t;
Segev Finer39243772017-07-25 11:47:43 +030094#ifdef _MSC_VER
95#pragma pack(pop)
96#endif
Victor Stinnered3b0bc2013-11-23 12:27:24 +010097
Victor Stinnere492ae52016-03-22 12:58:23 +010098
Victor Stinnered3b0bc2013-11-23 12:27:24 +010099typedef struct {
100 Py_uhash_t hash;
101 int nframe;
102 frame_t frames[1];
103} traceback_t;
104
105#define TRACEBACK_SIZE(NFRAME) \
106 (sizeof(traceback_t) + sizeof(frame_t) * (NFRAME - 1))
Victor Stinnerf28ce602013-11-27 22:27:13 +0100107
108#define MAX_NFRAME \
Victor Stinner52aee852014-08-16 15:44:02 +0200109 ((INT_MAX - (int)sizeof(traceback_t)) / (int)sizeof(frame_t) + 1)
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100110
Victor Stinnere492ae52016-03-22 12:58:23 +0100111
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100112static PyObject *unknown_filename = NULL;
113static traceback_t tracemalloc_empty_traceback;
114
Victor Stinner7a5be142013-11-26 01:06:02 +0100115/* Trace of a memory block */
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100116typedef struct {
Victor Stinner7a5be142013-11-26 01:06:02 +0100117 /* Size of the memory block in bytes */
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100118 size_t size;
Victor Stinner7a5be142013-11-26 01:06:02 +0100119
120 /* Traceback where the memory block was allocated */
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100121 traceback_t *traceback;
122} trace_t;
123
Victor Stinnere492ae52016-03-22 12:58:23 +0100124
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100125/* Size in bytes of currently traced memory.
126 Protected by TABLES_LOCK(). */
127static size_t tracemalloc_traced_memory = 0;
128
Victor Stinner3c0481d2013-11-27 21:39:49 +0100129/* Peak size in bytes of traced memory.
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100130 Protected by TABLES_LOCK(). */
Victor Stinner3c0481d2013-11-27 21:39:49 +0100131static size_t tracemalloc_peak_traced_memory = 0;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100132
Serhiy Storchaka56a6d852014-12-01 18:28:43 +0200133/* Hash table used as a set to intern filenames:
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100134 PyObject* => PyObject*.
135 Protected by the GIL */
136static _Py_hashtable_t *tracemalloc_filenames = NULL;
137
Victor Stinnerf28ce602013-11-27 22:27:13 +0100138/* Buffer to store a new traceback in traceback_new().
139 Protected by the GIL. */
140static traceback_t *tracemalloc_traceback = NULL;
141
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100142/* Hash table used as a set to intern tracebacks:
143 traceback_t* => traceback_t*
144 Protected by the GIL */
145static _Py_hashtable_t *tracemalloc_tracebacks = NULL;
146
147/* pointer (void*) => trace (trace_t).
148 Protected by TABLES_LOCK(). */
149static _Py_hashtable_t *tracemalloc_traces = NULL;
150
Victor Stinnere492ae52016-03-22 12:58:23 +0100151
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100152#ifdef TRACE_DEBUG
153static void
154tracemalloc_error(const char *format, ...)
155{
156 va_list ap;
157 fprintf(stderr, "tracemalloc: ");
158 va_start(ap, format);
159 vfprintf(stderr, format, ap);
160 va_end(ap);
161 fprintf(stderr, "\n");
162 fflush(stderr);
163}
164#endif
165
Victor Stinnere492ae52016-03-22 12:58:23 +0100166
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100167#if defined(WITH_THREAD) && defined(TRACE_RAW_MALLOC)
168#define REENTRANT_THREADLOCAL
169
170/* If your OS does not provide native thread local storage, you can implement
171 it manually using a lock. Functions of thread.c cannot be used because
172 they use PyMem_RawMalloc() which leads to a reentrant call. */
173#if !(defined(_POSIX_THREADS) || defined(NT_THREADS))
174# error "need native thread local storage (TLS)"
175#endif
176
Victor Stinner4a066472016-03-22 17:45:09 +0100177static int tracemalloc_reentrant_key = -1;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100178
179/* Any non-NULL pointer can be used */
180#define REENTRANT Py_True
181
182static int
183get_reentrant(void)
184{
Victor Stinner4a066472016-03-22 17:45:09 +0100185 void *ptr;
186
187 assert(tracemalloc_reentrant_key != -1);
188 ptr = PyThread_get_key_value(tracemalloc_reentrant_key);
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100189 if (ptr != NULL) {
190 assert(ptr == REENTRANT);
191 return 1;
192 }
193 else
194 return 0;
195}
196
197static void
198set_reentrant(int reentrant)
199{
Victor Stinner2ead3d22013-11-26 01:08:53 +0100200 assert(reentrant == 0 || reentrant == 1);
Victor Stinner4a066472016-03-22 17:45:09 +0100201 assert(tracemalloc_reentrant_key != -1);
202
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100203 if (reentrant) {
Victor Stinner0cfc0582016-03-22 17:40:07 +0100204 assert(!get_reentrant());
Victor Stinner590cebe2013-12-13 11:08:56 +0100205 PyThread_set_key_value(tracemalloc_reentrant_key, REENTRANT);
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100206 }
207 else {
Victor Stinner0cfc0582016-03-22 17:40:07 +0100208 assert(get_reentrant());
Victor Stinner590cebe2013-12-13 11:08:56 +0100209 PyThread_set_key_value(tracemalloc_reentrant_key, NULL);
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100210 }
211}
212
213#else
214
215/* WITH_THREAD not defined: Python compiled without threads,
216 or TRACE_RAW_MALLOC not defined: variable protected by the GIL */
217static int tracemalloc_reentrant = 0;
218
219static int
220get_reentrant(void)
221{
222 return tracemalloc_reentrant;
223}
224
225static void
226set_reentrant(int reentrant)
227{
Victor Stinnerd5871e62016-03-23 00:17:04 +0100228 assert(reentrant != tracemalloc_reentrant);
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100229 tracemalloc_reentrant = reentrant;
230}
231#endif
232
Victor Stinnere492ae52016-03-22 12:58:23 +0100233
Victor Stinner285cf0a2016-03-21 22:00:58 +0100234static Py_uhash_t
Victor Stinner5dacbd42016-03-23 09:52:13 +0100235hashtable_hash_pyobject(_Py_hashtable_t *ht, const void *pkey)
Victor Stinner51b846c2016-03-18 21:52:22 +0100236{
Victor Stinner285cf0a2016-03-21 22:00:58 +0100237 PyObject *obj;
238
Victor Stinner5dacbd42016-03-23 09:52:13 +0100239 _Py_HASHTABLE_READ_KEY(ht, pkey, obj);
Victor Stinner285cf0a2016-03-21 22:00:58 +0100240 return PyObject_Hash(obj);
241}
242
Victor Stinnere492ae52016-03-22 12:58:23 +0100243
Victor Stinner285cf0a2016-03-21 22:00:58 +0100244static int
Victor Stinner5dacbd42016-03-23 09:52:13 +0100245hashtable_compare_unicode(_Py_hashtable_t *ht, const void *pkey,
Victor Stinner285cf0a2016-03-21 22:00:58 +0100246 const _Py_hashtable_entry_t *entry)
247{
Victor Stinnere492ae52016-03-22 12:58:23 +0100248 PyObject *key1, *key2;
Victor Stinner285cf0a2016-03-21 22:00:58 +0100249
Victor Stinner5dacbd42016-03-23 09:52:13 +0100250 _Py_HASHTABLE_READ_KEY(ht, pkey, key1);
251 _Py_HASHTABLE_ENTRY_READ_KEY(ht, entry, key2);
Victor Stinner285cf0a2016-03-21 22:00:58 +0100252
Victor Stinnere492ae52016-03-22 12:58:23 +0100253 if (key1 != NULL && key2 != NULL)
254 return (PyUnicode_Compare(key1, key2) == 0);
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100255 else
Victor Stinnere492ae52016-03-22 12:58:23 +0100256 return key1 == key2;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100257}
258
Victor Stinnere492ae52016-03-22 12:58:23 +0100259
260static Py_uhash_t
Victor Stinner5dacbd42016-03-23 09:52:13 +0100261hashtable_hash_pointer_t(_Py_hashtable_t *ht, const void *pkey)
Victor Stinnere492ae52016-03-22 12:58:23 +0100262{
263 pointer_t ptr;
264 Py_uhash_t hash;
265
Victor Stinner5dacbd42016-03-23 09:52:13 +0100266 _Py_HASHTABLE_READ_KEY(ht, pkey, ptr);
Victor Stinnere492ae52016-03-22 12:58:23 +0100267
268 hash = (Py_uhash_t)_Py_HashPointer((void*)ptr.ptr);
269 hash ^= ptr.domain;
270 return hash;
271}
272
273
doko@ubuntu.combc731502016-05-18 01:06:01 +0200274static int
Victor Stinner5dacbd42016-03-23 09:52:13 +0100275hashtable_compare_pointer_t(_Py_hashtable_t *ht, const void *pkey,
Victor Stinnere492ae52016-03-22 12:58:23 +0100276 const _Py_hashtable_entry_t *entry)
277{
278 pointer_t ptr1, ptr2;
279
Victor Stinner5dacbd42016-03-23 09:52:13 +0100280 _Py_HASHTABLE_READ_KEY(ht, pkey, ptr1);
281 _Py_HASHTABLE_ENTRY_READ_KEY(ht, entry, ptr2);
Victor Stinnere492ae52016-03-22 12:58:23 +0100282
283 /* compare pointer before domain, because pointer is more likely to be
284 different */
285 return (ptr1.ptr == ptr2.ptr && ptr1.domain == ptr2.domain);
286
287}
288
289
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100290static _Py_hashtable_t *
Victor Stinner285cf0a2016-03-21 22:00:58 +0100291hashtable_new(size_t key_size, size_t data_size,
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100292 _Py_hashtable_hash_func hash_func,
293 _Py_hashtable_compare_func compare_func)
294{
Victor Stinnerc9553872016-03-22 12:13:01 +0100295 _Py_hashtable_allocator_t hashtable_alloc = {malloc, free};
Victor Stinner285cf0a2016-03-21 22:00:58 +0100296 return _Py_hashtable_new_full(key_size, data_size, 0,
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100297 hash_func, compare_func,
Victor Stinnerc9553872016-03-22 12:13:01 +0100298 &hashtable_alloc);
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100299}
300
Victor Stinnere492ae52016-03-22 12:58:23 +0100301
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100302static void*
303raw_malloc(size_t size)
304{
305 return allocators.raw.malloc(allocators.raw.ctx, size);
306}
307
308static void
309raw_free(void *ptr)
310{
311 allocators.raw.free(allocators.raw.ctx, ptr);
312}
313
Victor Stinnere492ae52016-03-22 12:58:23 +0100314
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100315static Py_uhash_t
Victor Stinner5dacbd42016-03-23 09:52:13 +0100316hashtable_hash_traceback(_Py_hashtable_t *ht, const void *pkey)
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100317{
Victor Stinnerb32a7ed2016-03-21 23:05:08 +0100318 traceback_t *traceback;
Victor Stinner285cf0a2016-03-21 22:00:58 +0100319
Victor Stinner5dacbd42016-03-23 09:52:13 +0100320 _Py_HASHTABLE_READ_KEY(ht, pkey, traceback);
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100321 return traceback->hash;
322}
323
Victor Stinnere492ae52016-03-22 12:58:23 +0100324
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100325static int
Victor Stinner5dacbd42016-03-23 09:52:13 +0100326hashtable_compare_traceback(_Py_hashtable_t *ht, const void *pkey,
327 const _Py_hashtable_entry_t *entry)
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100328{
Victor Stinner285cf0a2016-03-21 22:00:58 +0100329 traceback_t *traceback1, *traceback2;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100330 const frame_t *frame1, *frame2;
331 int i;
332
Victor Stinner5dacbd42016-03-23 09:52:13 +0100333 _Py_HASHTABLE_READ_KEY(ht, pkey, traceback1);
334 _Py_HASHTABLE_ENTRY_READ_KEY(ht, entry, traceback2);
Victor Stinner285cf0a2016-03-21 22:00:58 +0100335
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100336 if (traceback1->nframe != traceback2->nframe)
337 return 0;
338
339 for (i=0; i < traceback1->nframe; i++) {
340 frame1 = &traceback1->frames[i];
341 frame2 = &traceback2->frames[i];
342
343 if (frame1->lineno != frame2->lineno)
344 return 0;
345
346 if (frame1->filename != frame2->filename) {
347 assert(PyUnicode_Compare(frame1->filename, frame2->filename) != 0);
348 return 0;
349 }
350 }
351 return 1;
352}
353
Victor Stinnere492ae52016-03-22 12:58:23 +0100354
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100355static void
356tracemalloc_get_frame(PyFrameObject *pyframe, frame_t *frame)
357{
358 PyCodeObject *code;
359 PyObject *filename;
360 _Py_hashtable_entry_t *entry;
Victor Stinner95283342016-03-15 21:57:02 +0100361 int lineno;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100362
363 frame->filename = unknown_filename;
Victor Stinner95283342016-03-15 21:57:02 +0100364 lineno = PyFrame_GetLineNumber(pyframe);
365 if (lineno < 0)
366 lineno = 0;
367 frame->lineno = (unsigned int)lineno;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100368
369 code = pyframe->f_code;
370 if (code == NULL) {
371#ifdef TRACE_DEBUG
Victor Stinner4dc74202013-11-26 01:18:52 +0100372 tracemalloc_error("failed to get the code object of the frame");
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100373#endif
374 return;
375 }
376
377 if (code->co_filename == NULL) {
378#ifdef TRACE_DEBUG
379 tracemalloc_error("failed to get the filename of the code object");
380#endif
381 return;
382 }
383
384 filename = code->co_filename;
385 assert(filename != NULL);
386 if (filename == NULL)
387 return;
388
389 if (!PyUnicode_Check(filename)) {
390#ifdef TRACE_DEBUG
Martin Panter6245cb32016-04-15 02:14:19 +0000391 tracemalloc_error("filename is not a unicode string");
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100392#endif
393 return;
394 }
395 if (!PyUnicode_IS_READY(filename)) {
396 /* Don't make a Unicode string ready to avoid reentrant calls
397 to tracemalloc_malloc() or tracemalloc_realloc() */
398#ifdef TRACE_DEBUG
399 tracemalloc_error("filename is not a ready unicode string");
400#endif
401 return;
402 }
403
404 /* intern the filename */
Victor Stinner285cf0a2016-03-21 22:00:58 +0100405 entry = _Py_HASHTABLE_GET_ENTRY(tracemalloc_filenames, filename);
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100406 if (entry != NULL) {
Victor Stinner5dacbd42016-03-23 09:52:13 +0100407 _Py_HASHTABLE_ENTRY_READ_KEY(tracemalloc_filenames, entry, filename);
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100408 }
409 else {
410 /* tracemalloc_filenames is responsible to keep a reference
411 to the filename */
412 Py_INCREF(filename);
Victor Stinner285cf0a2016-03-21 22:00:58 +0100413 if (_Py_HASHTABLE_SET_NODATA(tracemalloc_filenames, filename) < 0) {
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100414 Py_DECREF(filename);
415#ifdef TRACE_DEBUG
416 tracemalloc_error("failed to intern the filename");
417#endif
418 return;
419 }
420 }
421
422 /* the tracemalloc_filenames table keeps a reference to the filename */
423 frame->filename = filename;
424}
425
Victor Stinnere492ae52016-03-22 12:58:23 +0100426
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100427static Py_uhash_t
428traceback_hash(traceback_t *traceback)
429{
430 /* code based on tuplehash() of Objects/tupleobject.c */
Victor Stinner4d8c29c2013-12-16 23:05:13 +0100431 Py_uhash_t x, y; /* Unsigned for defined overflow behavior. */
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100432 int len = traceback->nframe;
433 Py_uhash_t mult = _PyHASH_MULTIPLIER;
434 frame_t *frame;
435
436 x = 0x345678UL;
437 frame = traceback->frames;
438 while (--len >= 0) {
Victor Stinner4d8c29c2013-12-16 23:05:13 +0100439 y = (Py_uhash_t)PyObject_Hash(frame->filename);
440 y ^= (Py_uhash_t)frame->lineno;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100441 frame++;
442
443 x = (x ^ y) * mult;
444 /* the cast might truncate len; that doesn't change hash stability */
Victor Stinner4d8c29c2013-12-16 23:05:13 +0100445 mult += (Py_uhash_t)(82520UL + len + len);
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100446 }
447 x += 97531UL;
448 return x;
449}
450
Victor Stinnere492ae52016-03-22 12:58:23 +0100451
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100452static void
453traceback_get_frames(traceback_t *traceback)
454{
455 PyThreadState *tstate;
456 PyFrameObject *pyframe;
457
458#ifdef WITH_THREAD
459 tstate = PyGILState_GetThisThreadState();
460#else
461 tstate = PyThreadState_Get();
462#endif
463 if (tstate == NULL) {
464#ifdef TRACE_DEBUG
465 tracemalloc_error("failed to get the current thread state");
466#endif
467 return;
468 }
469
470 for (pyframe = tstate->frame; pyframe != NULL; pyframe = pyframe->f_back) {
471 tracemalloc_get_frame(pyframe, &traceback->frames[traceback->nframe]);
472 assert(traceback->frames[traceback->nframe].filename != NULL);
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100473 traceback->nframe++;
474 if (traceback->nframe == tracemalloc_config.max_nframe)
475 break;
476 }
477}
478
Victor Stinnere492ae52016-03-22 12:58:23 +0100479
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100480static traceback_t *
481traceback_new(void)
482{
Victor Stinnerf28ce602013-11-27 22:27:13 +0100483 traceback_t *traceback;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100484 _Py_hashtable_entry_t *entry;
485
486#ifdef WITH_THREAD
487 assert(PyGILState_Check());
488#endif
489
490 /* get frames */
Victor Stinnerf28ce602013-11-27 22:27:13 +0100491 traceback = tracemalloc_traceback;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100492 traceback->nframe = 0;
493 traceback_get_frames(traceback);
494 if (traceback->nframe == 0)
495 return &tracemalloc_empty_traceback;
496 traceback->hash = traceback_hash(traceback);
497
498 /* intern the traceback */
Victor Stinner285cf0a2016-03-21 22:00:58 +0100499 entry = _Py_HASHTABLE_GET_ENTRY(tracemalloc_tracebacks, traceback);
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100500 if (entry != NULL) {
Victor Stinner5dacbd42016-03-23 09:52:13 +0100501 _Py_HASHTABLE_ENTRY_READ_KEY(tracemalloc_tracebacks, entry, traceback);
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100502 }
503 else {
504 traceback_t *copy;
505 size_t traceback_size;
506
507 traceback_size = TRACEBACK_SIZE(traceback->nframe);
508
509 copy = raw_malloc(traceback_size);
510 if (copy == NULL) {
511#ifdef TRACE_DEBUG
512 tracemalloc_error("failed to intern the traceback: malloc failed");
513#endif
514 return NULL;
515 }
516 memcpy(copy, traceback, traceback_size);
517
Victor Stinner285cf0a2016-03-21 22:00:58 +0100518 if (_Py_HASHTABLE_SET_NODATA(tracemalloc_tracebacks, copy) < 0) {
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100519 raw_free(copy);
520#ifdef TRACE_DEBUG
521 tracemalloc_error("failed to intern the traceback: putdata failed");
522#endif
523 return NULL;
524 }
525 traceback = copy;
526 }
527 return traceback;
528}
529
Victor Stinnere492ae52016-03-22 12:58:23 +0100530
Victor Stinner5e14a382016-03-23 22:03:55 +0100531static int
532tracemalloc_use_domain_cb(_Py_hashtable_t *old_traces,
533 _Py_hashtable_entry_t *entry, void *user_data)
534{
Benjamin Petersonca470632016-09-06 13:47:26 -0700535 uintptr_t ptr;
Victor Stinner5e14a382016-03-23 22:03:55 +0100536 pointer_t key;
537 _Py_hashtable_t *new_traces = (_Py_hashtable_t *)user_data;
538 const void *pdata = _Py_HASHTABLE_ENTRY_PDATA(old_traces, entry);
539
540 _Py_HASHTABLE_ENTRY_READ_KEY(old_traces, entry, ptr);
541 key.ptr = ptr;
542 key.domain = DEFAULT_DOMAIN;
543
544 return _Py_hashtable_set(new_traces,
545 sizeof(key), &key,
546 old_traces->data_size, pdata);
547}
548
549
Benjamin Petersonca470632016-09-06 13:47:26 -0700550/* Convert tracemalloc_traces from compact key (uintptr_t) to pointer_t key.
Victor Stinner5e14a382016-03-23 22:03:55 +0100551 * Return 0 on success, -1 on error. */
552static int
553tracemalloc_use_domain(void)
554{
555 _Py_hashtable_t *new_traces = NULL;
556
557 assert(!tracemalloc_config.use_domain);
558
559 new_traces = hashtable_new(sizeof(pointer_t),
560 sizeof(trace_t),
561 hashtable_hash_pointer_t,
562 hashtable_compare_pointer_t);
563 if (new_traces == NULL) {
564 return -1;
565 }
566
567 if (_Py_hashtable_foreach(tracemalloc_traces, tracemalloc_use_domain_cb,
568 new_traces) < 0)
569 {
570 _Py_hashtable_destroy(new_traces);
571 return -1;
572 }
573
574 _Py_hashtable_destroy(tracemalloc_traces);
575 tracemalloc_traces = new_traces;
576
577 tracemalloc_config.use_domain = 1;
578
579 return 0;
580}
581
582
Victor Stinnere492ae52016-03-22 12:58:23 +0100583static void
Victor Stinner5ea4c062017-06-20 17:46:36 +0200584tracemalloc_remove_trace(unsigned int domain, uintptr_t ptr)
Victor Stinnere492ae52016-03-22 12:58:23 +0100585{
586 trace_t trace;
587 int removed;
588
Victor Stinner10b73e12016-03-22 13:39:05 +0100589 assert(tracemalloc_config.tracing);
590
Victor Stinnere492ae52016-03-22 12:58:23 +0100591 if (tracemalloc_config.use_domain) {
592 pointer_t key = {ptr, domain};
593 removed = _Py_HASHTABLE_POP(tracemalloc_traces, key, trace);
594 }
595 else {
596 removed = _Py_HASHTABLE_POP(tracemalloc_traces, ptr, trace);
597 }
598 if (!removed) {
599 return;
600 }
601
602 assert(tracemalloc_traced_memory >= trace.size);
603 tracemalloc_traced_memory -= trace.size;
604}
605
606#define REMOVE_TRACE(ptr) \
Benjamin Petersonca470632016-09-06 13:47:26 -0700607 tracemalloc_remove_trace(DEFAULT_DOMAIN, (uintptr_t)(ptr))
Victor Stinnere492ae52016-03-22 12:58:23 +0100608
609
Victor Stinner52968672013-11-24 11:37:15 +0100610static int
Victor Stinner5ea4c062017-06-20 17:46:36 +0200611tracemalloc_add_trace(unsigned int domain, uintptr_t ptr,
Victor Stinner10b73e12016-03-22 13:39:05 +0100612 size_t size)
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100613{
Victor Stinnerca79ccd2016-03-23 09:38:54 +0100614 pointer_t key = {ptr, domain};
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100615 traceback_t *traceback;
616 trace_t trace;
Victor Stinnerca79ccd2016-03-23 09:38:54 +0100617 _Py_hashtable_entry_t* entry;
Victor Stinner52968672013-11-24 11:37:15 +0100618 int res;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100619
Victor Stinner10b73e12016-03-22 13:39:05 +0100620 assert(tracemalloc_config.tracing);
621
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100622 traceback = traceback_new();
Victor Stinnere492ae52016-03-22 12:58:23 +0100623 if (traceback == NULL) {
Victor Stinner52968672013-11-24 11:37:15 +0100624 return -1;
Victor Stinnere492ae52016-03-22 12:58:23 +0100625 }
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100626
Victor Stinner5e14a382016-03-23 22:03:55 +0100627 if (!tracemalloc_config.use_domain && domain != DEFAULT_DOMAIN) {
628 /* first trace using a non-zero domain whereas traces use compact
Benjamin Petersonca470632016-09-06 13:47:26 -0700629 (uintptr_t) keys: switch to pointer_t keys. */
Victor Stinner5e14a382016-03-23 22:03:55 +0100630 if (tracemalloc_use_domain() < 0) {
631 return -1;
632 }
633 }
634
Victor Stinnere492ae52016-03-22 12:58:23 +0100635 if (tracemalloc_config.use_domain) {
Victor Stinnerca79ccd2016-03-23 09:38:54 +0100636 entry = _Py_HASHTABLE_GET_ENTRY(tracemalloc_traces, key);
Victor Stinnere492ae52016-03-22 12:58:23 +0100637 }
638 else {
Victor Stinnerca79ccd2016-03-23 09:38:54 +0100639 entry = _Py_HASHTABLE_GET_ENTRY(tracemalloc_traces, ptr);
Victor Stinnerd606ba72013-11-24 11:28:20 +0100640 }
Victor Stinner52968672013-11-24 11:37:15 +0100641
Victor Stinnerca79ccd2016-03-23 09:38:54 +0100642 if (entry != NULL) {
643 /* the memory block is already tracked */
644 _Py_HASHTABLE_ENTRY_READ_DATA(tracemalloc_traces, entry, trace);
645 assert(tracemalloc_traced_memory >= trace.size);
646 tracemalloc_traced_memory -= trace.size;
647
648 trace.size = size;
649 trace.traceback = traceback;
650 _Py_HASHTABLE_ENTRY_WRITE_DATA(tracemalloc_traces, entry, trace);
651 }
652 else {
653 trace.size = size;
654 trace.traceback = traceback;
655
656 if (tracemalloc_config.use_domain) {
657 res = _Py_HASHTABLE_SET(tracemalloc_traces, key, trace);
658 }
659 else {
660 res = _Py_HASHTABLE_SET(tracemalloc_traces, ptr, trace);
661 }
662 if (res != 0) {
663 return res;
664 }
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100665 }
Victor Stinnere492ae52016-03-22 12:58:23 +0100666
Benjamin Peterson2f8bfef2016-09-07 09:26:18 -0700667 assert(tracemalloc_traced_memory <= SIZE_MAX - size);
Victor Stinnere492ae52016-03-22 12:58:23 +0100668 tracemalloc_traced_memory += size;
669 if (tracemalloc_traced_memory > tracemalloc_peak_traced_memory)
670 tracemalloc_peak_traced_memory = tracemalloc_traced_memory;
671 return 0;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100672}
673
Victor Stinnere492ae52016-03-22 12:58:23 +0100674#define ADD_TRACE(ptr, size) \
Benjamin Petersonca470632016-09-06 13:47:26 -0700675 tracemalloc_add_trace(DEFAULT_DOMAIN, (uintptr_t)(ptr), size)
Victor Stinnere492ae52016-03-22 12:58:23 +0100676
677
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100678static void*
Victor Stinnerdb067af2014-05-02 22:31:14 +0200679tracemalloc_alloc(int use_calloc, void *ctx, size_t nelem, size_t elsize)
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100680{
Victor Stinnerd8f0d922014-06-02 21:57:10 +0200681 PyMemAllocatorEx *alloc = (PyMemAllocatorEx *)ctx;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100682 void *ptr;
683
Benjamin Peterson2f8bfef2016-09-07 09:26:18 -0700684 assert(elsize == 0 || nelem <= SIZE_MAX / elsize);
Victor Stinnerdb067af2014-05-02 22:31:14 +0200685
686 if (use_calloc)
687 ptr = alloc->calloc(alloc->ctx, nelem, elsize);
688 else
689 ptr = alloc->malloc(alloc->ctx, nelem * elsize);
Victor Stinner15116802013-12-04 01:29:35 +0100690 if (ptr == NULL)
691 return NULL;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100692
Victor Stinner88c29872013-12-04 01:47:46 +0100693 TABLES_LOCK();
Victor Stinnere492ae52016-03-22 12:58:23 +0100694 if (ADD_TRACE(ptr, nelem * elsize) < 0) {
Victor Stinner15116802013-12-04 01:29:35 +0100695 /* Failed to allocate a trace for the new memory block */
Victor Stinner88c29872013-12-04 01:47:46 +0100696 TABLES_UNLOCK();
Victor Stinner15116802013-12-04 01:29:35 +0100697 alloc->free(alloc->ctx, ptr);
698 return NULL;
Victor Stinner52968672013-11-24 11:37:15 +0100699 }
Victor Stinner88c29872013-12-04 01:47:46 +0100700 TABLES_UNLOCK();
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100701 return ptr;
702}
703
Victor Stinnere492ae52016-03-22 12:58:23 +0100704
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100705static void*
Victor Stinner15116802013-12-04 01:29:35 +0100706tracemalloc_realloc(void *ctx, void *ptr, size_t new_size)
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100707{
Victor Stinnerd8f0d922014-06-02 21:57:10 +0200708 PyMemAllocatorEx *alloc = (PyMemAllocatorEx *)ctx;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100709 void *ptr2;
710
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100711 ptr2 = alloc->realloc(alloc->ctx, ptr, new_size);
Victor Stinner15116802013-12-04 01:29:35 +0100712 if (ptr2 == NULL)
713 return NULL;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100714
Victor Stinner15116802013-12-04 01:29:35 +0100715 if (ptr != NULL) {
716 /* an existing memory block has been resized */
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100717
Victor Stinner88c29872013-12-04 01:47:46 +0100718 TABLES_LOCK();
Victor Stinner42bcf372016-03-23 09:08:08 +0100719
720 /* tracemalloc_add_trace() updates the trace if there is already
721 a trace at address (domain, ptr2) */
722 if (ptr2 != ptr) {
723 REMOVE_TRACE(ptr);
724 }
Victor Stinner08facd22013-11-24 12:27:59 +0100725
Victor Stinnere492ae52016-03-22 12:58:23 +0100726 if (ADD_TRACE(ptr2, new_size) < 0) {
Victor Stinner15116802013-12-04 01:29:35 +0100727 /* Memory allocation failed. The error cannot be reported to
Raymond Hettinger15f44ab2016-08-30 10:47:49 -0700728 the caller, because realloc() may already have shrunk the
Victor Stinner15116802013-12-04 01:29:35 +0100729 memory block and so removed bytes.
730
Serhiy Storchaka6a7b3a72016-04-17 08:32:47 +0300731 This case is very unlikely: a hash entry has just been
Victor Stinner88c29872013-12-04 01:47:46 +0100732 released, so the hash table should have at least one free entry.
733
734 The GIL and the table lock ensures that only one thread is
735 allocating memory. */
736 assert(0 && "should never happen");
Victor Stinner52968672013-11-24 11:37:15 +0100737 }
Victor Stinner88c29872013-12-04 01:47:46 +0100738 TABLES_UNLOCK();
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100739 }
Victor Stinner15116802013-12-04 01:29:35 +0100740 else {
741 /* new allocation */
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100742
Victor Stinner88c29872013-12-04 01:47:46 +0100743 TABLES_LOCK();
Victor Stinnere492ae52016-03-22 12:58:23 +0100744 if (ADD_TRACE(ptr2, new_size) < 0) {
Victor Stinner15116802013-12-04 01:29:35 +0100745 /* Failed to allocate a trace for the new memory block */
Victor Stinner88c29872013-12-04 01:47:46 +0100746 TABLES_UNLOCK();
Victor Stinner15116802013-12-04 01:29:35 +0100747 alloc->free(alloc->ctx, ptr2);
748 return NULL;
749 }
Victor Stinner88c29872013-12-04 01:47:46 +0100750 TABLES_UNLOCK();
Victor Stinner15116802013-12-04 01:29:35 +0100751 }
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100752 return ptr2;
753}
754
Victor Stinnere492ae52016-03-22 12:58:23 +0100755
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100756static void
757tracemalloc_free(void *ctx, void *ptr)
758{
Victor Stinnerd8f0d922014-06-02 21:57:10 +0200759 PyMemAllocatorEx *alloc = (PyMemAllocatorEx *)ctx;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100760
761 if (ptr == NULL)
762 return;
763
764 /* GIL cannot be locked in PyMem_RawFree() because it would introduce
765 a deadlock in PyThreadState_DeleteCurrent(). */
766
767 alloc->free(alloc->ctx, ptr);
Victor Stinner88c29872013-12-04 01:47:46 +0100768
769 TABLES_LOCK();
Victor Stinnere492ae52016-03-22 12:58:23 +0100770 REMOVE_TRACE(ptr);
Victor Stinner88c29872013-12-04 01:47:46 +0100771 TABLES_UNLOCK();
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100772}
773
Victor Stinnere492ae52016-03-22 12:58:23 +0100774
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100775static void*
Victor Stinnerdb067af2014-05-02 22:31:14 +0200776tracemalloc_alloc_gil(int use_calloc, void *ctx, size_t nelem, size_t elsize)
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100777{
Victor Stinner15116802013-12-04 01:29:35 +0100778 void *ptr;
779
780 if (get_reentrant()) {
Victor Stinnerd8f0d922014-06-02 21:57:10 +0200781 PyMemAllocatorEx *alloc = (PyMemAllocatorEx *)ctx;
Victor Stinnerdb067af2014-05-02 22:31:14 +0200782 if (use_calloc)
783 return alloc->calloc(alloc->ctx, nelem, elsize);
784 else
785 return alloc->malloc(alloc->ctx, nelem * elsize);
Victor Stinner15116802013-12-04 01:29:35 +0100786 }
787
788 /* Ignore reentrant call. PyObjet_Malloc() calls PyMem_Malloc() for
789 allocations larger than 512 bytes, don't trace the same memory
790 allocation twice. */
791 set_reentrant(1);
792
Victor Stinnerdb067af2014-05-02 22:31:14 +0200793 ptr = tracemalloc_alloc(use_calloc, ctx, nelem, elsize);
Victor Stinner15116802013-12-04 01:29:35 +0100794
795 set_reentrant(0);
796 return ptr;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100797}
798
Victor Stinnere492ae52016-03-22 12:58:23 +0100799
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100800static void*
Victor Stinnerdb067af2014-05-02 22:31:14 +0200801tracemalloc_malloc_gil(void *ctx, size_t size)
802{
803 return tracemalloc_alloc_gil(0, ctx, 1, size);
804}
805
Victor Stinnere492ae52016-03-22 12:58:23 +0100806
Victor Stinnerdb067af2014-05-02 22:31:14 +0200807static void*
808tracemalloc_calloc_gil(void *ctx, size_t nelem, size_t elsize)
809{
810 return tracemalloc_alloc_gil(1, ctx, nelem, elsize);
811}
812
Victor Stinnere492ae52016-03-22 12:58:23 +0100813
Victor Stinnerdb067af2014-05-02 22:31:14 +0200814static void*
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100815tracemalloc_realloc_gil(void *ctx, void *ptr, size_t new_size)
816{
Victor Stinner15116802013-12-04 01:29:35 +0100817 void *ptr2;
818
819 if (get_reentrant()) {
820 /* Reentrant call to PyMem_Realloc() and PyMem_RawRealloc().
821 Example: PyMem_RawRealloc() is called internally by pymalloc
822 (_PyObject_Malloc() and _PyObject_Realloc()) to allocate a new
823 arena (new_arena()). */
Victor Stinnerd8f0d922014-06-02 21:57:10 +0200824 PyMemAllocatorEx *alloc = (PyMemAllocatorEx *)ctx;
Victor Stinner15116802013-12-04 01:29:35 +0100825
826 ptr2 = alloc->realloc(alloc->ctx, ptr, new_size);
Victor Stinner88c29872013-12-04 01:47:46 +0100827 if (ptr2 != NULL && ptr != NULL) {
828 TABLES_LOCK();
Victor Stinnere492ae52016-03-22 12:58:23 +0100829 REMOVE_TRACE(ptr);
Victor Stinner88c29872013-12-04 01:47:46 +0100830 TABLES_UNLOCK();
831 }
Victor Stinner15116802013-12-04 01:29:35 +0100832 return ptr2;
833 }
834
835 /* Ignore reentrant call. PyObjet_Realloc() calls PyMem_Realloc() for
836 allocations larger than 512 bytes. Don't trace the same memory
837 allocation twice. */
838 set_reentrant(1);
839
840 ptr2 = tracemalloc_realloc(ctx, ptr, new_size);
841
842 set_reentrant(0);
843 return ptr2;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100844}
845
Victor Stinnere492ae52016-03-22 12:58:23 +0100846
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100847#ifdef TRACE_RAW_MALLOC
848static void*
Victor Stinnerdb067af2014-05-02 22:31:14 +0200849tracemalloc_raw_alloc(int use_calloc, void *ctx, size_t nelem, size_t elsize)
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100850{
Victor Stinner15116802013-12-04 01:29:35 +0100851#ifdef WITH_THREAD
852 PyGILState_STATE gil_state;
853#endif
854 void *ptr;
855
856 if (get_reentrant()) {
Victor Stinnerd8f0d922014-06-02 21:57:10 +0200857 PyMemAllocatorEx *alloc = (PyMemAllocatorEx *)ctx;
Victor Stinnerdb067af2014-05-02 22:31:14 +0200858 if (use_calloc)
859 return alloc->calloc(alloc->ctx, nelem, elsize);
860 else
861 return alloc->malloc(alloc->ctx, nelem * elsize);
Victor Stinner15116802013-12-04 01:29:35 +0100862 }
863
864 /* Ignore reentrant call. PyGILState_Ensure() may call PyMem_RawMalloc()
865 indirectly which would call PyGILState_Ensure() if reentrant are not
866 disabled. */
867 set_reentrant(1);
868
869#ifdef WITH_THREAD
870 gil_state = PyGILState_Ensure();
Victor Stinnerdb067af2014-05-02 22:31:14 +0200871 ptr = tracemalloc_alloc(use_calloc, ctx, nelem, elsize);
Victor Stinner15116802013-12-04 01:29:35 +0100872 PyGILState_Release(gil_state);
873#else
Victor Stinnerdb067af2014-05-02 22:31:14 +0200874 ptr = tracemalloc_alloc(use_calloc, ctx, nelem, elsize);
Victor Stinner15116802013-12-04 01:29:35 +0100875#endif
876
877 set_reentrant(0);
878 return ptr;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100879}
880
Victor Stinnere492ae52016-03-22 12:58:23 +0100881
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100882static void*
Victor Stinnerdb067af2014-05-02 22:31:14 +0200883tracemalloc_raw_malloc(void *ctx, size_t size)
884{
885 return tracemalloc_raw_alloc(0, ctx, 1, size);
886}
887
Victor Stinnere492ae52016-03-22 12:58:23 +0100888
Victor Stinnerdb067af2014-05-02 22:31:14 +0200889static void*
890tracemalloc_raw_calloc(void *ctx, size_t nelem, size_t elsize)
891{
892 return tracemalloc_raw_alloc(1, ctx, nelem, elsize);
893}
894
Victor Stinnere492ae52016-03-22 12:58:23 +0100895
Victor Stinnerdb067af2014-05-02 22:31:14 +0200896static void*
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100897tracemalloc_raw_realloc(void *ctx, void *ptr, size_t new_size)
898{
Victor Stinner15116802013-12-04 01:29:35 +0100899#ifdef WITH_THREAD
900 PyGILState_STATE gil_state;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100901#endif
Victor Stinner15116802013-12-04 01:29:35 +0100902 void *ptr2;
903
904 if (get_reentrant()) {
905 /* Reentrant call to PyMem_RawRealloc(). */
Victor Stinnerd8f0d922014-06-02 21:57:10 +0200906 PyMemAllocatorEx *alloc = (PyMemAllocatorEx *)ctx;
Victor Stinner15116802013-12-04 01:29:35 +0100907
908 ptr2 = alloc->realloc(alloc->ctx, ptr, new_size);
Victor Stinner15116802013-12-04 01:29:35 +0100909
Victor Stinner88c29872013-12-04 01:47:46 +0100910 if (ptr2 != NULL && ptr != NULL) {
911 TABLES_LOCK();
Victor Stinnere492ae52016-03-22 12:58:23 +0100912 REMOVE_TRACE(ptr);
Victor Stinner88c29872013-12-04 01:47:46 +0100913 TABLES_UNLOCK();
914 }
Victor Stinner15116802013-12-04 01:29:35 +0100915 return ptr2;
916 }
917
918 /* Ignore reentrant call. PyGILState_Ensure() may call PyMem_RawMalloc()
919 indirectly which would call PyGILState_Ensure() if reentrant calls are
920 not disabled. */
921 set_reentrant(1);
922
923#ifdef WITH_THREAD
924 gil_state = PyGILState_Ensure();
925 ptr2 = tracemalloc_realloc(ctx, ptr, new_size);
926 PyGILState_Release(gil_state);
927#else
928 ptr2 = tracemalloc_realloc(ctx, ptr, new_size);
929#endif
930
931 set_reentrant(0);
932 return ptr2;
933}
934#endif /* TRACE_RAW_MALLOC */
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100935
Victor Stinnere492ae52016-03-22 12:58:23 +0100936
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100937static int
Victor Stinner285cf0a2016-03-21 22:00:58 +0100938tracemalloc_clear_filename(_Py_hashtable_t *ht, _Py_hashtable_entry_t *entry,
939 void *user_data)
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100940{
Victor Stinner285cf0a2016-03-21 22:00:58 +0100941 PyObject *filename;
942
Victor Stinner5dacbd42016-03-23 09:52:13 +0100943 _Py_HASHTABLE_ENTRY_READ_KEY(ht, entry, filename);
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100944 Py_DECREF(filename);
945 return 0;
946}
947
Victor Stinnere492ae52016-03-22 12:58:23 +0100948
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100949static int
Victor Stinner285cf0a2016-03-21 22:00:58 +0100950traceback_free_traceback(_Py_hashtable_t *ht, _Py_hashtable_entry_t *entry,
951 void *user_data)
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100952{
Victor Stinner285cf0a2016-03-21 22:00:58 +0100953 traceback_t *traceback;
954
Victor Stinner5dacbd42016-03-23 09:52:13 +0100955 _Py_HASHTABLE_ENTRY_READ_KEY(ht, entry, traceback);
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100956 raw_free(traceback);
957 return 0;
958}
959
Victor Stinnere492ae52016-03-22 12:58:23 +0100960
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100961/* reentrant flag must be set to call this function and GIL must be held */
962static void
963tracemalloc_clear_traces(void)
964{
965#ifdef WITH_THREAD
966 /* The GIL protects variables againt concurrent access */
967 assert(PyGILState_Check());
968#endif
969
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100970 TABLES_LOCK();
971 _Py_hashtable_clear(tracemalloc_traces);
972 tracemalloc_traced_memory = 0;
Victor Stinner3c0481d2013-11-27 21:39:49 +0100973 tracemalloc_peak_traced_memory = 0;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100974 TABLES_UNLOCK();
975
976 _Py_hashtable_foreach(tracemalloc_tracebacks, traceback_free_traceback, NULL);
977 _Py_hashtable_clear(tracemalloc_tracebacks);
978
979 _Py_hashtable_foreach(tracemalloc_filenames, tracemalloc_clear_filename, NULL);
980 _Py_hashtable_clear(tracemalloc_filenames);
981}
982
Victor Stinnere492ae52016-03-22 12:58:23 +0100983
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100984static int
985tracemalloc_init(void)
986{
987 if (tracemalloc_config.initialized == TRACEMALLOC_FINALIZED) {
988 PyErr_SetString(PyExc_RuntimeError,
989 "the tracemalloc module has been unloaded");
990 return -1;
991 }
992
Victor Stinnerf9a71152016-03-22 23:54:42 +0100993 if (tracemalloc_config.initialized == TRACEMALLOC_INITIALIZED)
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100994 return 0;
995
996 PyMem_GetAllocator(PYMEM_DOMAIN_RAW, &allocators.raw);
997
998#ifdef REENTRANT_THREADLOCAL
999 tracemalloc_reentrant_key = PyThread_create_key();
1000 if (tracemalloc_reentrant_key == -1) {
1001#ifdef MS_WINDOWS
1002 PyErr_SetFromWindowsErr(0);
1003#else
1004 PyErr_SetFromErrno(PyExc_OSError);
1005#endif
1006 return -1;
1007 }
1008#endif
1009
1010#if defined(WITH_THREAD) && defined(TRACE_RAW_MALLOC)
1011 if (tables_lock == NULL) {
1012 tables_lock = PyThread_allocate_lock();
1013 if (tables_lock == NULL) {
1014 PyErr_SetString(PyExc_RuntimeError, "cannot allocate lock");
1015 return -1;
1016 }
1017 }
1018#endif
1019
Victor Stinner285cf0a2016-03-21 22:00:58 +01001020 tracemalloc_filenames = hashtable_new(sizeof(PyObject *), 0,
1021 hashtable_hash_pyobject,
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001022 hashtable_compare_unicode);
1023
Victor Stinner285cf0a2016-03-21 22:00:58 +01001024 tracemalloc_tracebacks = hashtable_new(sizeof(traceback_t *), 0,
1025 hashtable_hash_traceback,
1026 hashtable_compare_traceback);
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001027
Victor Stinnere492ae52016-03-22 12:58:23 +01001028 if (tracemalloc_config.use_domain) {
1029 tracemalloc_traces = hashtable_new(sizeof(pointer_t),
1030 sizeof(trace_t),
1031 hashtable_hash_pointer_t,
1032 hashtable_compare_pointer_t);
1033 }
1034 else {
Benjamin Petersonca470632016-09-06 13:47:26 -07001035 tracemalloc_traces = hashtable_new(sizeof(uintptr_t),
Victor Stinnere492ae52016-03-22 12:58:23 +01001036 sizeof(trace_t),
1037 _Py_hashtable_hash_ptr,
1038 _Py_hashtable_compare_direct);
1039 }
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001040
1041 if (tracemalloc_filenames == NULL || tracemalloc_tracebacks == NULL
Victor Stinner285cf0a2016-03-21 22:00:58 +01001042 || tracemalloc_traces == NULL) {
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001043 PyErr_NoMemory();
1044 return -1;
1045 }
1046
1047 unknown_filename = PyUnicode_FromString("<unknown>");
1048 if (unknown_filename == NULL)
1049 return -1;
1050 PyUnicode_InternInPlace(&unknown_filename);
1051
1052 tracemalloc_empty_traceback.nframe = 1;
1053 /* borrowed reference */
1054 tracemalloc_empty_traceback.frames[0].filename = unknown_filename;
1055 tracemalloc_empty_traceback.frames[0].lineno = 0;
1056 tracemalloc_empty_traceback.hash = traceback_hash(&tracemalloc_empty_traceback);
1057
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001058 tracemalloc_config.initialized = TRACEMALLOC_INITIALIZED;
1059 return 0;
1060}
1061
Victor Stinnere492ae52016-03-22 12:58:23 +01001062
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001063static void
1064tracemalloc_deinit(void)
1065{
Victor Stinnerf9a71152016-03-22 23:54:42 +01001066 if (tracemalloc_config.initialized != TRACEMALLOC_INITIALIZED)
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001067 return;
1068 tracemalloc_config.initialized = TRACEMALLOC_FINALIZED;
1069
1070 tracemalloc_stop();
1071
1072 /* destroy hash tables */
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001073 _Py_hashtable_destroy(tracemalloc_tracebacks);
1074 _Py_hashtable_destroy(tracemalloc_filenames);
Victor Stinner285cf0a2016-03-21 22:00:58 +01001075 _Py_hashtable_destroy(tracemalloc_traces);
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001076
1077#if defined(WITH_THREAD) && defined(TRACE_RAW_MALLOC)
1078 if (tables_lock != NULL) {
1079 PyThread_free_lock(tables_lock);
1080 tables_lock = NULL;
1081 }
1082#endif
1083
1084#ifdef REENTRANT_THREADLOCAL
1085 PyThread_delete_key(tracemalloc_reentrant_key);
Victor Stinner4a066472016-03-22 17:45:09 +01001086 tracemalloc_reentrant_key = -1;
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001087#endif
1088
1089 Py_XDECREF(unknown_filename);
1090}
1091
Victor Stinnere492ae52016-03-22 12:58:23 +01001092
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001093static int
Victor Stinnerf28ce602013-11-27 22:27:13 +01001094tracemalloc_start(int max_nframe)
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001095{
Victor Stinnerd8f0d922014-06-02 21:57:10 +02001096 PyMemAllocatorEx alloc;
Victor Stinnerf28ce602013-11-27 22:27:13 +01001097 size_t size;
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001098
Victor Stinnerf9a71152016-03-22 23:54:42 +01001099 if (tracemalloc_init() < 0)
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001100 return -1;
1101
1102 if (tracemalloc_config.tracing) {
1103 /* hook already installed: do nothing */
1104 return 0;
1105 }
1106
Victor Stinner52aee852014-08-16 15:44:02 +02001107 assert(1 <= max_nframe && max_nframe <= MAX_NFRAME);
Victor Stinnerf28ce602013-11-27 22:27:13 +01001108 tracemalloc_config.max_nframe = max_nframe;
1109
1110 /* allocate a buffer to store a new traceback */
1111 size = TRACEBACK_SIZE(max_nframe);
1112 assert(tracemalloc_traceback == NULL);
1113 tracemalloc_traceback = raw_malloc(size);
1114 if (tracemalloc_traceback == NULL) {
1115 PyErr_NoMemory();
1116 return -1;
1117 }
1118
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001119#ifdef TRACE_RAW_MALLOC
1120 alloc.malloc = tracemalloc_raw_malloc;
Victor Stinnerdb067af2014-05-02 22:31:14 +02001121 alloc.calloc = tracemalloc_raw_calloc;
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001122 alloc.realloc = tracemalloc_raw_realloc;
1123 alloc.free = tracemalloc_free;
1124
1125 alloc.ctx = &allocators.raw;
1126 PyMem_GetAllocator(PYMEM_DOMAIN_RAW, &allocators.raw);
1127 PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &alloc);
1128#endif
1129
1130 alloc.malloc = tracemalloc_malloc_gil;
Victor Stinnerdb067af2014-05-02 22:31:14 +02001131 alloc.calloc = tracemalloc_calloc_gil;
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001132 alloc.realloc = tracemalloc_realloc_gil;
1133 alloc.free = tracemalloc_free;
1134
1135 alloc.ctx = &allocators.mem;
1136 PyMem_GetAllocator(PYMEM_DOMAIN_MEM, &allocators.mem);
1137 PyMem_SetAllocator(PYMEM_DOMAIN_MEM, &alloc);
1138
1139 alloc.ctx = &allocators.obj;
1140 PyMem_GetAllocator(PYMEM_DOMAIN_OBJ, &allocators.obj);
1141 PyMem_SetAllocator(PYMEM_DOMAIN_OBJ, &alloc);
1142
1143 /* everything is ready: start tracing Python memory allocations */
1144 tracemalloc_config.tracing = 1;
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001145
1146 return 0;
1147}
1148
Victor Stinnere492ae52016-03-22 12:58:23 +01001149
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001150static void
1151tracemalloc_stop(void)
1152{
Victor Stinnerf9a71152016-03-22 23:54:42 +01001153 if (!tracemalloc_config.tracing)
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001154 return;
1155
1156 /* stop tracing Python memory allocations */
1157 tracemalloc_config.tracing = 0;
1158
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001159 /* unregister the hook on memory allocators */
1160#ifdef TRACE_RAW_MALLOC
1161 PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &allocators.raw);
1162#endif
1163 PyMem_SetAllocator(PYMEM_DOMAIN_MEM, &allocators.mem);
1164 PyMem_SetAllocator(PYMEM_DOMAIN_OBJ, &allocators.obj);
1165
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001166 tracemalloc_clear_traces();
Victor Stinner285cf0a2016-03-21 22:00:58 +01001167
1168 /* release memory */
Victor Stinnerf28ce602013-11-27 22:27:13 +01001169 raw_free(tracemalloc_traceback);
1170 tracemalloc_traceback = NULL;
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001171}
1172
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001173
Victor Stinnere492ae52016-03-22 12:58:23 +01001174
Serhiy Storchakab451f912017-02-04 12:18:38 +02001175/*[clinic input]
1176_tracemalloc.is_tracing
1177
1178Return True if the tracemalloc module is tracing Python memory allocations.
1179[clinic start generated code]*/
1180
1181static PyObject *
1182_tracemalloc_is_tracing_impl(PyObject *module)
Serhiy Storchaka97353842017-02-05 22:58:46 +02001183/*[clinic end generated code: output=2d763b42601cd3ef input=af104b0a00192f63]*/
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001184{
1185 return PyBool_FromLong(tracemalloc_config.tracing);
1186}
1187
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001188
Serhiy Storchakab451f912017-02-04 12:18:38 +02001189/*[clinic input]
1190_tracemalloc.clear_traces
Victor Stinnere492ae52016-03-22 12:58:23 +01001191
Serhiy Storchakab451f912017-02-04 12:18:38 +02001192Clear traces of memory blocks allocated by Python.
1193[clinic start generated code]*/
1194
1195static PyObject *
1196_tracemalloc_clear_traces_impl(PyObject *module)
1197/*[clinic end generated code: output=a86080ee41b84197 input=0dab5b6c785183a5]*/
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001198{
1199 if (!tracemalloc_config.tracing)
1200 Py_RETURN_NONE;
1201
1202 set_reentrant(1);
1203 tracemalloc_clear_traces();
1204 set_reentrant(0);
1205
1206 Py_RETURN_NONE;
1207}
1208
Victor Stinnere492ae52016-03-22 12:58:23 +01001209
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001210static PyObject*
1211frame_to_pyobject(frame_t *frame)
1212{
1213 PyObject *frame_obj, *lineno_obj;
1214
1215 frame_obj = PyTuple_New(2);
1216 if (frame_obj == NULL)
1217 return NULL;
1218
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001219 Py_INCREF(frame->filename);
1220 PyTuple_SET_ITEM(frame_obj, 0, frame->filename);
1221
Victor Stinner95283342016-03-15 21:57:02 +01001222 lineno_obj = PyLong_FromUnsignedLong(frame->lineno);
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001223 if (lineno_obj == NULL) {
1224 Py_DECREF(frame_obj);
1225 return NULL;
1226 }
1227 PyTuple_SET_ITEM(frame_obj, 1, lineno_obj);
1228
1229 return frame_obj;
1230}
1231
Victor Stinnere492ae52016-03-22 12:58:23 +01001232
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001233static PyObject*
1234traceback_to_pyobject(traceback_t *traceback, _Py_hashtable_t *intern_table)
1235{
1236 int i;
1237 PyObject *frames, *frame;
1238
1239 if (intern_table != NULL) {
1240 if (_Py_HASHTABLE_GET(intern_table, traceback, frames)) {
1241 Py_INCREF(frames);
1242 return frames;
1243 }
1244 }
1245
1246 frames = PyTuple_New(traceback->nframe);
1247 if (frames == NULL)
1248 return NULL;
1249
1250 for (i=0; i < traceback->nframe; i++) {
1251 frame = frame_to_pyobject(&traceback->frames[i]);
1252 if (frame == NULL) {
1253 Py_DECREF(frames);
1254 return NULL;
1255 }
1256 PyTuple_SET_ITEM(frames, i, frame);
1257 }
1258
1259 if (intern_table != NULL) {
1260 if (_Py_HASHTABLE_SET(intern_table, traceback, frames) < 0) {
1261 Py_DECREF(frames);
1262 PyErr_NoMemory();
1263 return NULL;
1264 }
1265 /* intern_table keeps a new reference to frames */
1266 Py_INCREF(frames);
1267 }
1268 return frames;
1269}
1270
Victor Stinnere492ae52016-03-22 12:58:23 +01001271
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001272static PyObject*
Victor Stinner5ea4c062017-06-20 17:46:36 +02001273trace_to_pyobject(unsigned int domain, trace_t *trace,
Victor Stinnere492ae52016-03-22 12:58:23 +01001274 _Py_hashtable_t *intern_tracebacks)
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001275{
1276 PyObject *trace_obj = NULL;
Victor Stinnere492ae52016-03-22 12:58:23 +01001277 PyObject *obj;
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001278
Victor Stinnere492ae52016-03-22 12:58:23 +01001279 trace_obj = PyTuple_New(3);
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001280 if (trace_obj == NULL)
1281 return NULL;
1282
Victor Stinnere492ae52016-03-22 12:58:23 +01001283 obj = PyLong_FromSize_t(domain);
1284 if (obj == NULL) {
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001285 Py_DECREF(trace_obj);
1286 return NULL;
1287 }
Victor Stinnere492ae52016-03-22 12:58:23 +01001288 PyTuple_SET_ITEM(trace_obj, 0, obj);
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001289
Victor Stinnere492ae52016-03-22 12:58:23 +01001290 obj = PyLong_FromSize_t(trace->size);
1291 if (obj == NULL) {
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001292 Py_DECREF(trace_obj);
1293 return NULL;
1294 }
Victor Stinnere492ae52016-03-22 12:58:23 +01001295 PyTuple_SET_ITEM(trace_obj, 1, obj);
1296
1297 obj = traceback_to_pyobject(trace->traceback, intern_tracebacks);
1298 if (obj == NULL) {
1299 Py_DECREF(trace_obj);
1300 return NULL;
1301 }
1302 PyTuple_SET_ITEM(trace_obj, 2, obj);
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001303
1304 return trace_obj;
1305}
1306
Victor Stinnere492ae52016-03-22 12:58:23 +01001307
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001308typedef struct {
1309 _Py_hashtable_t *traces;
1310 _Py_hashtable_t *tracebacks;
1311 PyObject *list;
1312} get_traces_t;
1313
1314static int
Victor Stinner285cf0a2016-03-21 22:00:58 +01001315tracemalloc_get_traces_fill(_Py_hashtable_t *traces, _Py_hashtable_entry_t *entry,
1316 void *user_data)
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001317{
1318 get_traces_t *get_traces = user_data;
Victor Stinner5ea4c062017-06-20 17:46:36 +02001319 unsigned int domain;
Victor Stinner5dacbd42016-03-23 09:52:13 +01001320 trace_t trace;
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001321 PyObject *tracemalloc_obj;
1322 int res;
1323
Victor Stinnere492ae52016-03-22 12:58:23 +01001324 if (tracemalloc_config.use_domain) {
1325 pointer_t key;
Victor Stinner5dacbd42016-03-23 09:52:13 +01001326 _Py_HASHTABLE_ENTRY_READ_KEY(traces, entry, key);
Victor Stinnere492ae52016-03-22 12:58:23 +01001327 domain = key.domain;
1328 }
1329 else {
1330 domain = DEFAULT_DOMAIN;
1331 }
Victor Stinner5dacbd42016-03-23 09:52:13 +01001332 _Py_HASHTABLE_ENTRY_READ_DATA(traces, entry, trace);
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001333
Victor Stinner5dacbd42016-03-23 09:52:13 +01001334 tracemalloc_obj = trace_to_pyobject(domain, &trace, get_traces->tracebacks);
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001335 if (tracemalloc_obj == NULL)
1336 return 1;
1337
1338 res = PyList_Append(get_traces->list, tracemalloc_obj);
1339 Py_DECREF(tracemalloc_obj);
1340 if (res < 0)
1341 return 1;
1342
1343 return 0;
1344}
1345
Victor Stinnere492ae52016-03-22 12:58:23 +01001346
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001347static int
Victor Stinner285cf0a2016-03-21 22:00:58 +01001348tracemalloc_pyobject_decref_cb(_Py_hashtable_t *tracebacks,
1349 _Py_hashtable_entry_t *entry,
1350 void *user_data)
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001351{
Victor Stinnerc9553872016-03-22 12:13:01 +01001352 PyObject *obj;
Victor Stinnere8c6b2f2016-03-23 09:25:01 +01001353 _Py_HASHTABLE_ENTRY_READ_DATA(tracebacks, entry, obj);
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001354 Py_DECREF(obj);
1355 return 0;
1356}
1357
Victor Stinnere492ae52016-03-22 12:58:23 +01001358
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001359
Serhiy Storchakab451f912017-02-04 12:18:38 +02001360/*[clinic input]
1361_tracemalloc._get_traces
1362
1363Get traces of all memory blocks allocated by Python.
1364
1365Return a list of (size: int, traceback: tuple) tuples.
1366traceback is a tuple of (filename: str, lineno: int) tuples.
1367
1368Return an empty list if the tracemalloc module is disabled.
1369[clinic start generated code]*/
1370
1371static PyObject *
1372_tracemalloc__get_traces_impl(PyObject *module)
1373/*[clinic end generated code: output=e9929876ced4b5cc input=6c7d2230b24255aa]*/
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001374{
1375 get_traces_t get_traces;
1376 int err;
1377
1378 get_traces.traces = NULL;
1379 get_traces.tracebacks = NULL;
1380 get_traces.list = PyList_New(0);
1381 if (get_traces.list == NULL)
1382 goto error;
1383
1384 if (!tracemalloc_config.tracing)
1385 return get_traces.list;
1386
Victor Stinnerde2f1322013-11-26 00:26:23 +01001387 /* the traceback hash table is used temporarily to intern traceback tuple
1388 of (filename, lineno) tuples */
Victor Stinnerc9553872016-03-22 12:13:01 +01001389 get_traces.tracebacks = hashtable_new(sizeof(traceback_t *),
1390 sizeof(PyObject *),
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001391 _Py_hashtable_hash_ptr,
1392 _Py_hashtable_compare_direct);
1393 if (get_traces.tracebacks == NULL) {
1394 PyErr_NoMemory();
1395 goto error;
1396 }
1397
1398 TABLES_LOCK();
1399 get_traces.traces = _Py_hashtable_copy(tracemalloc_traces);
1400 TABLES_UNLOCK();
1401
1402 if (get_traces.traces == NULL) {
1403 PyErr_NoMemory();
1404 goto error;
1405 }
1406
1407 set_reentrant(1);
1408 err = _Py_hashtable_foreach(get_traces.traces,
1409 tracemalloc_get_traces_fill, &get_traces);
1410 set_reentrant(0);
1411 if (err)
1412 goto error;
1413
1414 goto finally;
1415
1416error:
1417 Py_CLEAR(get_traces.list);
1418
1419finally:
1420 if (get_traces.tracebacks != NULL) {
1421 _Py_hashtable_foreach(get_traces.tracebacks,
Victor Stinner285cf0a2016-03-21 22:00:58 +01001422 tracemalloc_pyobject_decref_cb, NULL);
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001423 _Py_hashtable_destroy(get_traces.tracebacks);
1424 }
Victor Stinnerc9553872016-03-22 12:13:01 +01001425 if (get_traces.traces != NULL) {
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001426 _Py_hashtable_destroy(get_traces.traces);
Victor Stinnerc9553872016-03-22 12:13:01 +01001427 }
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001428
1429 return get_traces.list;
1430}
1431
Victor Stinnere492ae52016-03-22 12:58:23 +01001432
Victor Stinner0611c262016-03-15 22:22:13 +01001433static traceback_t*
Victor Stinner5ea4c062017-06-20 17:46:36 +02001434tracemalloc_get_traceback(unsigned int domain, uintptr_t ptr)
Victor Stinner0611c262016-03-15 22:22:13 +01001435{
1436 trace_t trace;
1437 int found;
1438
1439 if (!tracemalloc_config.tracing)
1440 return NULL;
1441
1442 TABLES_LOCK();
Victor Stinnere492ae52016-03-22 12:58:23 +01001443 if (tracemalloc_config.use_domain) {
Victor Stinner10b73e12016-03-22 13:39:05 +01001444 pointer_t key = {ptr, domain};
Victor Stinnere492ae52016-03-22 12:58:23 +01001445 found = _Py_HASHTABLE_GET(tracemalloc_traces, key, trace);
1446 }
1447 else {
1448 found = _Py_HASHTABLE_GET(tracemalloc_traces, ptr, trace);
1449 }
Victor Stinner0611c262016-03-15 22:22:13 +01001450 TABLES_UNLOCK();
1451
1452 if (!found)
1453 return NULL;
1454
1455 return trace.traceback;
1456}
1457
Victor Stinnere492ae52016-03-22 12:58:23 +01001458
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001459
Serhiy Storchakab451f912017-02-04 12:18:38 +02001460/*[clinic input]
1461_tracemalloc._get_object_traceback
1462
1463 obj: object
1464 /
1465
1466Get the traceback where the Python object obj was allocated.
1467
1468Return a tuple of (filename: str, lineno: int) tuples.
1469Return None if the tracemalloc module is disabled or did not
1470trace the allocation of the object.
1471[clinic start generated code]*/
1472
1473static PyObject *
1474_tracemalloc__get_object_traceback(PyObject *module, PyObject *obj)
1475/*[clinic end generated code: output=41ee0553a658b0aa input=29495f1b21c53212]*/
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001476{
1477 PyTypeObject *type;
1478 void *ptr;
Victor Stinner0611c262016-03-15 22:22:13 +01001479 traceback_t *traceback;
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001480
1481 type = Py_TYPE(obj);
1482 if (PyType_IS_GC(type))
1483 ptr = (void *)((char *)obj - sizeof(PyGC_Head));
1484 else
1485 ptr = (void *)obj;
1486
Benjamin Petersonca470632016-09-06 13:47:26 -07001487 traceback = tracemalloc_get_traceback(DEFAULT_DOMAIN, (uintptr_t)ptr);
Victor Stinner0611c262016-03-15 22:22:13 +01001488 if (traceback == NULL)
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001489 Py_RETURN_NONE;
1490
Victor Stinner0611c262016-03-15 22:22:13 +01001491 return traceback_to_pyobject(traceback, NULL);
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001492}
1493
Victor Stinnere492ae52016-03-22 12:58:23 +01001494
Victor Stinner0611c262016-03-15 22:22:13 +01001495#define PUTS(fd, str) _Py_write_noraise(fd, str, (int)strlen(str))
1496
1497static void
1498_PyMem_DumpFrame(int fd, frame_t * frame)
1499{
1500 PUTS(fd, " File \"");
1501 _Py_DumpASCII(fd, frame->filename);
1502 PUTS(fd, "\", line ");
1503 _Py_DumpDecimal(fd, frame->lineno);
1504 PUTS(fd, "\n");
1505}
1506
1507/* Dump the traceback where a memory block was allocated into file descriptor
1508 fd. The function may block on TABLES_LOCK() but it is unlikely. */
1509void
1510_PyMem_DumpTraceback(int fd, const void *ptr)
1511{
1512 traceback_t *traceback;
1513 int i;
1514
Benjamin Petersonca470632016-09-06 13:47:26 -07001515 traceback = tracemalloc_get_traceback(DEFAULT_DOMAIN, (uintptr_t)ptr);
Victor Stinner0611c262016-03-15 22:22:13 +01001516 if (traceback == NULL)
1517 return;
1518
1519 PUTS(fd, "Memory block allocated at (most recent call first):\n");
1520 for (i=0; i < traceback->nframe; i++) {
1521 _PyMem_DumpFrame(fd, &traceback->frames[i]);
1522 }
1523 PUTS(fd, "\n");
1524}
1525
1526#undef PUTS
1527
Victor Stinnere492ae52016-03-22 12:58:23 +01001528
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001529
Serhiy Storchakab451f912017-02-04 12:18:38 +02001530/*[clinic input]
1531_tracemalloc.start
1532
1533 nframe: Py_ssize_t = 1
1534 /
1535
1536Start tracing Python memory allocations.
1537
1538Also set the maximum number of frames stored in the traceback of a
1539trace to nframe.
1540[clinic start generated code]*/
1541
1542static PyObject *
1543_tracemalloc_start_impl(PyObject *module, Py_ssize_t nframe)
1544/*[clinic end generated code: output=0f558d2079511553 input=997841629cc441cb]*/
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001545{
Victor Stinnerf28ce602013-11-27 22:27:13 +01001546 int nframe_int;
Victor Stinner3728d6c2013-11-23 12:37:20 +01001547
Victor Stinner52aee852014-08-16 15:44:02 +02001548 if (nframe < 1 || nframe > MAX_NFRAME) {
Victor Stinner3728d6c2013-11-23 12:37:20 +01001549 PyErr_Format(PyExc_ValueError,
1550 "the number of frames must be in range [1; %i]",
Serhiy Storchakab451f912017-02-04 12:18:38 +02001551 (int)MAX_NFRAME);
Victor Stinner3728d6c2013-11-23 12:37:20 +01001552 return NULL;
1553 }
Victor Stinnerf28ce602013-11-27 22:27:13 +01001554 nframe_int = Py_SAFE_DOWNCAST(nframe, Py_ssize_t, int);
Victor Stinner3728d6c2013-11-23 12:37:20 +01001555
Victor Stinnerf9a71152016-03-22 23:54:42 +01001556 if (tracemalloc_start(nframe_int) < 0)
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001557 return NULL;
1558
1559 Py_RETURN_NONE;
1560}
1561
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001562
Serhiy Storchakab451f912017-02-04 12:18:38 +02001563/*[clinic input]
1564_tracemalloc.stop
Victor Stinnere492ae52016-03-22 12:58:23 +01001565
Serhiy Storchakab451f912017-02-04 12:18:38 +02001566Stop tracing Python memory allocations.
1567
1568Also clear traces of memory blocks allocated by Python.
1569[clinic start generated code]*/
1570
1571static PyObject *
1572_tracemalloc_stop_impl(PyObject *module)
1573/*[clinic end generated code: output=c3c42ae03e3955cd input=7478f075e51dae18]*/
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001574{
1575 tracemalloc_stop();
1576 Py_RETURN_NONE;
1577}
1578
Victor Stinnere492ae52016-03-22 12:58:23 +01001579
Serhiy Storchakab451f912017-02-04 12:18:38 +02001580/*[clinic input]
1581_tracemalloc.get_traceback_limit
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001582
Serhiy Storchakab451f912017-02-04 12:18:38 +02001583Get the maximum number of frames stored in the traceback of a trace.
1584
1585By default, a trace of an allocated memory block only stores
1586the most recent frame: the limit is 1.
1587[clinic start generated code]*/
1588
1589static PyObject *
1590_tracemalloc_get_traceback_limit_impl(PyObject *module)
1591/*[clinic end generated code: output=d556d9306ba95567 input=da3cd977fc68ae3b]*/
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001592{
1593 return PyLong_FromLong(tracemalloc_config.max_nframe);
1594}
1595
Victor Stinnere492ae52016-03-22 12:58:23 +01001596
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001597
Serhiy Storchakab451f912017-02-04 12:18:38 +02001598/*[clinic input]
1599_tracemalloc.get_tracemalloc_memory
1600
1601Get the memory usage in bytes of the tracemalloc module.
1602
1603This memory is used internally to trace memory allocations.
1604[clinic start generated code]*/
1605
1606static PyObject *
1607_tracemalloc_get_tracemalloc_memory_impl(PyObject *module)
1608/*[clinic end generated code: output=e3f14e280a55f5aa input=5d919c0f4d5132ad]*/
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001609{
1610 size_t size;
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001611
1612 size = _Py_hashtable_size(tracemalloc_tracebacks);
1613 size += _Py_hashtable_size(tracemalloc_filenames);
1614
1615 TABLES_LOCK();
1616 size += _Py_hashtable_size(tracemalloc_traces);
1617 TABLES_UNLOCK();
1618
Serhiy Storchakab451f912017-02-04 12:18:38 +02001619 return PyLong_FromSize_t(size);
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001620}
1621
Victor Stinnere492ae52016-03-22 12:58:23 +01001622
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001623
Serhiy Storchakab451f912017-02-04 12:18:38 +02001624/*[clinic input]
1625_tracemalloc.get_traced_memory
1626
1627Get the current size and peak size of memory blocks traced by tracemalloc.
1628
1629Returns a tuple: (current: int, peak: int).
1630[clinic start generated code]*/
1631
1632static PyObject *
1633_tracemalloc_get_traced_memory_impl(PyObject *module)
1634/*[clinic end generated code: output=5b167189adb9e782 input=61ddb5478400ff66]*/
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001635{
Victor Stinner3c0481d2013-11-27 21:39:49 +01001636 Py_ssize_t size, peak_size;
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001637
1638 if (!tracemalloc_config.tracing)
1639 return Py_BuildValue("ii", 0, 0);
1640
1641 TABLES_LOCK();
1642 size = tracemalloc_traced_memory;
Victor Stinner3c0481d2013-11-27 21:39:49 +01001643 peak_size = tracemalloc_peak_traced_memory;
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001644 TABLES_UNLOCK();
1645
Serhiy Storchakab451f912017-02-04 12:18:38 +02001646 return Py_BuildValue("nn", size, peak_size);
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001647}
1648
Victor Stinnere492ae52016-03-22 12:58:23 +01001649
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001650static PyMethodDef module_methods[] = {
Serhiy Storchakab451f912017-02-04 12:18:38 +02001651 _TRACEMALLOC_IS_TRACING_METHODDEF
1652 _TRACEMALLOC_CLEAR_TRACES_METHODDEF
1653 _TRACEMALLOC__GET_TRACES_METHODDEF
1654 _TRACEMALLOC__GET_OBJECT_TRACEBACK_METHODDEF
1655 _TRACEMALLOC_START_METHODDEF
1656 _TRACEMALLOC_STOP_METHODDEF
1657 _TRACEMALLOC_GET_TRACEBACK_LIMIT_METHODDEF
1658 _TRACEMALLOC_GET_TRACEMALLOC_MEMORY_METHODDEF
1659 _TRACEMALLOC_GET_TRACED_MEMORY_METHODDEF
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001660 /* sentinel */
1661 {NULL, NULL}
1662};
1663
1664PyDoc_STRVAR(module_doc,
1665"Debug module to trace memory blocks allocated by Python.");
1666
1667static struct PyModuleDef module_def = {
1668 PyModuleDef_HEAD_INIT,
1669 "_tracemalloc",
1670 module_doc,
1671 0, /* non-negative size to be able to unload the module */
1672 module_methods,
1673 NULL,
1674};
1675
1676PyMODINIT_FUNC
1677PyInit__tracemalloc(void)
1678{
1679 PyObject *m;
1680 m = PyModule_Create(&module_def);
1681 if (m == NULL)
1682 return NULL;
1683
1684 if (tracemalloc_init() < 0)
1685 return NULL;
1686
1687 return m;
1688}
1689
Victor Stinnere492ae52016-03-22 12:58:23 +01001690
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001691static int
1692parse_sys_xoptions(PyObject *value)
1693{
1694 PyObject *valuelong;
1695 long nframe;
1696
1697 if (value == Py_True)
1698 return 1;
1699
1700 assert(PyUnicode_Check(value));
1701 if (PyUnicode_GetLength(value) == 0)
1702 return -1;
1703
1704 valuelong = PyLong_FromUnicodeObject(value, 10);
1705 if (valuelong == NULL)
1706 return -1;
1707
1708 nframe = PyLong_AsLong(valuelong);
1709 Py_DECREF(valuelong);
1710 if (nframe == -1 && PyErr_Occurred())
1711 return -1;
1712
Victor Stinner52aee852014-08-16 15:44:02 +02001713 if (nframe < 1 || nframe > MAX_NFRAME)
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001714 return -1;
1715
1716 return Py_SAFE_DOWNCAST(nframe, long, int);
1717}
1718
Victor Stinnere492ae52016-03-22 12:58:23 +01001719
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001720int
1721_PyTraceMalloc_Init(void)
1722{
1723 char *p;
1724 int nframe;
1725
1726#ifdef WITH_THREAD
1727 assert(PyGILState_Check());
1728#endif
1729
1730 if ((p = Py_GETENV("PYTHONTRACEMALLOC")) && *p != '\0') {
1731 char *endptr = p;
Victor Stinnerf28ce602013-11-27 22:27:13 +01001732 long value;
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001733
Victor Stinner711e27c2013-12-16 23:06:19 +01001734 errno = 0;
Victor Stinnerf28ce602013-11-27 22:27:13 +01001735 value = strtol(p, &endptr, 10);
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001736 if (*endptr != '\0'
1737 || value < 1
Victor Stinner52aee852014-08-16 15:44:02 +02001738 || value > MAX_NFRAME
Victor Stinner711e27c2013-12-16 23:06:19 +01001739 || errno == ERANGE)
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001740 {
Victor Stinnerf28ce602013-11-27 22:27:13 +01001741 Py_FatalError("PYTHONTRACEMALLOC: invalid number of frames");
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001742 return -1;
1743 }
1744
1745 nframe = (int)value;
1746 }
1747 else {
1748 PyObject *xoptions, *key, *value;
1749
1750 xoptions = PySys_GetXOptions();
1751 if (xoptions == NULL)
1752 return -1;
1753
1754 key = PyUnicode_FromString("tracemalloc");
1755 if (key == NULL)
1756 return -1;
1757
Xiang Zhang4ed5ad72017-07-19 00:33:29 +08001758 value = PyDict_GetItemWithError(xoptions, key); /* borrowed */
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001759 Py_DECREF(key);
1760 if (value == NULL) {
1761 if (PyErr_Occurred())
1762 return -1;
1763
1764 /* -X tracemalloc is not used */
1765 return 0;
1766 }
1767
1768 nframe = parse_sys_xoptions(value);
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001769 if (nframe < 0) {
Victor Stinnerf28ce602013-11-27 22:27:13 +01001770 Py_FatalError("-X tracemalloc=NFRAME: invalid number of frames");
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001771 }
1772 }
1773
Victor Stinnerf28ce602013-11-27 22:27:13 +01001774 return tracemalloc_start(nframe);
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001775}
1776
Victor Stinnere492ae52016-03-22 12:58:23 +01001777
Victor Stinnerbe0708f2013-12-01 10:03:26 +01001778void
1779_PyTraceMalloc_Fini(void)
1780{
1781#ifdef WITH_THREAD
1782 assert(PyGILState_Check());
1783#endif
1784 tracemalloc_deinit();
1785}
Victor Stinner10b73e12016-03-22 13:39:05 +01001786
1787int
Victor Stinner5ea4c062017-06-20 17:46:36 +02001788PyTraceMalloc_Track(unsigned int domain, uintptr_t ptr,
1789 size_t size)
Victor Stinner10b73e12016-03-22 13:39:05 +01001790{
1791 int res;
1792#ifdef WITH_THREAD
1793 PyGILState_STATE gil_state;
1794#endif
1795
1796 if (!tracemalloc_config.tracing) {
1797 /* tracemalloc is not tracing: do nothing */
1798 return -2;
1799 }
1800
1801#ifdef WITH_THREAD
1802 gil_state = PyGILState_Ensure();
1803#endif
1804
1805 TABLES_LOCK();
1806 res = tracemalloc_add_trace(domain, ptr, size);
1807 TABLES_UNLOCK();
1808
1809#ifdef WITH_THREAD
1810 PyGILState_Release(gil_state);
1811#endif
1812 return res;
1813}
1814
1815
1816int
Victor Stinner5ea4c062017-06-20 17:46:36 +02001817PyTraceMalloc_Untrack(unsigned int domain, uintptr_t ptr)
Victor Stinner10b73e12016-03-22 13:39:05 +01001818{
1819 if (!tracemalloc_config.tracing) {
1820 /* tracemalloc is not tracing: do nothing */
1821 return -2;
1822 }
1823
1824 TABLES_LOCK();
1825 tracemalloc_remove_trace(domain, ptr);
1826 TABLES_UNLOCK();
1827
1828 return 0;
1829}
1830
1831
1832PyObject*
Victor Stinner5ea4c062017-06-20 17:46:36 +02001833_PyTraceMalloc_GetTraceback(unsigned int domain, uintptr_t ptr)
Victor Stinner10b73e12016-03-22 13:39:05 +01001834{
1835 traceback_t *traceback;
1836
1837 traceback = tracemalloc_get_traceback(domain, ptr);
1838 if (traceback == NULL)
1839 Py_RETURN_NONE;
1840
1841 return traceback_to_pyobject(traceback, NULL);
1842}