blob: 226a473b4c74e862f124391ae4a6a27720744906 [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 Stinnerbe0708f2013-12-01 10:03:26 +010042} tracemalloc_config = {TRACEMALLOC_NOT_INITIALIZED, 0, 1};
Victor Stinnered3b0bc2013-11-23 12:27:24 +010043
44#if defined(TRACE_RAW_MALLOC) && defined(WITH_THREAD)
45/* This lock is needed because tracemalloc_free() is called without
46 the GIL held from PyMem_RawFree(). It cannot acquire the lock because it
47 would introduce a deadlock in PyThreadState_DeleteCurrent(). */
48static PyThread_type_lock tables_lock;
49# define TABLES_LOCK() PyThread_acquire_lock(tables_lock, 1)
50# define TABLES_UNLOCK() PyThread_release_lock(tables_lock)
51#else
52 /* variables are protected by the GIL */
53# define TABLES_LOCK()
54# define TABLES_UNLOCK()
55#endif
56
57/* Pack the frame_t structure to reduce the memory footprint on 64-bit
58 architectures: 12 bytes instead of 16. This optimization might produce
59 SIGBUS on architectures not supporting unaligned memory accesses (64-bit
Victor Stinner444f1242015-03-18 16:05:18 +010060 MIPS CPU?): on such architecture, the structure must not be packed. */
Victor Stinnered3b0bc2013-11-23 12:27:24 +010061typedef struct
62#ifdef __GNUC__
63__attribute__((packed))
Victor Stinnerdd382ef2014-02-01 03:43:58 +010064#elif defined(_MSC_VER)
65_declspec(align(4))
Victor Stinnered3b0bc2013-11-23 12:27:24 +010066#endif
67{
68 PyObject *filename;
69 int lineno;
70} frame_t;
71
72typedef struct {
73 Py_uhash_t hash;
74 int nframe;
75 frame_t frames[1];
76} traceback_t;
77
78#define TRACEBACK_SIZE(NFRAME) \
79 (sizeof(traceback_t) + sizeof(frame_t) * (NFRAME - 1))
Victor Stinnerf28ce602013-11-27 22:27:13 +010080
81#define MAX_NFRAME \
Victor Stinner52aee852014-08-16 15:44:02 +020082 ((INT_MAX - (int)sizeof(traceback_t)) / (int)sizeof(frame_t) + 1)
Victor Stinnered3b0bc2013-11-23 12:27:24 +010083
84static PyObject *unknown_filename = NULL;
85static traceback_t tracemalloc_empty_traceback;
86
Victor Stinner7a5be142013-11-26 01:06:02 +010087/* Trace of a memory block */
Victor Stinnered3b0bc2013-11-23 12:27:24 +010088typedef struct {
Victor Stinner7a5be142013-11-26 01:06:02 +010089 /* Size of the memory block in bytes */
Victor Stinnered3b0bc2013-11-23 12:27:24 +010090 size_t size;
Victor Stinner7a5be142013-11-26 01:06:02 +010091
92 /* Traceback where the memory block was allocated */
Victor Stinnered3b0bc2013-11-23 12:27:24 +010093 traceback_t *traceback;
94} trace_t;
95
96/* Size in bytes of currently traced memory.
97 Protected by TABLES_LOCK(). */
98static size_t tracemalloc_traced_memory = 0;
99
Victor Stinner3c0481d2013-11-27 21:39:49 +0100100/* Peak size in bytes of traced memory.
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100101 Protected by TABLES_LOCK(). */
Victor Stinner3c0481d2013-11-27 21:39:49 +0100102static size_t tracemalloc_peak_traced_memory = 0;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100103
Serhiy Storchaka56a6d852014-12-01 18:28:43 +0200104/* Hash table used as a set to intern filenames:
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100105 PyObject* => PyObject*.
106 Protected by the GIL */
107static _Py_hashtable_t *tracemalloc_filenames = NULL;
108
Victor Stinnerf28ce602013-11-27 22:27:13 +0100109/* Buffer to store a new traceback in traceback_new().
110 Protected by the GIL. */
111static traceback_t *tracemalloc_traceback = NULL;
112
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100113/* Hash table used as a set to intern tracebacks:
114 traceback_t* => traceback_t*
115 Protected by the GIL */
116static _Py_hashtable_t *tracemalloc_tracebacks = NULL;
117
118/* pointer (void*) => trace (trace_t).
119 Protected by TABLES_LOCK(). */
120static _Py_hashtable_t *tracemalloc_traces = NULL;
121
122#ifdef TRACE_DEBUG
123static void
124tracemalloc_error(const char *format, ...)
125{
126 va_list ap;
127 fprintf(stderr, "tracemalloc: ");
128 va_start(ap, format);
129 vfprintf(stderr, format, ap);
130 va_end(ap);
131 fprintf(stderr, "\n");
132 fflush(stderr);
133}
134#endif
135
136#if defined(WITH_THREAD) && defined(TRACE_RAW_MALLOC)
137#define REENTRANT_THREADLOCAL
138
139/* If your OS does not provide native thread local storage, you can implement
140 it manually using a lock. Functions of thread.c cannot be used because
141 they use PyMem_RawMalloc() which leads to a reentrant call. */
142#if !(defined(_POSIX_THREADS) || defined(NT_THREADS))
143# error "need native thread local storage (TLS)"
144#endif
145
146static int tracemalloc_reentrant_key;
147
148/* Any non-NULL pointer can be used */
149#define REENTRANT Py_True
150
151static int
152get_reentrant(void)
153{
154 void *ptr = PyThread_get_key_value(tracemalloc_reentrant_key);
155 if (ptr != NULL) {
156 assert(ptr == REENTRANT);
157 return 1;
158 }
159 else
160 return 0;
161}
162
163static void
164set_reentrant(int reentrant)
165{
Victor Stinner2ead3d22013-11-26 01:08:53 +0100166 assert(reentrant == 0 || reentrant == 1);
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100167 if (reentrant) {
168 assert(PyThread_get_key_value(tracemalloc_reentrant_key) == NULL);
Victor Stinner590cebe2013-12-13 11:08:56 +0100169 PyThread_set_key_value(tracemalloc_reentrant_key, REENTRANT);
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100170 }
171 else {
Victor Stinner590cebe2013-12-13 11:08:56 +0100172 assert(PyThread_get_key_value(tracemalloc_reentrant_key) == REENTRANT);
173 PyThread_set_key_value(tracemalloc_reentrant_key, NULL);
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100174 }
175}
176
177#else
178
179/* WITH_THREAD not defined: Python compiled without threads,
180 or TRACE_RAW_MALLOC not defined: variable protected by the GIL */
181static int tracemalloc_reentrant = 0;
182
183static int
184get_reentrant(void)
185{
186 return tracemalloc_reentrant;
187}
188
189static void
190set_reentrant(int reentrant)
191{
192 assert(!reentrant || !get_reentrant());
193 tracemalloc_reentrant = reentrant;
194}
195#endif
196
197static int
198hashtable_compare_unicode(const void *key, const _Py_hashtable_entry_t *entry)
199{
200 if (key != NULL && entry->key != NULL)
201 return (PyUnicode_Compare((PyObject *)key, (PyObject *)entry->key) == 0);
202 else
203 return key == entry->key;
204}
205
206static _Py_hashtable_allocator_t hashtable_alloc = {malloc, free};
207
208static _Py_hashtable_t *
209hashtable_new(size_t data_size,
210 _Py_hashtable_hash_func hash_func,
211 _Py_hashtable_compare_func compare_func)
212{
213 return _Py_hashtable_new_full(data_size, 0,
214 hash_func, compare_func,
215 NULL, NULL, NULL, &hashtable_alloc);
216}
217
218static void*
219raw_malloc(size_t size)
220{
221 return allocators.raw.malloc(allocators.raw.ctx, size);
222}
223
224static void
225raw_free(void *ptr)
226{
227 allocators.raw.free(allocators.raw.ctx, ptr);
228}
229
230static Py_uhash_t
231hashtable_hash_traceback(const void *key)
232{
233 const traceback_t *traceback = key;
234 return traceback->hash;
235}
236
237static int
238hashtable_compare_traceback(const traceback_t *traceback1,
239 const _Py_hashtable_entry_t *he)
240{
241 const traceback_t *traceback2 = he->key;
242 const frame_t *frame1, *frame2;
243 int i;
244
245 if (traceback1->nframe != traceback2->nframe)
246 return 0;
247
248 for (i=0; i < traceback1->nframe; i++) {
249 frame1 = &traceback1->frames[i];
250 frame2 = &traceback2->frames[i];
251
252 if (frame1->lineno != frame2->lineno)
253 return 0;
254
255 if (frame1->filename != frame2->filename) {
256 assert(PyUnicode_Compare(frame1->filename, frame2->filename) != 0);
257 return 0;
258 }
259 }
260 return 1;
261}
262
263static void
264tracemalloc_get_frame(PyFrameObject *pyframe, frame_t *frame)
265{
266 PyCodeObject *code;
267 PyObject *filename;
268 _Py_hashtable_entry_t *entry;
269
270 frame->filename = unknown_filename;
271 frame->lineno = PyFrame_GetLineNumber(pyframe);
272 assert(frame->lineno >= 0);
273 if (frame->lineno < 0)
274 frame->lineno = 0;
275
276 code = pyframe->f_code;
277 if (code == NULL) {
278#ifdef TRACE_DEBUG
Victor Stinner4dc74202013-11-26 01:18:52 +0100279 tracemalloc_error("failed to get the code object of the frame");
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100280#endif
281 return;
282 }
283
284 if (code->co_filename == NULL) {
285#ifdef TRACE_DEBUG
286 tracemalloc_error("failed to get the filename of the code object");
287#endif
288 return;
289 }
290
291 filename = code->co_filename;
292 assert(filename != NULL);
293 if (filename == NULL)
294 return;
295
296 if (!PyUnicode_Check(filename)) {
297#ifdef TRACE_DEBUG
298 tracemalloc_error("filename is not an unicode string");
299#endif
300 return;
301 }
302 if (!PyUnicode_IS_READY(filename)) {
303 /* Don't make a Unicode string ready to avoid reentrant calls
304 to tracemalloc_malloc() or tracemalloc_realloc() */
305#ifdef TRACE_DEBUG
306 tracemalloc_error("filename is not a ready unicode string");
307#endif
308 return;
309 }
310
311 /* intern the filename */
312 entry = _Py_hashtable_get_entry(tracemalloc_filenames, filename);
313 if (entry != NULL) {
314 filename = (PyObject *)entry->key;
315 }
316 else {
317 /* tracemalloc_filenames is responsible to keep a reference
318 to the filename */
319 Py_INCREF(filename);
320 if (_Py_hashtable_set(tracemalloc_filenames, filename, NULL, 0) < 0) {
321 Py_DECREF(filename);
322#ifdef TRACE_DEBUG
323 tracemalloc_error("failed to intern the filename");
324#endif
325 return;
326 }
327 }
328
329 /* the tracemalloc_filenames table keeps a reference to the filename */
330 frame->filename = filename;
331}
332
333static Py_uhash_t
334traceback_hash(traceback_t *traceback)
335{
336 /* code based on tuplehash() of Objects/tupleobject.c */
Victor Stinner4d8c29c2013-12-16 23:05:13 +0100337 Py_uhash_t x, y; /* Unsigned for defined overflow behavior. */
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100338 int len = traceback->nframe;
339 Py_uhash_t mult = _PyHASH_MULTIPLIER;
340 frame_t *frame;
341
342 x = 0x345678UL;
343 frame = traceback->frames;
344 while (--len >= 0) {
Victor Stinner4d8c29c2013-12-16 23:05:13 +0100345 y = (Py_uhash_t)PyObject_Hash(frame->filename);
346 y ^= (Py_uhash_t)frame->lineno;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100347 frame++;
348
349 x = (x ^ y) * mult;
350 /* the cast might truncate len; that doesn't change hash stability */
Victor Stinner4d8c29c2013-12-16 23:05:13 +0100351 mult += (Py_uhash_t)(82520UL + len + len);
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100352 }
353 x += 97531UL;
354 return x;
355}
356
357static void
358traceback_get_frames(traceback_t *traceback)
359{
360 PyThreadState *tstate;
361 PyFrameObject *pyframe;
362
363#ifdef WITH_THREAD
364 tstate = PyGILState_GetThisThreadState();
365#else
366 tstate = PyThreadState_Get();
367#endif
368 if (tstate == NULL) {
369#ifdef TRACE_DEBUG
370 tracemalloc_error("failed to get the current thread state");
371#endif
372 return;
373 }
374
375 for (pyframe = tstate->frame; pyframe != NULL; pyframe = pyframe->f_back) {
376 tracemalloc_get_frame(pyframe, &traceback->frames[traceback->nframe]);
377 assert(traceback->frames[traceback->nframe].filename != NULL);
378 assert(traceback->frames[traceback->nframe].lineno >= 0);
379 traceback->nframe++;
380 if (traceback->nframe == tracemalloc_config.max_nframe)
381 break;
382 }
383}
384
385static traceback_t *
386traceback_new(void)
387{
Victor Stinnerf28ce602013-11-27 22:27:13 +0100388 traceback_t *traceback;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100389 _Py_hashtable_entry_t *entry;
390
391#ifdef WITH_THREAD
392 assert(PyGILState_Check());
393#endif
394
395 /* get frames */
Victor Stinnerf28ce602013-11-27 22:27:13 +0100396 traceback = tracemalloc_traceback;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100397 traceback->nframe = 0;
398 traceback_get_frames(traceback);
399 if (traceback->nframe == 0)
400 return &tracemalloc_empty_traceback;
401 traceback->hash = traceback_hash(traceback);
402
403 /* intern the traceback */
404 entry = _Py_hashtable_get_entry(tracemalloc_tracebacks, traceback);
405 if (entry != NULL) {
406 traceback = (traceback_t *)entry->key;
407 }
408 else {
409 traceback_t *copy;
410 size_t traceback_size;
411
412 traceback_size = TRACEBACK_SIZE(traceback->nframe);
413
414 copy = raw_malloc(traceback_size);
415 if (copy == NULL) {
416#ifdef TRACE_DEBUG
417 tracemalloc_error("failed to intern the traceback: malloc failed");
418#endif
419 return NULL;
420 }
421 memcpy(copy, traceback, traceback_size);
422
423 if (_Py_hashtable_set(tracemalloc_tracebacks, copy, NULL, 0) < 0) {
424 raw_free(copy);
425#ifdef TRACE_DEBUG
426 tracemalloc_error("failed to intern the traceback: putdata failed");
427#endif
428 return NULL;
429 }
430 traceback = copy;
431 }
432 return traceback;
433}
434
Victor Stinner52968672013-11-24 11:37:15 +0100435static int
Victor Stinner15116802013-12-04 01:29:35 +0100436tracemalloc_add_trace(void *ptr, size_t size)
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100437{
438 traceback_t *traceback;
439 trace_t trace;
Victor Stinner52968672013-11-24 11:37:15 +0100440 int res;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100441
442#ifdef WITH_THREAD
443 assert(PyGILState_Check());
444#endif
445
446 traceback = traceback_new();
Victor Stinner52968672013-11-24 11:37:15 +0100447 if (traceback == NULL)
448 return -1;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100449
450 trace.size = size;
451 trace.traceback = traceback;
452
Victor Stinner52968672013-11-24 11:37:15 +0100453 res = _Py_HASHTABLE_SET(tracemalloc_traces, ptr, trace);
454 if (res == 0) {
Victor Stinnerd606ba72013-11-24 11:28:20 +0100455 assert(tracemalloc_traced_memory <= PY_SIZE_MAX - size);
456 tracemalloc_traced_memory += size;
Victor Stinner3c0481d2013-11-27 21:39:49 +0100457 if (tracemalloc_traced_memory > tracemalloc_peak_traced_memory)
458 tracemalloc_peak_traced_memory = tracemalloc_traced_memory;
Victor Stinnerd606ba72013-11-24 11:28:20 +0100459 }
Victor Stinner52968672013-11-24 11:37:15 +0100460
461 return res;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100462}
463
464static void
Victor Stinner15116802013-12-04 01:29:35 +0100465tracemalloc_remove_trace(void *ptr)
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100466{
467 trace_t trace;
468
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100469 if (_Py_hashtable_pop(tracemalloc_traces, ptr, &trace, sizeof(trace))) {
470 assert(tracemalloc_traced_memory >= trace.size);
471 tracemalloc_traced_memory -= trace.size;
472 }
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100473}
474
475static void*
Victor Stinnerdb067af2014-05-02 22:31:14 +0200476tracemalloc_alloc(int use_calloc, void *ctx, size_t nelem, size_t elsize)
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100477{
Victor Stinnerd8f0d922014-06-02 21:57:10 +0200478 PyMemAllocatorEx *alloc = (PyMemAllocatorEx *)ctx;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100479 void *ptr;
480
Victor Stinneraa0e7af2014-06-02 21:40:22 +0200481 assert(elsize == 0 || nelem <= PY_SIZE_MAX / elsize);
Victor Stinnerdb067af2014-05-02 22:31:14 +0200482
483 if (use_calloc)
484 ptr = alloc->calloc(alloc->ctx, nelem, elsize);
485 else
486 ptr = alloc->malloc(alloc->ctx, nelem * elsize);
Victor Stinner15116802013-12-04 01:29:35 +0100487 if (ptr == NULL)
488 return NULL;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100489
Victor Stinner88c29872013-12-04 01:47:46 +0100490 TABLES_LOCK();
Victor Stinnerdb067af2014-05-02 22:31:14 +0200491 if (tracemalloc_add_trace(ptr, nelem * elsize) < 0) {
Victor Stinner15116802013-12-04 01:29:35 +0100492 /* Failed to allocate a trace for the new memory block */
Victor Stinner88c29872013-12-04 01:47:46 +0100493 TABLES_UNLOCK();
Victor Stinner15116802013-12-04 01:29:35 +0100494 alloc->free(alloc->ctx, ptr);
495 return NULL;
Victor Stinner52968672013-11-24 11:37:15 +0100496 }
Victor Stinner88c29872013-12-04 01:47:46 +0100497 TABLES_UNLOCK();
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100498 return ptr;
499}
500
501static void*
Victor Stinner15116802013-12-04 01:29:35 +0100502tracemalloc_realloc(void *ctx, void *ptr, size_t new_size)
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100503{
Victor Stinnerd8f0d922014-06-02 21:57:10 +0200504 PyMemAllocatorEx *alloc = (PyMemAllocatorEx *)ctx;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100505 void *ptr2;
506
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100507 ptr2 = alloc->realloc(alloc->ctx, ptr, new_size);
Victor Stinner15116802013-12-04 01:29:35 +0100508 if (ptr2 == NULL)
509 return NULL;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100510
Victor Stinner15116802013-12-04 01:29:35 +0100511 if (ptr != NULL) {
512 /* an existing memory block has been resized */
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100513
Victor Stinner88c29872013-12-04 01:47:46 +0100514 TABLES_LOCK();
Victor Stinner15116802013-12-04 01:29:35 +0100515 tracemalloc_remove_trace(ptr);
Victor Stinner08facd22013-11-24 12:27:59 +0100516
Victor Stinner15116802013-12-04 01:29:35 +0100517 if (tracemalloc_add_trace(ptr2, new_size) < 0) {
518 /* Memory allocation failed. The error cannot be reported to
519 the caller, because realloc() may already have shrinked the
520 memory block and so removed bytes.
521
Victor Stinner88c29872013-12-04 01:47:46 +0100522 This case is very unlikely: an hash entry has just been
523 released, so the hash table should have at least one free entry.
524
525 The GIL and the table lock ensures that only one thread is
526 allocating memory. */
527 assert(0 && "should never happen");
Victor Stinner52968672013-11-24 11:37:15 +0100528 }
Victor Stinner88c29872013-12-04 01:47:46 +0100529 TABLES_UNLOCK();
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100530 }
Victor Stinner15116802013-12-04 01:29:35 +0100531 else {
532 /* new allocation */
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100533
Victor Stinner88c29872013-12-04 01:47:46 +0100534 TABLES_LOCK();
Victor Stinner15116802013-12-04 01:29:35 +0100535 if (tracemalloc_add_trace(ptr2, new_size) < 0) {
536 /* Failed to allocate a trace for the new memory block */
Victor Stinner88c29872013-12-04 01:47:46 +0100537 TABLES_UNLOCK();
Victor Stinner15116802013-12-04 01:29:35 +0100538 alloc->free(alloc->ctx, ptr2);
539 return NULL;
540 }
Victor Stinner88c29872013-12-04 01:47:46 +0100541 TABLES_UNLOCK();
Victor Stinner15116802013-12-04 01:29:35 +0100542 }
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100543 return ptr2;
544}
545
546static void
547tracemalloc_free(void *ctx, void *ptr)
548{
Victor Stinnerd8f0d922014-06-02 21:57:10 +0200549 PyMemAllocatorEx *alloc = (PyMemAllocatorEx *)ctx;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100550
551 if (ptr == NULL)
552 return;
553
554 /* GIL cannot be locked in PyMem_RawFree() because it would introduce
555 a deadlock in PyThreadState_DeleteCurrent(). */
556
557 alloc->free(alloc->ctx, ptr);
Victor Stinner88c29872013-12-04 01:47:46 +0100558
559 TABLES_LOCK();
Victor Stinner15116802013-12-04 01:29:35 +0100560 tracemalloc_remove_trace(ptr);
Victor Stinner88c29872013-12-04 01:47:46 +0100561 TABLES_UNLOCK();
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100562}
563
564static void*
Victor Stinnerdb067af2014-05-02 22:31:14 +0200565tracemalloc_alloc_gil(int use_calloc, void *ctx, size_t nelem, size_t elsize)
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100566{
Victor Stinner15116802013-12-04 01:29:35 +0100567 void *ptr;
568
569 if (get_reentrant()) {
Victor Stinnerd8f0d922014-06-02 21:57:10 +0200570 PyMemAllocatorEx *alloc = (PyMemAllocatorEx *)ctx;
Victor Stinnerdb067af2014-05-02 22:31:14 +0200571 if (use_calloc)
572 return alloc->calloc(alloc->ctx, nelem, elsize);
573 else
574 return alloc->malloc(alloc->ctx, nelem * elsize);
Victor Stinner15116802013-12-04 01:29:35 +0100575 }
576
577 /* Ignore reentrant call. PyObjet_Malloc() calls PyMem_Malloc() for
578 allocations larger than 512 bytes, don't trace the same memory
579 allocation twice. */
580 set_reentrant(1);
581
Victor Stinnerdb067af2014-05-02 22:31:14 +0200582 ptr = tracemalloc_alloc(use_calloc, ctx, nelem, elsize);
Victor Stinner15116802013-12-04 01:29:35 +0100583
584 set_reentrant(0);
585 return ptr;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100586}
587
588static void*
Victor Stinnerdb067af2014-05-02 22:31:14 +0200589tracemalloc_malloc_gil(void *ctx, size_t size)
590{
591 return tracemalloc_alloc_gil(0, ctx, 1, size);
592}
593
594static void*
595tracemalloc_calloc_gil(void *ctx, size_t nelem, size_t elsize)
596{
597 return tracemalloc_alloc_gil(1, ctx, nelem, elsize);
598}
599
600static void*
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100601tracemalloc_realloc_gil(void *ctx, void *ptr, size_t new_size)
602{
Victor Stinner15116802013-12-04 01:29:35 +0100603 void *ptr2;
604
605 if (get_reentrant()) {
606 /* Reentrant call to PyMem_Realloc() and PyMem_RawRealloc().
607 Example: PyMem_RawRealloc() is called internally by pymalloc
608 (_PyObject_Malloc() and _PyObject_Realloc()) to allocate a new
609 arena (new_arena()). */
Victor Stinnerd8f0d922014-06-02 21:57:10 +0200610 PyMemAllocatorEx *alloc = (PyMemAllocatorEx *)ctx;
Victor Stinner15116802013-12-04 01:29:35 +0100611
612 ptr2 = alloc->realloc(alloc->ctx, ptr, new_size);
Victor Stinner88c29872013-12-04 01:47:46 +0100613 if (ptr2 != NULL && ptr != NULL) {
614 TABLES_LOCK();
Victor Stinner15116802013-12-04 01:29:35 +0100615 tracemalloc_remove_trace(ptr);
Victor Stinner88c29872013-12-04 01:47:46 +0100616 TABLES_UNLOCK();
617 }
Victor Stinner15116802013-12-04 01:29:35 +0100618 return ptr2;
619 }
620
621 /* Ignore reentrant call. PyObjet_Realloc() calls PyMem_Realloc() for
622 allocations larger than 512 bytes. Don't trace the same memory
623 allocation twice. */
624 set_reentrant(1);
625
626 ptr2 = tracemalloc_realloc(ctx, ptr, new_size);
627
628 set_reentrant(0);
629 return ptr2;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100630}
631
632#ifdef TRACE_RAW_MALLOC
633static void*
Victor Stinnerdb067af2014-05-02 22:31:14 +0200634tracemalloc_raw_alloc(int use_calloc, void *ctx, size_t nelem, size_t elsize)
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100635{
Victor Stinner15116802013-12-04 01:29:35 +0100636#ifdef WITH_THREAD
637 PyGILState_STATE gil_state;
638#endif
639 void *ptr;
640
641 if (get_reentrant()) {
Victor Stinnerd8f0d922014-06-02 21:57:10 +0200642 PyMemAllocatorEx *alloc = (PyMemAllocatorEx *)ctx;
Victor Stinnerdb067af2014-05-02 22:31:14 +0200643 if (use_calloc)
644 return alloc->calloc(alloc->ctx, nelem, elsize);
645 else
646 return alloc->malloc(alloc->ctx, nelem * elsize);
Victor Stinner15116802013-12-04 01:29:35 +0100647 }
648
649 /* Ignore reentrant call. PyGILState_Ensure() may call PyMem_RawMalloc()
650 indirectly which would call PyGILState_Ensure() if reentrant are not
651 disabled. */
652 set_reentrant(1);
653
654#ifdef WITH_THREAD
655 gil_state = PyGILState_Ensure();
Victor Stinnerdb067af2014-05-02 22:31:14 +0200656 ptr = tracemalloc_alloc(use_calloc, ctx, nelem, elsize);
Victor Stinner15116802013-12-04 01:29:35 +0100657 PyGILState_Release(gil_state);
658#else
Victor Stinnerdb067af2014-05-02 22:31:14 +0200659 ptr = tracemalloc_alloc(use_calloc, ctx, nelem, elsize);
Victor Stinner15116802013-12-04 01:29:35 +0100660#endif
661
662 set_reentrant(0);
663 return ptr;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100664}
665
666static void*
Victor Stinnerdb067af2014-05-02 22:31:14 +0200667tracemalloc_raw_malloc(void *ctx, size_t size)
668{
669 return tracemalloc_raw_alloc(0, ctx, 1, size);
670}
671
672static void*
673tracemalloc_raw_calloc(void *ctx, size_t nelem, size_t elsize)
674{
675 return tracemalloc_raw_alloc(1, ctx, nelem, elsize);
676}
677
678static void*
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100679tracemalloc_raw_realloc(void *ctx, void *ptr, size_t new_size)
680{
Victor Stinner15116802013-12-04 01:29:35 +0100681#ifdef WITH_THREAD
682 PyGILState_STATE gil_state;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100683#endif
Victor Stinner15116802013-12-04 01:29:35 +0100684 void *ptr2;
685
686 if (get_reentrant()) {
687 /* Reentrant call to PyMem_RawRealloc(). */
Victor Stinnerd8f0d922014-06-02 21:57:10 +0200688 PyMemAllocatorEx *alloc = (PyMemAllocatorEx *)ctx;
Victor Stinner15116802013-12-04 01:29:35 +0100689
690 ptr2 = alloc->realloc(alloc->ctx, ptr, new_size);
Victor Stinner15116802013-12-04 01:29:35 +0100691
Victor Stinner88c29872013-12-04 01:47:46 +0100692 if (ptr2 != NULL && ptr != NULL) {
693 TABLES_LOCK();
694 tracemalloc_remove_trace(ptr);
695 TABLES_UNLOCK();
696 }
Victor Stinner15116802013-12-04 01:29:35 +0100697 return ptr2;
698 }
699
700 /* Ignore reentrant call. PyGILState_Ensure() may call PyMem_RawMalloc()
701 indirectly which would call PyGILState_Ensure() if reentrant calls are
702 not disabled. */
703 set_reentrant(1);
704
705#ifdef WITH_THREAD
706 gil_state = PyGILState_Ensure();
707 ptr2 = tracemalloc_realloc(ctx, ptr, new_size);
708 PyGILState_Release(gil_state);
709#else
710 ptr2 = tracemalloc_realloc(ctx, ptr, new_size);
711#endif
712
713 set_reentrant(0);
714 return ptr2;
715}
716#endif /* TRACE_RAW_MALLOC */
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100717
718static int
719tracemalloc_clear_filename(_Py_hashtable_entry_t *entry, void *user_data)
720{
721 PyObject *filename = (PyObject *)entry->key;
722 Py_DECREF(filename);
723 return 0;
724}
725
726static int
727traceback_free_traceback(_Py_hashtable_entry_t *entry, void *user_data)
728{
729 traceback_t *traceback = (traceback_t *)entry->key;
730 raw_free(traceback);
731 return 0;
732}
733
734/* reentrant flag must be set to call this function and GIL must be held */
735static void
736tracemalloc_clear_traces(void)
737{
738#ifdef WITH_THREAD
739 /* The GIL protects variables againt concurrent access */
740 assert(PyGILState_Check());
741#endif
742
743 /* Disable also reentrant calls to tracemalloc_malloc() to not add a new
744 trace while we are clearing traces */
745 assert(get_reentrant());
746
747 TABLES_LOCK();
748 _Py_hashtable_clear(tracemalloc_traces);
749 tracemalloc_traced_memory = 0;
Victor Stinner3c0481d2013-11-27 21:39:49 +0100750 tracemalloc_peak_traced_memory = 0;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100751 TABLES_UNLOCK();
752
753 _Py_hashtable_foreach(tracemalloc_tracebacks, traceback_free_traceback, NULL);
754 _Py_hashtable_clear(tracemalloc_tracebacks);
755
756 _Py_hashtable_foreach(tracemalloc_filenames, tracemalloc_clear_filename, NULL);
757 _Py_hashtable_clear(tracemalloc_filenames);
758}
759
760static int
761tracemalloc_init(void)
762{
763 if (tracemalloc_config.initialized == TRACEMALLOC_FINALIZED) {
764 PyErr_SetString(PyExc_RuntimeError,
765 "the tracemalloc module has been unloaded");
766 return -1;
767 }
768
769 if (tracemalloc_config.initialized == TRACEMALLOC_INITIALIZED)
770 return 0;
771
772 PyMem_GetAllocator(PYMEM_DOMAIN_RAW, &allocators.raw);
773
774#ifdef REENTRANT_THREADLOCAL
775 tracemalloc_reentrant_key = PyThread_create_key();
776 if (tracemalloc_reentrant_key == -1) {
777#ifdef MS_WINDOWS
778 PyErr_SetFromWindowsErr(0);
779#else
780 PyErr_SetFromErrno(PyExc_OSError);
781#endif
782 return -1;
783 }
784#endif
785
786#if defined(WITH_THREAD) && defined(TRACE_RAW_MALLOC)
787 if (tables_lock == NULL) {
788 tables_lock = PyThread_allocate_lock();
789 if (tables_lock == NULL) {
790 PyErr_SetString(PyExc_RuntimeError, "cannot allocate lock");
791 return -1;
792 }
793 }
794#endif
795
796 tracemalloc_filenames = hashtable_new(0,
797 (_Py_hashtable_hash_func)PyObject_Hash,
798 hashtable_compare_unicode);
799
800 tracemalloc_tracebacks = hashtable_new(0,
801 (_Py_hashtable_hash_func)hashtable_hash_traceback,
802 (_Py_hashtable_compare_func)hashtable_compare_traceback);
803
804 tracemalloc_traces = hashtable_new(sizeof(trace_t),
805 _Py_hashtable_hash_ptr,
806 _Py_hashtable_compare_direct);
807
808 if (tracemalloc_filenames == NULL || tracemalloc_tracebacks == NULL
809 || tracemalloc_traces == NULL)
810 {
811 PyErr_NoMemory();
812 return -1;
813 }
814
815 unknown_filename = PyUnicode_FromString("<unknown>");
816 if (unknown_filename == NULL)
817 return -1;
818 PyUnicode_InternInPlace(&unknown_filename);
819
820 tracemalloc_empty_traceback.nframe = 1;
821 /* borrowed reference */
822 tracemalloc_empty_traceback.frames[0].filename = unknown_filename;
823 tracemalloc_empty_traceback.frames[0].lineno = 0;
824 tracemalloc_empty_traceback.hash = traceback_hash(&tracemalloc_empty_traceback);
825
826 /* Disable tracing allocations until hooks are installed. Set
827 also the reentrant flag to detect bugs: fail with an assertion error
828 if set_reentrant(1) is called while tracing is disabled. */
829 set_reentrant(1);
830
831 tracemalloc_config.initialized = TRACEMALLOC_INITIALIZED;
832 return 0;
833}
834
835static void
836tracemalloc_deinit(void)
837{
838 if (tracemalloc_config.initialized != TRACEMALLOC_INITIALIZED)
839 return;
840 tracemalloc_config.initialized = TRACEMALLOC_FINALIZED;
841
842 tracemalloc_stop();
843
844 /* destroy hash tables */
845 _Py_hashtable_destroy(tracemalloc_traces);
846 _Py_hashtable_destroy(tracemalloc_tracebacks);
847 _Py_hashtable_destroy(tracemalloc_filenames);
848
849#if defined(WITH_THREAD) && defined(TRACE_RAW_MALLOC)
850 if (tables_lock != NULL) {
851 PyThread_free_lock(tables_lock);
852 tables_lock = NULL;
853 }
854#endif
855
856#ifdef REENTRANT_THREADLOCAL
857 PyThread_delete_key(tracemalloc_reentrant_key);
858#endif
859
860 Py_XDECREF(unknown_filename);
861}
862
863static int
Victor Stinnerf28ce602013-11-27 22:27:13 +0100864tracemalloc_start(int max_nframe)
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100865{
Victor Stinnerd8f0d922014-06-02 21:57:10 +0200866 PyMemAllocatorEx alloc;
Victor Stinnerf28ce602013-11-27 22:27:13 +0100867 size_t size;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100868
869 if (tracemalloc_init() < 0)
870 return -1;
871
872 if (tracemalloc_config.tracing) {
873 /* hook already installed: do nothing */
874 return 0;
875 }
876
Victor Stinner52aee852014-08-16 15:44:02 +0200877 assert(1 <= max_nframe && max_nframe <= MAX_NFRAME);
Victor Stinnerf28ce602013-11-27 22:27:13 +0100878 tracemalloc_config.max_nframe = max_nframe;
879
880 /* allocate a buffer to store a new traceback */
881 size = TRACEBACK_SIZE(max_nframe);
882 assert(tracemalloc_traceback == NULL);
883 tracemalloc_traceback = raw_malloc(size);
884 if (tracemalloc_traceback == NULL) {
885 PyErr_NoMemory();
886 return -1;
887 }
888
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100889#ifdef TRACE_RAW_MALLOC
890 alloc.malloc = tracemalloc_raw_malloc;
Victor Stinnerdb067af2014-05-02 22:31:14 +0200891 alloc.calloc = tracemalloc_raw_calloc;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100892 alloc.realloc = tracemalloc_raw_realloc;
893 alloc.free = tracemalloc_free;
894
895 alloc.ctx = &allocators.raw;
896 PyMem_GetAllocator(PYMEM_DOMAIN_RAW, &allocators.raw);
897 PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &alloc);
898#endif
899
900 alloc.malloc = tracemalloc_malloc_gil;
Victor Stinnerdb067af2014-05-02 22:31:14 +0200901 alloc.calloc = tracemalloc_calloc_gil;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100902 alloc.realloc = tracemalloc_realloc_gil;
903 alloc.free = tracemalloc_free;
904
905 alloc.ctx = &allocators.mem;
906 PyMem_GetAllocator(PYMEM_DOMAIN_MEM, &allocators.mem);
907 PyMem_SetAllocator(PYMEM_DOMAIN_MEM, &alloc);
908
909 alloc.ctx = &allocators.obj;
910 PyMem_GetAllocator(PYMEM_DOMAIN_OBJ, &allocators.obj);
911 PyMem_SetAllocator(PYMEM_DOMAIN_OBJ, &alloc);
912
913 /* everything is ready: start tracing Python memory allocations */
914 tracemalloc_config.tracing = 1;
915 set_reentrant(0);
916
917 return 0;
918}
919
920static void
921tracemalloc_stop(void)
922{
923 if (!tracemalloc_config.tracing)
924 return;
925
926 /* stop tracing Python memory allocations */
927 tracemalloc_config.tracing = 0;
928
929 /* set the reentrant flag to detect bugs: fail with an assertion error if
930 set_reentrant(1) is called while tracing is disabled. */
931 set_reentrant(1);
932
933 /* unregister the hook on memory allocators */
934#ifdef TRACE_RAW_MALLOC
935 PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &allocators.raw);
936#endif
937 PyMem_SetAllocator(PYMEM_DOMAIN_MEM, &allocators.mem);
938 PyMem_SetAllocator(PYMEM_DOMAIN_OBJ, &allocators.obj);
939
940 /* release memory */
941 tracemalloc_clear_traces();
Victor Stinnerf28ce602013-11-27 22:27:13 +0100942 raw_free(tracemalloc_traceback);
943 tracemalloc_traceback = NULL;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100944}
945
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100946static PyObject*
947lineno_as_obj(int lineno)
948{
949 if (lineno >= 0)
950 return PyLong_FromLong(lineno);
951 else
952 Py_RETURN_NONE;
953}
954
955PyDoc_STRVAR(tracemalloc_is_tracing_doc,
956 "is_tracing()->bool\n"
957 "\n"
958 "True if the tracemalloc module is tracing Python memory allocations,\n"
959 "False otherwise.");
960
961static PyObject*
962py_tracemalloc_is_tracing(PyObject *self)
963{
964 return PyBool_FromLong(tracemalloc_config.tracing);
965}
966
967PyDoc_STRVAR(tracemalloc_clear_traces_doc,
968 "clear_traces()\n"
969 "\n"
970 "Clear traces of memory blocks allocated by Python.");
971
972static PyObject*
973py_tracemalloc_clear_traces(PyObject *self)
974{
975 if (!tracemalloc_config.tracing)
976 Py_RETURN_NONE;
977
978 set_reentrant(1);
979 tracemalloc_clear_traces();
980 set_reentrant(0);
981
982 Py_RETURN_NONE;
983}
984
985static PyObject*
986frame_to_pyobject(frame_t *frame)
987{
988 PyObject *frame_obj, *lineno_obj;
989
990 frame_obj = PyTuple_New(2);
991 if (frame_obj == NULL)
992 return NULL;
993
994 if (frame->filename == NULL)
995 frame->filename = Py_None;
996 Py_INCREF(frame->filename);
997 PyTuple_SET_ITEM(frame_obj, 0, frame->filename);
998
999 assert(frame->lineno >= 0);
1000 lineno_obj = lineno_as_obj(frame->lineno);
1001 if (lineno_obj == NULL) {
1002 Py_DECREF(frame_obj);
1003 return NULL;
1004 }
1005 PyTuple_SET_ITEM(frame_obj, 1, lineno_obj);
1006
1007 return frame_obj;
1008}
1009
1010static PyObject*
1011traceback_to_pyobject(traceback_t *traceback, _Py_hashtable_t *intern_table)
1012{
1013 int i;
1014 PyObject *frames, *frame;
1015
1016 if (intern_table != NULL) {
1017 if (_Py_HASHTABLE_GET(intern_table, traceback, frames)) {
1018 Py_INCREF(frames);
1019 return frames;
1020 }
1021 }
1022
1023 frames = PyTuple_New(traceback->nframe);
1024 if (frames == NULL)
1025 return NULL;
1026
1027 for (i=0; i < traceback->nframe; i++) {
1028 frame = frame_to_pyobject(&traceback->frames[i]);
1029 if (frame == NULL) {
1030 Py_DECREF(frames);
1031 return NULL;
1032 }
1033 PyTuple_SET_ITEM(frames, i, frame);
1034 }
1035
1036 if (intern_table != NULL) {
1037 if (_Py_HASHTABLE_SET(intern_table, traceback, frames) < 0) {
1038 Py_DECREF(frames);
1039 PyErr_NoMemory();
1040 return NULL;
1041 }
1042 /* intern_table keeps a new reference to frames */
1043 Py_INCREF(frames);
1044 }
1045 return frames;
1046}
1047
1048static PyObject*
1049trace_to_pyobject(trace_t *trace, _Py_hashtable_t *intern_tracebacks)
1050{
1051 PyObject *trace_obj = NULL;
1052 PyObject *size, *traceback;
1053
1054 trace_obj = PyTuple_New(2);
1055 if (trace_obj == NULL)
1056 return NULL;
1057
1058 size = PyLong_FromSize_t(trace->size);
1059 if (size == NULL) {
1060 Py_DECREF(trace_obj);
1061 return NULL;
1062 }
1063 PyTuple_SET_ITEM(trace_obj, 0, size);
1064
1065 traceback = traceback_to_pyobject(trace->traceback, intern_tracebacks);
1066 if (traceback == NULL) {
1067 Py_DECREF(trace_obj);
1068 return NULL;
1069 }
1070 PyTuple_SET_ITEM(trace_obj, 1, traceback);
1071
1072 return trace_obj;
1073}
1074
1075typedef struct {
1076 _Py_hashtable_t *traces;
1077 _Py_hashtable_t *tracebacks;
1078 PyObject *list;
1079} get_traces_t;
1080
1081static int
1082tracemalloc_get_traces_fill(_Py_hashtable_entry_t *entry, void *user_data)
1083{
1084 get_traces_t *get_traces = user_data;
1085 trace_t *trace;
1086 PyObject *tracemalloc_obj;
1087 int res;
1088
Victor Stinnerd9a73522014-03-24 22:34:34 +01001089 trace = (trace_t *)_Py_HASHTABLE_ENTRY_DATA(entry);
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001090
1091 tracemalloc_obj = trace_to_pyobject(trace, get_traces->tracebacks);
1092 if (tracemalloc_obj == NULL)
1093 return 1;
1094
1095 res = PyList_Append(get_traces->list, tracemalloc_obj);
1096 Py_DECREF(tracemalloc_obj);
1097 if (res < 0)
1098 return 1;
1099
1100 return 0;
1101}
1102
1103static int
1104tracemalloc_pyobject_decref_cb(_Py_hashtable_entry_t *entry, void *user_data)
1105{
1106 PyObject *obj = (PyObject *)_Py_HASHTABLE_ENTRY_DATA_AS_VOID_P(entry);
1107 Py_DECREF(obj);
1108 return 0;
1109}
1110
1111PyDoc_STRVAR(tracemalloc_get_traces_doc,
Victor Stinner4fbefdb2013-11-25 09:33:18 +01001112 "_get_traces() -> list\n"
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001113 "\n"
1114 "Get traces of all memory blocks allocated by Python.\n"
1115 "Return a list of (size: int, traceback: tuple) tuples.\n"
1116 "traceback is a tuple of (filename: str, lineno: int) tuples.\n"
1117 "\n"
1118 "Return an empty list if the tracemalloc module is disabled.");
1119
1120static PyObject*
1121py_tracemalloc_get_traces(PyObject *self, PyObject *obj)
1122{
1123 get_traces_t get_traces;
1124 int err;
1125
1126 get_traces.traces = NULL;
1127 get_traces.tracebacks = NULL;
1128 get_traces.list = PyList_New(0);
1129 if (get_traces.list == NULL)
1130 goto error;
1131
1132 if (!tracemalloc_config.tracing)
1133 return get_traces.list;
1134
Victor Stinnerde2f1322013-11-26 00:26:23 +01001135 /* the traceback hash table is used temporarily to intern traceback tuple
1136 of (filename, lineno) tuples */
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001137 get_traces.tracebacks = hashtable_new(sizeof(PyObject *),
1138 _Py_hashtable_hash_ptr,
1139 _Py_hashtable_compare_direct);
1140 if (get_traces.tracebacks == NULL) {
1141 PyErr_NoMemory();
1142 goto error;
1143 }
1144
1145 TABLES_LOCK();
1146 get_traces.traces = _Py_hashtable_copy(tracemalloc_traces);
1147 TABLES_UNLOCK();
1148
1149 if (get_traces.traces == NULL) {
1150 PyErr_NoMemory();
1151 goto error;
1152 }
1153
1154 set_reentrant(1);
1155 err = _Py_hashtable_foreach(get_traces.traces,
1156 tracemalloc_get_traces_fill, &get_traces);
1157 set_reentrant(0);
1158 if (err)
1159 goto error;
1160
1161 goto finally;
1162
1163error:
1164 Py_CLEAR(get_traces.list);
1165
1166finally:
1167 if (get_traces.tracebacks != NULL) {
1168 _Py_hashtable_foreach(get_traces.tracebacks,
1169 tracemalloc_pyobject_decref_cb, NULL);
1170 _Py_hashtable_destroy(get_traces.tracebacks);
1171 }
1172 if (get_traces.traces != NULL)
1173 _Py_hashtable_destroy(get_traces.traces);
1174
1175 return get_traces.list;
1176}
1177
1178PyDoc_STRVAR(tracemalloc_get_object_traceback_doc,
Victor Stinner4fbefdb2013-11-25 09:33:18 +01001179 "_get_object_traceback(obj)\n"
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001180 "\n"
1181 "Get the traceback where the Python object obj was allocated.\n"
1182 "Return a tuple of (filename: str, lineno: int) tuples.\n"
1183 "\n"
1184 "Return None if the tracemalloc module is disabled or did not\n"
1185 "trace the allocation of the object.");
1186
1187static PyObject*
1188py_tracemalloc_get_object_traceback(PyObject *self, PyObject *obj)
1189{
1190 PyTypeObject *type;
1191 void *ptr;
1192 trace_t trace;
1193 int found;
1194
1195 if (!tracemalloc_config.tracing)
1196 Py_RETURN_NONE;
1197
1198 type = Py_TYPE(obj);
1199 if (PyType_IS_GC(type))
1200 ptr = (void *)((char *)obj - sizeof(PyGC_Head));
1201 else
1202 ptr = (void *)obj;
1203
1204 TABLES_LOCK();
1205 found = _Py_HASHTABLE_GET(tracemalloc_traces, ptr, trace);
1206 TABLES_UNLOCK();
1207
1208 if (!found)
1209 Py_RETURN_NONE;
1210
1211 return traceback_to_pyobject(trace.traceback, NULL);
1212}
1213
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001214PyDoc_STRVAR(tracemalloc_start_doc,
Victor Stinner3728d6c2013-11-23 12:37:20 +01001215 "start(nframe: int=1)\n"
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001216 "\n"
Victor Stinner3728d6c2013-11-23 12:37:20 +01001217 "Start tracing Python memory allocations. Set also the maximum number \n"
1218 "of frames stored in the traceback of a trace to nframe.");
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001219
1220static PyObject*
Victor Stinner3728d6c2013-11-23 12:37:20 +01001221py_tracemalloc_start(PyObject *self, PyObject *args)
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001222{
Victor Stinner3728d6c2013-11-23 12:37:20 +01001223 Py_ssize_t nframe = 1;
Victor Stinnerf28ce602013-11-27 22:27:13 +01001224 int nframe_int;
Victor Stinner3728d6c2013-11-23 12:37:20 +01001225
1226 if (!PyArg_ParseTuple(args, "|n:start", &nframe))
1227 return NULL;
1228
Victor Stinner52aee852014-08-16 15:44:02 +02001229 if (nframe < 1 || nframe > MAX_NFRAME) {
Victor Stinner3728d6c2013-11-23 12:37:20 +01001230 PyErr_Format(PyExc_ValueError,
1231 "the number of frames must be in range [1; %i]",
Victor Stinner52aee852014-08-16 15:44:02 +02001232 MAX_NFRAME);
Victor Stinner3728d6c2013-11-23 12:37:20 +01001233 return NULL;
1234 }
Victor Stinnerf28ce602013-11-27 22:27:13 +01001235 nframe_int = Py_SAFE_DOWNCAST(nframe, Py_ssize_t, int);
Victor Stinner3728d6c2013-11-23 12:37:20 +01001236
Victor Stinnerf28ce602013-11-27 22:27:13 +01001237 if (tracemalloc_start(nframe_int) < 0)
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001238 return NULL;
1239
1240 Py_RETURN_NONE;
1241}
1242
1243PyDoc_STRVAR(tracemalloc_stop_doc,
1244 "stop()\n"
1245 "\n"
1246 "Stop tracing Python memory allocations and clear traces\n"
1247 "of memory blocks allocated by Python.");
1248
1249static PyObject*
1250py_tracemalloc_stop(PyObject *self)
1251{
1252 tracemalloc_stop();
1253 Py_RETURN_NONE;
1254}
1255
1256PyDoc_STRVAR(tracemalloc_get_traceback_limit_doc,
1257 "get_traceback_limit() -> int\n"
1258 "\n"
1259 "Get the maximum number of frames stored in the traceback\n"
1260 "of a trace.\n"
1261 "\n"
1262 "By default, a trace of an allocated memory block only stores\n"
1263 "the most recent frame: the limit is 1.");
1264
1265static PyObject*
1266py_tracemalloc_get_traceback_limit(PyObject *self)
1267{
1268 return PyLong_FromLong(tracemalloc_config.max_nframe);
1269}
1270
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001271PyDoc_STRVAR(tracemalloc_get_tracemalloc_memory_doc,
1272 "get_tracemalloc_memory() -> int\n"
1273 "\n"
1274 "Get the memory usage in bytes of the tracemalloc module\n"
1275 "used internally to trace memory allocations.");
1276
1277static PyObject*
1278tracemalloc_get_tracemalloc_memory(PyObject *self)
1279{
1280 size_t size;
1281 PyObject *size_obj;
1282
1283 size = _Py_hashtable_size(tracemalloc_tracebacks);
1284 size += _Py_hashtable_size(tracemalloc_filenames);
1285
1286 TABLES_LOCK();
1287 size += _Py_hashtable_size(tracemalloc_traces);
1288 TABLES_UNLOCK();
1289
1290 size_obj = PyLong_FromSize_t(size);
1291 return Py_BuildValue("N", size_obj);
1292}
1293
1294PyDoc_STRVAR(tracemalloc_get_traced_memory_doc,
Victor Stinner59463d82013-11-26 10:46:06 +01001295 "get_traced_memory() -> (int, int)\n"
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001296 "\n"
Victor Stinner3c0481d2013-11-27 21:39:49 +01001297 "Get the current size and peak size of memory blocks traced\n"
1298 "by the tracemalloc module as a tuple: (current: int, peak: int).");
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001299
1300static PyObject*
1301tracemalloc_get_traced_memory(PyObject *self)
1302{
Victor Stinner3c0481d2013-11-27 21:39:49 +01001303 Py_ssize_t size, peak_size;
1304 PyObject *size_obj, *peak_size_obj;
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001305
1306 if (!tracemalloc_config.tracing)
1307 return Py_BuildValue("ii", 0, 0);
1308
1309 TABLES_LOCK();
1310 size = tracemalloc_traced_memory;
Victor Stinner3c0481d2013-11-27 21:39:49 +01001311 peak_size = tracemalloc_peak_traced_memory;
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001312 TABLES_UNLOCK();
1313
1314 size_obj = PyLong_FromSize_t(size);
Victor Stinner3c0481d2013-11-27 21:39:49 +01001315 peak_size_obj = PyLong_FromSize_t(peak_size);
1316 return Py_BuildValue("NN", size_obj, peak_size_obj);
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001317}
1318
1319static PyMethodDef module_methods[] = {
1320 {"is_tracing", (PyCFunction)py_tracemalloc_is_tracing,
1321 METH_NOARGS, tracemalloc_is_tracing_doc},
1322 {"clear_traces", (PyCFunction)py_tracemalloc_clear_traces,
1323 METH_NOARGS, tracemalloc_clear_traces_doc},
1324 {"_get_traces", (PyCFunction)py_tracemalloc_get_traces,
1325 METH_NOARGS, tracemalloc_get_traces_doc},
1326 {"_get_object_traceback", (PyCFunction)py_tracemalloc_get_object_traceback,
1327 METH_O, tracemalloc_get_object_traceback_doc},
1328 {"start", (PyCFunction)py_tracemalloc_start,
Victor Stinner3728d6c2013-11-23 12:37:20 +01001329 METH_VARARGS, tracemalloc_start_doc},
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001330 {"stop", (PyCFunction)py_tracemalloc_stop,
1331 METH_NOARGS, tracemalloc_stop_doc},
1332 {"get_traceback_limit", (PyCFunction)py_tracemalloc_get_traceback_limit,
1333 METH_NOARGS, tracemalloc_get_traceback_limit_doc},
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001334 {"get_tracemalloc_memory", (PyCFunction)tracemalloc_get_tracemalloc_memory,
1335 METH_NOARGS, tracemalloc_get_tracemalloc_memory_doc},
1336 {"get_traced_memory", (PyCFunction)tracemalloc_get_traced_memory,
1337 METH_NOARGS, tracemalloc_get_traced_memory_doc},
1338
1339 /* sentinel */
1340 {NULL, NULL}
1341};
1342
1343PyDoc_STRVAR(module_doc,
1344"Debug module to trace memory blocks allocated by Python.");
1345
1346static struct PyModuleDef module_def = {
1347 PyModuleDef_HEAD_INIT,
1348 "_tracemalloc",
1349 module_doc,
1350 0, /* non-negative size to be able to unload the module */
1351 module_methods,
1352 NULL,
1353};
1354
1355PyMODINIT_FUNC
1356PyInit__tracemalloc(void)
1357{
1358 PyObject *m;
1359 m = PyModule_Create(&module_def);
1360 if (m == NULL)
1361 return NULL;
1362
1363 if (tracemalloc_init() < 0)
1364 return NULL;
1365
1366 return m;
1367}
1368
1369static int
1370parse_sys_xoptions(PyObject *value)
1371{
1372 PyObject *valuelong;
1373 long nframe;
1374
1375 if (value == Py_True)
1376 return 1;
1377
1378 assert(PyUnicode_Check(value));
1379 if (PyUnicode_GetLength(value) == 0)
1380 return -1;
1381
1382 valuelong = PyLong_FromUnicodeObject(value, 10);
1383 if (valuelong == NULL)
1384 return -1;
1385
1386 nframe = PyLong_AsLong(valuelong);
1387 Py_DECREF(valuelong);
1388 if (nframe == -1 && PyErr_Occurred())
1389 return -1;
1390
Victor Stinner52aee852014-08-16 15:44:02 +02001391 if (nframe < 1 || nframe > MAX_NFRAME)
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001392 return -1;
1393
1394 return Py_SAFE_DOWNCAST(nframe, long, int);
1395}
1396
1397int
1398_PyTraceMalloc_Init(void)
1399{
1400 char *p;
1401 int nframe;
1402
1403#ifdef WITH_THREAD
1404 assert(PyGILState_Check());
1405#endif
1406
1407 if ((p = Py_GETENV("PYTHONTRACEMALLOC")) && *p != '\0') {
1408 char *endptr = p;
Victor Stinnerf28ce602013-11-27 22:27:13 +01001409 long value;
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001410
Victor Stinner711e27c2013-12-16 23:06:19 +01001411 errno = 0;
Victor Stinnerf28ce602013-11-27 22:27:13 +01001412 value = strtol(p, &endptr, 10);
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001413 if (*endptr != '\0'
1414 || value < 1
Victor Stinner52aee852014-08-16 15:44:02 +02001415 || value > MAX_NFRAME
Victor Stinner711e27c2013-12-16 23:06:19 +01001416 || errno == ERANGE)
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001417 {
Victor Stinnerf28ce602013-11-27 22:27:13 +01001418 Py_FatalError("PYTHONTRACEMALLOC: invalid number of frames");
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001419 return -1;
1420 }
1421
1422 nframe = (int)value;
1423 }
1424 else {
1425 PyObject *xoptions, *key, *value;
1426
1427 xoptions = PySys_GetXOptions();
1428 if (xoptions == NULL)
1429 return -1;
1430
1431 key = PyUnicode_FromString("tracemalloc");
1432 if (key == NULL)
1433 return -1;
1434
1435 value = PyDict_GetItemWithError(xoptions, key);
1436 Py_DECREF(key);
1437 if (value == NULL) {
1438 if (PyErr_Occurred())
1439 return -1;
1440
1441 /* -X tracemalloc is not used */
1442 return 0;
1443 }
1444
1445 nframe = parse_sys_xoptions(value);
1446 Py_DECREF(value);
1447 if (nframe < 0) {
Victor Stinnerf28ce602013-11-27 22:27:13 +01001448 Py_FatalError("-X tracemalloc=NFRAME: invalid number of frames");
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001449 }
1450 }
1451
Victor Stinnerf28ce602013-11-27 22:27:13 +01001452 return tracemalloc_start(nframe);
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001453}
1454
Victor Stinnerbe0708f2013-12-01 10:03:26 +01001455void
1456_PyTraceMalloc_Fini(void)
1457{
1458#ifdef WITH_THREAD
1459 assert(PyGILState_Check());
1460#endif
1461 tracemalloc_deinit();
1462}
1463