blob: b39e950c2733525a047ba31a396e0f156aa1af48 [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
19#define _STR(VAL) #VAL
20#define STR(VAL) _STR(VAL)
21
22/* Protected by the GIL */
23static struct {
24 PyMemAllocator mem;
25 PyMemAllocator raw;
26 PyMemAllocator obj;
27} allocators;
28
Victor Stinnered3b0bc2013-11-23 12:27:24 +010029static struct {
30 /* Module initialized?
31 Variable protected by the GIL */
32 enum {
33 TRACEMALLOC_NOT_INITIALIZED,
34 TRACEMALLOC_INITIALIZED,
35 TRACEMALLOC_FINALIZED
36 } initialized;
37
Victor Stinnered3b0bc2013-11-23 12:27:24 +010038 /* Is tracemalloc tracing memory allocations?
39 Variable protected by the GIL */
40 int tracing;
41
42 /* limit of the number of frames in a traceback, 1 by default.
43 Variable protected by the GIL. */
44 int max_nframe;
Victor Stinnerbe0708f2013-12-01 10:03:26 +010045} tracemalloc_config = {TRACEMALLOC_NOT_INITIALIZED, 0, 1};
Victor Stinnered3b0bc2013-11-23 12:27:24 +010046
47#if defined(TRACE_RAW_MALLOC) && defined(WITH_THREAD)
48/* This lock is needed because tracemalloc_free() is called without
49 the GIL held from PyMem_RawFree(). It cannot acquire the lock because it
50 would introduce a deadlock in PyThreadState_DeleteCurrent(). */
51static PyThread_type_lock tables_lock;
52# define TABLES_LOCK() PyThread_acquire_lock(tables_lock, 1)
53# define TABLES_UNLOCK() PyThread_release_lock(tables_lock)
54#else
55 /* variables are protected by the GIL */
56# define TABLES_LOCK()
57# define TABLES_UNLOCK()
58#endif
59
60/* Pack the frame_t structure to reduce the memory footprint on 64-bit
61 architectures: 12 bytes instead of 16. This optimization might produce
62 SIGBUS on architectures not supporting unaligned memory accesses (64-bit
63 IPS CPU?): on such architecture, the structure must not be packed. */
64#pragma pack(4)
65typedef struct
66#ifdef __GNUC__
67__attribute__((packed))
68#endif
69{
70 PyObject *filename;
71 int lineno;
72} frame_t;
73
74typedef struct {
75 Py_uhash_t hash;
76 int nframe;
77 frame_t frames[1];
78} traceback_t;
79
80#define TRACEBACK_SIZE(NFRAME) \
81 (sizeof(traceback_t) + sizeof(frame_t) * (NFRAME - 1))
Victor Stinnerf28ce602013-11-27 22:27:13 +010082
83#define MAX_NFRAME \
84 ((INT_MAX - sizeof(traceback_t)) / sizeof(frame_t) + 1)
Victor Stinnered3b0bc2013-11-23 12:27:24 +010085
86static PyObject *unknown_filename = NULL;
87static traceback_t tracemalloc_empty_traceback;
88
Victor Stinner7a5be142013-11-26 01:06:02 +010089/* Trace of a memory block */
Victor Stinnered3b0bc2013-11-23 12:27:24 +010090typedef struct {
Victor Stinner7a5be142013-11-26 01:06:02 +010091 /* Size of the memory block in bytes */
Victor Stinnered3b0bc2013-11-23 12:27:24 +010092 size_t size;
Victor Stinner7a5be142013-11-26 01:06:02 +010093
94 /* Traceback where the memory block was allocated */
Victor Stinnered3b0bc2013-11-23 12:27:24 +010095 traceback_t *traceback;
96} trace_t;
97
98/* Size in bytes of currently traced memory.
99 Protected by TABLES_LOCK(). */
100static size_t tracemalloc_traced_memory = 0;
101
Victor Stinner3c0481d2013-11-27 21:39:49 +0100102/* Peak size in bytes of traced memory.
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100103 Protected by TABLES_LOCK(). */
Victor Stinner3c0481d2013-11-27 21:39:49 +0100104static size_t tracemalloc_peak_traced_memory = 0;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100105
106/* Hash table used as a set to to intern filenames:
107 PyObject* => PyObject*.
108 Protected by the GIL */
109static _Py_hashtable_t *tracemalloc_filenames = NULL;
110
Victor Stinnerf28ce602013-11-27 22:27:13 +0100111/* Buffer to store a new traceback in traceback_new().
112 Protected by the GIL. */
113static traceback_t *tracemalloc_traceback = NULL;
114
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100115/* Hash table used as a set to intern tracebacks:
116 traceback_t* => traceback_t*
117 Protected by the GIL */
118static _Py_hashtable_t *tracemalloc_tracebacks = NULL;
119
120/* pointer (void*) => trace (trace_t).
121 Protected by TABLES_LOCK(). */
122static _Py_hashtable_t *tracemalloc_traces = NULL;
123
124#ifdef TRACE_DEBUG
125static void
126tracemalloc_error(const char *format, ...)
127{
128 va_list ap;
129 fprintf(stderr, "tracemalloc: ");
130 va_start(ap, format);
131 vfprintf(stderr, format, ap);
132 va_end(ap);
133 fprintf(stderr, "\n");
134 fflush(stderr);
135}
136#endif
137
138#if defined(WITH_THREAD) && defined(TRACE_RAW_MALLOC)
139#define REENTRANT_THREADLOCAL
140
141/* If your OS does not provide native thread local storage, you can implement
142 it manually using a lock. Functions of thread.c cannot be used because
143 they use PyMem_RawMalloc() which leads to a reentrant call. */
144#if !(defined(_POSIX_THREADS) || defined(NT_THREADS))
145# error "need native thread local storage (TLS)"
146#endif
147
148static int tracemalloc_reentrant_key;
149
150/* Any non-NULL pointer can be used */
151#define REENTRANT Py_True
152
153static int
154get_reentrant(void)
155{
156 void *ptr = PyThread_get_key_value(tracemalloc_reentrant_key);
157 if (ptr != NULL) {
158 assert(ptr == REENTRANT);
159 return 1;
160 }
161 else
162 return 0;
163}
164
165static void
166set_reentrant(int reentrant)
167{
Victor Stinner2ead3d22013-11-26 01:08:53 +0100168 assert(reentrant == 0 || reentrant == 1);
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100169 if (reentrant) {
170 assert(PyThread_get_key_value(tracemalloc_reentrant_key) == NULL);
171 PyThread_set_key_value(tracemalloc_reentrant_key,
172 REENTRANT);
173 }
174 else {
175 /* FIXME: PyThread_set_key_value() cannot be used to set the flag
176 to zero, because it does nothing if the variable has already
177 a value set. */
178 PyThread_delete_key_value(tracemalloc_reentrant_key);
179 }
180}
181
182#else
183
184/* WITH_THREAD not defined: Python compiled without threads,
185 or TRACE_RAW_MALLOC not defined: variable protected by the GIL */
186static int tracemalloc_reentrant = 0;
187
188static int
189get_reentrant(void)
190{
191 return tracemalloc_reentrant;
192}
193
194static void
195set_reentrant(int reentrant)
196{
197 assert(!reentrant || !get_reentrant());
198 tracemalloc_reentrant = reentrant;
199}
200#endif
201
202static int
203hashtable_compare_unicode(const void *key, const _Py_hashtable_entry_t *entry)
204{
205 if (key != NULL && entry->key != NULL)
206 return (PyUnicode_Compare((PyObject *)key, (PyObject *)entry->key) == 0);
207 else
208 return key == entry->key;
209}
210
211static _Py_hashtable_allocator_t hashtable_alloc = {malloc, free};
212
213static _Py_hashtable_t *
214hashtable_new(size_t data_size,
215 _Py_hashtable_hash_func hash_func,
216 _Py_hashtable_compare_func compare_func)
217{
218 return _Py_hashtable_new_full(data_size, 0,
219 hash_func, compare_func,
220 NULL, NULL, NULL, &hashtable_alloc);
221}
222
223static void*
224raw_malloc(size_t size)
225{
226 return allocators.raw.malloc(allocators.raw.ctx, size);
227}
228
229static void
230raw_free(void *ptr)
231{
232 allocators.raw.free(allocators.raw.ctx, ptr);
233}
234
235static Py_uhash_t
236hashtable_hash_traceback(const void *key)
237{
238 const traceback_t *traceback = key;
239 return traceback->hash;
240}
241
242static int
243hashtable_compare_traceback(const traceback_t *traceback1,
244 const _Py_hashtable_entry_t *he)
245{
246 const traceback_t *traceback2 = he->key;
247 const frame_t *frame1, *frame2;
248 int i;
249
250 if (traceback1->nframe != traceback2->nframe)
251 return 0;
252
253 for (i=0; i < traceback1->nframe; i++) {
254 frame1 = &traceback1->frames[i];
255 frame2 = &traceback2->frames[i];
256
257 if (frame1->lineno != frame2->lineno)
258 return 0;
259
260 if (frame1->filename != frame2->filename) {
261 assert(PyUnicode_Compare(frame1->filename, frame2->filename) != 0);
262 return 0;
263 }
264 }
265 return 1;
266}
267
268static void
269tracemalloc_get_frame(PyFrameObject *pyframe, frame_t *frame)
270{
271 PyCodeObject *code;
272 PyObject *filename;
273 _Py_hashtable_entry_t *entry;
274
275 frame->filename = unknown_filename;
276 frame->lineno = PyFrame_GetLineNumber(pyframe);
277 assert(frame->lineno >= 0);
278 if (frame->lineno < 0)
279 frame->lineno = 0;
280
281 code = pyframe->f_code;
282 if (code == NULL) {
283#ifdef TRACE_DEBUG
Victor Stinner4dc74202013-11-26 01:18:52 +0100284 tracemalloc_error("failed to get the code object of the frame");
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100285#endif
286 return;
287 }
288
289 if (code->co_filename == NULL) {
290#ifdef TRACE_DEBUG
291 tracemalloc_error("failed to get the filename of the code object");
292#endif
293 return;
294 }
295
296 filename = code->co_filename;
297 assert(filename != NULL);
298 if (filename == NULL)
299 return;
300
301 if (!PyUnicode_Check(filename)) {
302#ifdef TRACE_DEBUG
303 tracemalloc_error("filename is not an unicode string");
304#endif
305 return;
306 }
307 if (!PyUnicode_IS_READY(filename)) {
308 /* Don't make a Unicode string ready to avoid reentrant calls
309 to tracemalloc_malloc() or tracemalloc_realloc() */
310#ifdef TRACE_DEBUG
311 tracemalloc_error("filename is not a ready unicode string");
312#endif
313 return;
314 }
315
316 /* intern the filename */
317 entry = _Py_hashtable_get_entry(tracemalloc_filenames, filename);
318 if (entry != NULL) {
319 filename = (PyObject *)entry->key;
320 }
321 else {
322 /* tracemalloc_filenames is responsible to keep a reference
323 to the filename */
324 Py_INCREF(filename);
325 if (_Py_hashtable_set(tracemalloc_filenames, filename, NULL, 0) < 0) {
326 Py_DECREF(filename);
327#ifdef TRACE_DEBUG
328 tracemalloc_error("failed to intern the filename");
329#endif
330 return;
331 }
332 }
333
334 /* the tracemalloc_filenames table keeps a reference to the filename */
335 frame->filename = filename;
336}
337
338static Py_uhash_t
339traceback_hash(traceback_t *traceback)
340{
341 /* code based on tuplehash() of Objects/tupleobject.c */
342 Py_uhash_t x; /* Unsigned for defined overflow behavior. */
343 Py_hash_t y;
344 int len = traceback->nframe;
345 Py_uhash_t mult = _PyHASH_MULTIPLIER;
346 frame_t *frame;
347
348 x = 0x345678UL;
349 frame = traceback->frames;
350 while (--len >= 0) {
351 y = PyObject_Hash(frame->filename);
352 y ^= frame->lineno;
353 frame++;
354
355 x = (x ^ y) * mult;
356 /* the cast might truncate len; that doesn't change hash stability */
357 mult += (Py_hash_t)(82520UL + len + len);
358 }
359 x += 97531UL;
360 return x;
361}
362
363static void
364traceback_get_frames(traceback_t *traceback)
365{
366 PyThreadState *tstate;
367 PyFrameObject *pyframe;
368
369#ifdef WITH_THREAD
370 tstate = PyGILState_GetThisThreadState();
371#else
372 tstate = PyThreadState_Get();
373#endif
374 if (tstate == NULL) {
375#ifdef TRACE_DEBUG
376 tracemalloc_error("failed to get the current thread state");
377#endif
378 return;
379 }
380
381 for (pyframe = tstate->frame; pyframe != NULL; pyframe = pyframe->f_back) {
382 tracemalloc_get_frame(pyframe, &traceback->frames[traceback->nframe]);
383 assert(traceback->frames[traceback->nframe].filename != NULL);
384 assert(traceback->frames[traceback->nframe].lineno >= 0);
385 traceback->nframe++;
386 if (traceback->nframe == tracemalloc_config.max_nframe)
387 break;
388 }
389}
390
391static traceback_t *
392traceback_new(void)
393{
Victor Stinnerf28ce602013-11-27 22:27:13 +0100394 traceback_t *traceback;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100395 _Py_hashtable_entry_t *entry;
396
397#ifdef WITH_THREAD
398 assert(PyGILState_Check());
399#endif
400
401 /* get frames */
Victor Stinnerf28ce602013-11-27 22:27:13 +0100402 traceback = tracemalloc_traceback;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100403 traceback->nframe = 0;
404 traceback_get_frames(traceback);
405 if (traceback->nframe == 0)
406 return &tracemalloc_empty_traceback;
407 traceback->hash = traceback_hash(traceback);
408
409 /* intern the traceback */
410 entry = _Py_hashtable_get_entry(tracemalloc_tracebacks, traceback);
411 if (entry != NULL) {
412 traceback = (traceback_t *)entry->key;
413 }
414 else {
415 traceback_t *copy;
416 size_t traceback_size;
417
418 traceback_size = TRACEBACK_SIZE(traceback->nframe);
419
420 copy = raw_malloc(traceback_size);
421 if (copy == NULL) {
422#ifdef TRACE_DEBUG
423 tracemalloc_error("failed to intern the traceback: malloc failed");
424#endif
425 return NULL;
426 }
427 memcpy(copy, traceback, traceback_size);
428
429 if (_Py_hashtable_set(tracemalloc_tracebacks, copy, NULL, 0) < 0) {
430 raw_free(copy);
431#ifdef TRACE_DEBUG
432 tracemalloc_error("failed to intern the traceback: putdata failed");
433#endif
434 return NULL;
435 }
436 traceback = copy;
437 }
438 return traceback;
439}
440
Victor Stinner52968672013-11-24 11:37:15 +0100441static int
Victor Stinner15116802013-12-04 01:29:35 +0100442tracemalloc_add_trace(void *ptr, size_t size)
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100443{
444 traceback_t *traceback;
445 trace_t trace;
Victor Stinner52968672013-11-24 11:37:15 +0100446 int res;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100447
448#ifdef WITH_THREAD
449 assert(PyGILState_Check());
450#endif
451
452 traceback = traceback_new();
Victor Stinner52968672013-11-24 11:37:15 +0100453 if (traceback == NULL)
454 return -1;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100455
456 trace.size = size;
457 trace.traceback = traceback;
458
Victor Stinner52968672013-11-24 11:37:15 +0100459 res = _Py_HASHTABLE_SET(tracemalloc_traces, ptr, trace);
460 if (res == 0) {
Victor Stinnerd606ba72013-11-24 11:28:20 +0100461 assert(tracemalloc_traced_memory <= PY_SIZE_MAX - size);
462 tracemalloc_traced_memory += size;
Victor Stinner3c0481d2013-11-27 21:39:49 +0100463 if (tracemalloc_traced_memory > tracemalloc_peak_traced_memory)
464 tracemalloc_peak_traced_memory = tracemalloc_traced_memory;
Victor Stinnerd606ba72013-11-24 11:28:20 +0100465 }
Victor Stinner52968672013-11-24 11:37:15 +0100466
467 return res;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100468}
469
470static void
Victor Stinner15116802013-12-04 01:29:35 +0100471tracemalloc_remove_trace(void *ptr)
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100472{
473 trace_t trace;
474
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100475 if (_Py_hashtable_pop(tracemalloc_traces, ptr, &trace, sizeof(trace))) {
476 assert(tracemalloc_traced_memory >= trace.size);
477 tracemalloc_traced_memory -= trace.size;
478 }
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100479}
480
481static void*
Victor Stinner15116802013-12-04 01:29:35 +0100482tracemalloc_malloc(void *ctx, size_t size)
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100483{
484 PyMemAllocator *alloc = (PyMemAllocator *)ctx;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100485 void *ptr;
486
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100487 ptr = alloc->malloc(alloc->ctx, size);
Victor Stinner15116802013-12-04 01:29:35 +0100488 if (ptr == NULL)
489 return NULL;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100490
Victor Stinner88c29872013-12-04 01:47:46 +0100491 TABLES_LOCK();
Victor Stinner15116802013-12-04 01:29:35 +0100492 if (tracemalloc_add_trace(ptr, size) < 0) {
493 /* Failed to allocate a trace for the new memory block */
Victor Stinner88c29872013-12-04 01:47:46 +0100494 TABLES_UNLOCK();
Victor Stinner15116802013-12-04 01:29:35 +0100495 alloc->free(alloc->ctx, ptr);
496 return NULL;
Victor Stinner52968672013-11-24 11:37:15 +0100497 }
Victor Stinner88c29872013-12-04 01:47:46 +0100498 TABLES_UNLOCK();
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100499 return ptr;
500}
501
502static void*
Victor Stinner15116802013-12-04 01:29:35 +0100503tracemalloc_realloc(void *ctx, void *ptr, size_t new_size)
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100504{
505 PyMemAllocator *alloc = (PyMemAllocator *)ctx;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100506 void *ptr2;
507
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100508 ptr2 = alloc->realloc(alloc->ctx, ptr, new_size);
Victor Stinner15116802013-12-04 01:29:35 +0100509 if (ptr2 == NULL)
510 return NULL;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100511
Victor Stinner15116802013-12-04 01:29:35 +0100512 if (ptr != NULL) {
513 /* an existing memory block has been resized */
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100514
Victor Stinner88c29872013-12-04 01:47:46 +0100515 TABLES_LOCK();
Victor Stinner15116802013-12-04 01:29:35 +0100516 tracemalloc_remove_trace(ptr);
Victor Stinner08facd22013-11-24 12:27:59 +0100517
Victor Stinner15116802013-12-04 01:29:35 +0100518 if (tracemalloc_add_trace(ptr2, new_size) < 0) {
519 /* Memory allocation failed. The error cannot be reported to
520 the caller, because realloc() may already have shrinked the
521 memory block and so removed bytes.
522
Victor Stinner88c29872013-12-04 01:47:46 +0100523 This case is very unlikely: an hash entry has just been
524 released, so the hash table should have at least one free entry.
525
526 The GIL and the table lock ensures that only one thread is
527 allocating memory. */
528 assert(0 && "should never happen");
Victor Stinner52968672013-11-24 11:37:15 +0100529 }
Victor Stinner88c29872013-12-04 01:47:46 +0100530 TABLES_UNLOCK();
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100531 }
Victor Stinner15116802013-12-04 01:29:35 +0100532 else {
533 /* new allocation */
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100534
Victor Stinner88c29872013-12-04 01:47:46 +0100535 TABLES_LOCK();
Victor Stinner15116802013-12-04 01:29:35 +0100536 if (tracemalloc_add_trace(ptr2, new_size) < 0) {
537 /* Failed to allocate a trace for the new memory block */
Victor Stinner88c29872013-12-04 01:47:46 +0100538 TABLES_UNLOCK();
Victor Stinner15116802013-12-04 01:29:35 +0100539 alloc->free(alloc->ctx, ptr2);
540 return NULL;
541 }
Victor Stinner88c29872013-12-04 01:47:46 +0100542 TABLES_UNLOCK();
Victor Stinner15116802013-12-04 01:29:35 +0100543 }
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100544 return ptr2;
545}
546
547static void
548tracemalloc_free(void *ctx, void *ptr)
549{
550 PyMemAllocator *alloc = (PyMemAllocator *)ctx;
551
552 if (ptr == NULL)
553 return;
554
555 /* GIL cannot be locked in PyMem_RawFree() because it would introduce
556 a deadlock in PyThreadState_DeleteCurrent(). */
557
558 alloc->free(alloc->ctx, ptr);
Victor Stinner88c29872013-12-04 01:47:46 +0100559
560 TABLES_LOCK();
Victor Stinner15116802013-12-04 01:29:35 +0100561 tracemalloc_remove_trace(ptr);
Victor Stinner88c29872013-12-04 01:47:46 +0100562 TABLES_UNLOCK();
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100563}
564
565static void*
566tracemalloc_malloc_gil(void *ctx, size_t size)
567{
Victor Stinner15116802013-12-04 01:29:35 +0100568 void *ptr;
569
570 if (get_reentrant()) {
571 PyMemAllocator *alloc = (PyMemAllocator *)ctx;
572 return alloc->malloc(alloc->ctx, size);
573 }
574
575 /* Ignore reentrant call. PyObjet_Malloc() calls PyMem_Malloc() for
576 allocations larger than 512 bytes, don't trace the same memory
577 allocation twice. */
578 set_reentrant(1);
579
580 ptr = tracemalloc_malloc(ctx, size);
581
582 set_reentrant(0);
583 return ptr;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100584}
585
586static void*
587tracemalloc_realloc_gil(void *ctx, void *ptr, size_t new_size)
588{
Victor Stinner15116802013-12-04 01:29:35 +0100589 void *ptr2;
590
591 if (get_reentrant()) {
592 /* Reentrant call to PyMem_Realloc() and PyMem_RawRealloc().
593 Example: PyMem_RawRealloc() is called internally by pymalloc
594 (_PyObject_Malloc() and _PyObject_Realloc()) to allocate a new
595 arena (new_arena()). */
596 PyMemAllocator *alloc = (PyMemAllocator *)ctx;
597
598 ptr2 = alloc->realloc(alloc->ctx, ptr, new_size);
Victor Stinner88c29872013-12-04 01:47:46 +0100599 if (ptr2 != NULL && ptr != NULL) {
600 TABLES_LOCK();
Victor Stinner15116802013-12-04 01:29:35 +0100601 tracemalloc_remove_trace(ptr);
Victor Stinner88c29872013-12-04 01:47:46 +0100602 TABLES_UNLOCK();
603 }
Victor Stinner15116802013-12-04 01:29:35 +0100604 return ptr2;
605 }
606
607 /* Ignore reentrant call. PyObjet_Realloc() calls PyMem_Realloc() for
608 allocations larger than 512 bytes. Don't trace the same memory
609 allocation twice. */
610 set_reentrant(1);
611
612 ptr2 = tracemalloc_realloc(ctx, ptr, new_size);
613
614 set_reentrant(0);
615 return ptr2;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100616}
617
618#ifdef TRACE_RAW_MALLOC
619static void*
620tracemalloc_raw_malloc(void *ctx, size_t size)
621{
Victor Stinner15116802013-12-04 01:29:35 +0100622#ifdef WITH_THREAD
623 PyGILState_STATE gil_state;
624#endif
625 void *ptr;
626
627 if (get_reentrant()) {
628 PyMemAllocator *alloc = (PyMemAllocator *)ctx;
629 return alloc->malloc(alloc->ctx, size);
630 }
631
632 /* Ignore reentrant call. PyGILState_Ensure() may call PyMem_RawMalloc()
633 indirectly which would call PyGILState_Ensure() if reentrant are not
634 disabled. */
635 set_reentrant(1);
636
637#ifdef WITH_THREAD
638 gil_state = PyGILState_Ensure();
639 ptr = tracemalloc_malloc(ctx, size);
640 PyGILState_Release(gil_state);
641#else
642 ptr = tracemalloc_malloc(ctx, size);
643#endif
644
645 set_reentrant(0);
646 return ptr;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100647}
648
649static void*
650tracemalloc_raw_realloc(void *ctx, void *ptr, size_t new_size)
651{
Victor Stinner15116802013-12-04 01:29:35 +0100652#ifdef WITH_THREAD
653 PyGILState_STATE gil_state;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100654#endif
Victor Stinner15116802013-12-04 01:29:35 +0100655 void *ptr2;
656
657 if (get_reentrant()) {
658 /* Reentrant call to PyMem_RawRealloc(). */
659 PyMemAllocator *alloc = (PyMemAllocator *)ctx;
660
661 ptr2 = alloc->realloc(alloc->ctx, ptr, new_size);
Victor Stinner15116802013-12-04 01:29:35 +0100662
Victor Stinner88c29872013-12-04 01:47:46 +0100663 if (ptr2 != NULL && ptr != NULL) {
664 TABLES_LOCK();
665 tracemalloc_remove_trace(ptr);
666 TABLES_UNLOCK();
667 }
Victor Stinner15116802013-12-04 01:29:35 +0100668 return ptr2;
669 }
670
671 /* Ignore reentrant call. PyGILState_Ensure() may call PyMem_RawMalloc()
672 indirectly which would call PyGILState_Ensure() if reentrant calls are
673 not disabled. */
674 set_reentrant(1);
675
676#ifdef WITH_THREAD
677 gil_state = PyGILState_Ensure();
678 ptr2 = tracemalloc_realloc(ctx, ptr, new_size);
679 PyGILState_Release(gil_state);
680#else
681 ptr2 = tracemalloc_realloc(ctx, ptr, new_size);
682#endif
683
684 set_reentrant(0);
685 return ptr2;
686}
687#endif /* TRACE_RAW_MALLOC */
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100688
689static int
690tracemalloc_clear_filename(_Py_hashtable_entry_t *entry, void *user_data)
691{
692 PyObject *filename = (PyObject *)entry->key;
693 Py_DECREF(filename);
694 return 0;
695}
696
697static int
698traceback_free_traceback(_Py_hashtable_entry_t *entry, void *user_data)
699{
700 traceback_t *traceback = (traceback_t *)entry->key;
701 raw_free(traceback);
702 return 0;
703}
704
705/* reentrant flag must be set to call this function and GIL must be held */
706static void
707tracemalloc_clear_traces(void)
708{
709#ifdef WITH_THREAD
710 /* The GIL protects variables againt concurrent access */
711 assert(PyGILState_Check());
712#endif
713
714 /* Disable also reentrant calls to tracemalloc_malloc() to not add a new
715 trace while we are clearing traces */
716 assert(get_reentrant());
717
718 TABLES_LOCK();
719 _Py_hashtable_clear(tracemalloc_traces);
720 tracemalloc_traced_memory = 0;
Victor Stinner3c0481d2013-11-27 21:39:49 +0100721 tracemalloc_peak_traced_memory = 0;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100722 TABLES_UNLOCK();
723
724 _Py_hashtable_foreach(tracemalloc_tracebacks, traceback_free_traceback, NULL);
725 _Py_hashtable_clear(tracemalloc_tracebacks);
726
727 _Py_hashtable_foreach(tracemalloc_filenames, tracemalloc_clear_filename, NULL);
728 _Py_hashtable_clear(tracemalloc_filenames);
729}
730
731static int
732tracemalloc_init(void)
733{
734 if (tracemalloc_config.initialized == TRACEMALLOC_FINALIZED) {
735 PyErr_SetString(PyExc_RuntimeError,
736 "the tracemalloc module has been unloaded");
737 return -1;
738 }
739
740 if (tracemalloc_config.initialized == TRACEMALLOC_INITIALIZED)
741 return 0;
742
743 PyMem_GetAllocator(PYMEM_DOMAIN_RAW, &allocators.raw);
744
745#ifdef REENTRANT_THREADLOCAL
746 tracemalloc_reentrant_key = PyThread_create_key();
747 if (tracemalloc_reentrant_key == -1) {
748#ifdef MS_WINDOWS
749 PyErr_SetFromWindowsErr(0);
750#else
751 PyErr_SetFromErrno(PyExc_OSError);
752#endif
753 return -1;
754 }
755#endif
756
757#if defined(WITH_THREAD) && defined(TRACE_RAW_MALLOC)
758 if (tables_lock == NULL) {
759 tables_lock = PyThread_allocate_lock();
760 if (tables_lock == NULL) {
761 PyErr_SetString(PyExc_RuntimeError, "cannot allocate lock");
762 return -1;
763 }
764 }
765#endif
766
767 tracemalloc_filenames = hashtable_new(0,
768 (_Py_hashtable_hash_func)PyObject_Hash,
769 hashtable_compare_unicode);
770
771 tracemalloc_tracebacks = hashtable_new(0,
772 (_Py_hashtable_hash_func)hashtable_hash_traceback,
773 (_Py_hashtable_compare_func)hashtable_compare_traceback);
774
775 tracemalloc_traces = hashtable_new(sizeof(trace_t),
776 _Py_hashtable_hash_ptr,
777 _Py_hashtable_compare_direct);
778
779 if (tracemalloc_filenames == NULL || tracemalloc_tracebacks == NULL
780 || tracemalloc_traces == NULL)
781 {
782 PyErr_NoMemory();
783 return -1;
784 }
785
786 unknown_filename = PyUnicode_FromString("<unknown>");
787 if (unknown_filename == NULL)
788 return -1;
789 PyUnicode_InternInPlace(&unknown_filename);
790
791 tracemalloc_empty_traceback.nframe = 1;
792 /* borrowed reference */
793 tracemalloc_empty_traceback.frames[0].filename = unknown_filename;
794 tracemalloc_empty_traceback.frames[0].lineno = 0;
795 tracemalloc_empty_traceback.hash = traceback_hash(&tracemalloc_empty_traceback);
796
797 /* Disable tracing allocations until hooks are installed. Set
798 also the reentrant flag to detect bugs: fail with an assertion error
799 if set_reentrant(1) is called while tracing is disabled. */
800 set_reentrant(1);
801
802 tracemalloc_config.initialized = TRACEMALLOC_INITIALIZED;
803 return 0;
804}
805
806static void
807tracemalloc_deinit(void)
808{
809 if (tracemalloc_config.initialized != TRACEMALLOC_INITIALIZED)
810 return;
811 tracemalloc_config.initialized = TRACEMALLOC_FINALIZED;
812
813 tracemalloc_stop();
814
815 /* destroy hash tables */
816 _Py_hashtable_destroy(tracemalloc_traces);
817 _Py_hashtable_destroy(tracemalloc_tracebacks);
818 _Py_hashtable_destroy(tracemalloc_filenames);
819
820#if defined(WITH_THREAD) && defined(TRACE_RAW_MALLOC)
821 if (tables_lock != NULL) {
822 PyThread_free_lock(tables_lock);
823 tables_lock = NULL;
824 }
825#endif
826
827#ifdef REENTRANT_THREADLOCAL
828 PyThread_delete_key(tracemalloc_reentrant_key);
829#endif
830
831 Py_XDECREF(unknown_filename);
832}
833
834static int
Victor Stinnerf28ce602013-11-27 22:27:13 +0100835tracemalloc_start(int max_nframe)
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100836{
837 PyMemAllocator alloc;
Victor Stinnerf28ce602013-11-27 22:27:13 +0100838 size_t size;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100839
840 if (tracemalloc_init() < 0)
841 return -1;
842
843 if (tracemalloc_config.tracing) {
844 /* hook already installed: do nothing */
845 return 0;
846 }
847
Victor Stinnerf28ce602013-11-27 22:27:13 +0100848 assert(1 <= max_nframe && max_nframe <= MAX_NFRAME);
849 tracemalloc_config.max_nframe = max_nframe;
850
851 /* allocate a buffer to store a new traceback */
852 size = TRACEBACK_SIZE(max_nframe);
853 assert(tracemalloc_traceback == NULL);
854 tracemalloc_traceback = raw_malloc(size);
855 if (tracemalloc_traceback == NULL) {
856 PyErr_NoMemory();
857 return -1;
858 }
859
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100860#ifdef TRACE_RAW_MALLOC
861 alloc.malloc = tracemalloc_raw_malloc;
862 alloc.realloc = tracemalloc_raw_realloc;
863 alloc.free = tracemalloc_free;
864
865 alloc.ctx = &allocators.raw;
866 PyMem_GetAllocator(PYMEM_DOMAIN_RAW, &allocators.raw);
867 PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &alloc);
868#endif
869
870 alloc.malloc = tracemalloc_malloc_gil;
871 alloc.realloc = tracemalloc_realloc_gil;
872 alloc.free = tracemalloc_free;
873
874 alloc.ctx = &allocators.mem;
875 PyMem_GetAllocator(PYMEM_DOMAIN_MEM, &allocators.mem);
876 PyMem_SetAllocator(PYMEM_DOMAIN_MEM, &alloc);
877
878 alloc.ctx = &allocators.obj;
879 PyMem_GetAllocator(PYMEM_DOMAIN_OBJ, &allocators.obj);
880 PyMem_SetAllocator(PYMEM_DOMAIN_OBJ, &alloc);
881
882 /* everything is ready: start tracing Python memory allocations */
883 tracemalloc_config.tracing = 1;
884 set_reentrant(0);
885
886 return 0;
887}
888
889static void
890tracemalloc_stop(void)
891{
892 if (!tracemalloc_config.tracing)
893 return;
894
895 /* stop tracing Python memory allocations */
896 tracemalloc_config.tracing = 0;
897
898 /* set the reentrant flag to detect bugs: fail with an assertion error if
899 set_reentrant(1) is called while tracing is disabled. */
900 set_reentrant(1);
901
902 /* unregister the hook on memory allocators */
903#ifdef TRACE_RAW_MALLOC
904 PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &allocators.raw);
905#endif
906 PyMem_SetAllocator(PYMEM_DOMAIN_MEM, &allocators.mem);
907 PyMem_SetAllocator(PYMEM_DOMAIN_OBJ, &allocators.obj);
908
909 /* release memory */
910 tracemalloc_clear_traces();
Victor Stinnerf28ce602013-11-27 22:27:13 +0100911 raw_free(tracemalloc_traceback);
912 tracemalloc_traceback = NULL;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100913}
914
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100915static PyObject*
916lineno_as_obj(int lineno)
917{
918 if (lineno >= 0)
919 return PyLong_FromLong(lineno);
920 else
921 Py_RETURN_NONE;
922}
923
924PyDoc_STRVAR(tracemalloc_is_tracing_doc,
925 "is_tracing()->bool\n"
926 "\n"
927 "True if the tracemalloc module is tracing Python memory allocations,\n"
928 "False otherwise.");
929
930static PyObject*
931py_tracemalloc_is_tracing(PyObject *self)
932{
933 return PyBool_FromLong(tracemalloc_config.tracing);
934}
935
936PyDoc_STRVAR(tracemalloc_clear_traces_doc,
937 "clear_traces()\n"
938 "\n"
939 "Clear traces of memory blocks allocated by Python.");
940
941static PyObject*
942py_tracemalloc_clear_traces(PyObject *self)
943{
944 if (!tracemalloc_config.tracing)
945 Py_RETURN_NONE;
946
947 set_reentrant(1);
948 tracemalloc_clear_traces();
949 set_reentrant(0);
950
951 Py_RETURN_NONE;
952}
953
954static PyObject*
955frame_to_pyobject(frame_t *frame)
956{
957 PyObject *frame_obj, *lineno_obj;
958
959 frame_obj = PyTuple_New(2);
960 if (frame_obj == NULL)
961 return NULL;
962
963 if (frame->filename == NULL)
964 frame->filename = Py_None;
965 Py_INCREF(frame->filename);
966 PyTuple_SET_ITEM(frame_obj, 0, frame->filename);
967
968 assert(frame->lineno >= 0);
969 lineno_obj = lineno_as_obj(frame->lineno);
970 if (lineno_obj == NULL) {
971 Py_DECREF(frame_obj);
972 return NULL;
973 }
974 PyTuple_SET_ITEM(frame_obj, 1, lineno_obj);
975
976 return frame_obj;
977}
978
979static PyObject*
980traceback_to_pyobject(traceback_t *traceback, _Py_hashtable_t *intern_table)
981{
982 int i;
983 PyObject *frames, *frame;
984
985 if (intern_table != NULL) {
986 if (_Py_HASHTABLE_GET(intern_table, traceback, frames)) {
987 Py_INCREF(frames);
988 return frames;
989 }
990 }
991
992 frames = PyTuple_New(traceback->nframe);
993 if (frames == NULL)
994 return NULL;
995
996 for (i=0; i < traceback->nframe; i++) {
997 frame = frame_to_pyobject(&traceback->frames[i]);
998 if (frame == NULL) {
999 Py_DECREF(frames);
1000 return NULL;
1001 }
1002 PyTuple_SET_ITEM(frames, i, frame);
1003 }
1004
1005 if (intern_table != NULL) {
1006 if (_Py_HASHTABLE_SET(intern_table, traceback, frames) < 0) {
1007 Py_DECREF(frames);
1008 PyErr_NoMemory();
1009 return NULL;
1010 }
1011 /* intern_table keeps a new reference to frames */
1012 Py_INCREF(frames);
1013 }
1014 return frames;
1015}
1016
1017static PyObject*
1018trace_to_pyobject(trace_t *trace, _Py_hashtable_t *intern_tracebacks)
1019{
1020 PyObject *trace_obj = NULL;
1021 PyObject *size, *traceback;
1022
1023 trace_obj = PyTuple_New(2);
1024 if (trace_obj == NULL)
1025 return NULL;
1026
1027 size = PyLong_FromSize_t(trace->size);
1028 if (size == NULL) {
1029 Py_DECREF(trace_obj);
1030 return NULL;
1031 }
1032 PyTuple_SET_ITEM(trace_obj, 0, size);
1033
1034 traceback = traceback_to_pyobject(trace->traceback, intern_tracebacks);
1035 if (traceback == NULL) {
1036 Py_DECREF(trace_obj);
1037 return NULL;
1038 }
1039 PyTuple_SET_ITEM(trace_obj, 1, traceback);
1040
1041 return trace_obj;
1042}
1043
1044typedef struct {
1045 _Py_hashtable_t *traces;
1046 _Py_hashtable_t *tracebacks;
1047 PyObject *list;
1048} get_traces_t;
1049
1050static int
1051tracemalloc_get_traces_fill(_Py_hashtable_entry_t *entry, void *user_data)
1052{
1053 get_traces_t *get_traces = user_data;
1054 trace_t *trace;
1055 PyObject *tracemalloc_obj;
1056 int res;
1057
1058 trace = (trace_t *)_PY_HASHTABLE_ENTRY_DATA(entry);
1059
1060 tracemalloc_obj = trace_to_pyobject(trace, get_traces->tracebacks);
1061 if (tracemalloc_obj == NULL)
1062 return 1;
1063
1064 res = PyList_Append(get_traces->list, tracemalloc_obj);
1065 Py_DECREF(tracemalloc_obj);
1066 if (res < 0)
1067 return 1;
1068
1069 return 0;
1070}
1071
1072static int
1073tracemalloc_pyobject_decref_cb(_Py_hashtable_entry_t *entry, void *user_data)
1074{
1075 PyObject *obj = (PyObject *)_Py_HASHTABLE_ENTRY_DATA_AS_VOID_P(entry);
1076 Py_DECREF(obj);
1077 return 0;
1078}
1079
1080PyDoc_STRVAR(tracemalloc_get_traces_doc,
Victor Stinner4fbefdb2013-11-25 09:33:18 +01001081 "_get_traces() -> list\n"
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001082 "\n"
1083 "Get traces of all memory blocks allocated by Python.\n"
1084 "Return a list of (size: int, traceback: tuple) tuples.\n"
1085 "traceback is a tuple of (filename: str, lineno: int) tuples.\n"
1086 "\n"
1087 "Return an empty list if the tracemalloc module is disabled.");
1088
1089static PyObject*
1090py_tracemalloc_get_traces(PyObject *self, PyObject *obj)
1091{
1092 get_traces_t get_traces;
1093 int err;
1094
1095 get_traces.traces = NULL;
1096 get_traces.tracebacks = NULL;
1097 get_traces.list = PyList_New(0);
1098 if (get_traces.list == NULL)
1099 goto error;
1100
1101 if (!tracemalloc_config.tracing)
1102 return get_traces.list;
1103
Victor Stinnerde2f1322013-11-26 00:26:23 +01001104 /* the traceback hash table is used temporarily to intern traceback tuple
1105 of (filename, lineno) tuples */
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001106 get_traces.tracebacks = hashtable_new(sizeof(PyObject *),
1107 _Py_hashtable_hash_ptr,
1108 _Py_hashtable_compare_direct);
1109 if (get_traces.tracebacks == NULL) {
1110 PyErr_NoMemory();
1111 goto error;
1112 }
1113
1114 TABLES_LOCK();
1115 get_traces.traces = _Py_hashtable_copy(tracemalloc_traces);
1116 TABLES_UNLOCK();
1117
1118 if (get_traces.traces == NULL) {
1119 PyErr_NoMemory();
1120 goto error;
1121 }
1122
1123 set_reentrant(1);
1124 err = _Py_hashtable_foreach(get_traces.traces,
1125 tracemalloc_get_traces_fill, &get_traces);
1126 set_reentrant(0);
1127 if (err)
1128 goto error;
1129
1130 goto finally;
1131
1132error:
1133 Py_CLEAR(get_traces.list);
1134
1135finally:
1136 if (get_traces.tracebacks != NULL) {
1137 _Py_hashtable_foreach(get_traces.tracebacks,
1138 tracemalloc_pyobject_decref_cb, NULL);
1139 _Py_hashtable_destroy(get_traces.tracebacks);
1140 }
1141 if (get_traces.traces != NULL)
1142 _Py_hashtable_destroy(get_traces.traces);
1143
1144 return get_traces.list;
1145}
1146
1147PyDoc_STRVAR(tracemalloc_get_object_traceback_doc,
Victor Stinner4fbefdb2013-11-25 09:33:18 +01001148 "_get_object_traceback(obj)\n"
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001149 "\n"
1150 "Get the traceback where the Python object obj was allocated.\n"
1151 "Return a tuple of (filename: str, lineno: int) tuples.\n"
1152 "\n"
1153 "Return None if the tracemalloc module is disabled or did not\n"
1154 "trace the allocation of the object.");
1155
1156static PyObject*
1157py_tracemalloc_get_object_traceback(PyObject *self, PyObject *obj)
1158{
1159 PyTypeObject *type;
1160 void *ptr;
1161 trace_t trace;
1162 int found;
1163
1164 if (!tracemalloc_config.tracing)
1165 Py_RETURN_NONE;
1166
1167 type = Py_TYPE(obj);
1168 if (PyType_IS_GC(type))
1169 ptr = (void *)((char *)obj - sizeof(PyGC_Head));
1170 else
1171 ptr = (void *)obj;
1172
1173 TABLES_LOCK();
1174 found = _Py_HASHTABLE_GET(tracemalloc_traces, ptr, trace);
1175 TABLES_UNLOCK();
1176
1177 if (!found)
1178 Py_RETURN_NONE;
1179
1180 return traceback_to_pyobject(trace.traceback, NULL);
1181}
1182
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001183PyDoc_STRVAR(tracemalloc_start_doc,
Victor Stinner3728d6c2013-11-23 12:37:20 +01001184 "start(nframe: int=1)\n"
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001185 "\n"
Victor Stinner3728d6c2013-11-23 12:37:20 +01001186 "Start tracing Python memory allocations. Set also the maximum number \n"
1187 "of frames stored in the traceback of a trace to nframe.");
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001188
1189static PyObject*
Victor Stinner3728d6c2013-11-23 12:37:20 +01001190py_tracemalloc_start(PyObject *self, PyObject *args)
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001191{
Victor Stinner3728d6c2013-11-23 12:37:20 +01001192 Py_ssize_t nframe = 1;
Victor Stinnerf28ce602013-11-27 22:27:13 +01001193 int nframe_int;
Victor Stinner3728d6c2013-11-23 12:37:20 +01001194
1195 if (!PyArg_ParseTuple(args, "|n:start", &nframe))
1196 return NULL;
1197
1198 if (nframe < 1 || nframe > MAX_NFRAME) {
1199 PyErr_Format(PyExc_ValueError,
1200 "the number of frames must be in range [1; %i]",
Victor Stinnerf28ce602013-11-27 22:27:13 +01001201 (int)MAX_NFRAME);
Victor Stinner3728d6c2013-11-23 12:37:20 +01001202 return NULL;
1203 }
Victor Stinnerf28ce602013-11-27 22:27:13 +01001204 nframe_int = Py_SAFE_DOWNCAST(nframe, Py_ssize_t, int);
Victor Stinner3728d6c2013-11-23 12:37:20 +01001205
Victor Stinnerf28ce602013-11-27 22:27:13 +01001206 if (tracemalloc_start(nframe_int) < 0)
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001207 return NULL;
1208
1209 Py_RETURN_NONE;
1210}
1211
1212PyDoc_STRVAR(tracemalloc_stop_doc,
1213 "stop()\n"
1214 "\n"
1215 "Stop tracing Python memory allocations and clear traces\n"
1216 "of memory blocks allocated by Python.");
1217
1218static PyObject*
1219py_tracemalloc_stop(PyObject *self)
1220{
1221 tracemalloc_stop();
1222 Py_RETURN_NONE;
1223}
1224
1225PyDoc_STRVAR(tracemalloc_get_traceback_limit_doc,
1226 "get_traceback_limit() -> int\n"
1227 "\n"
1228 "Get the maximum number of frames stored in the traceback\n"
1229 "of a trace.\n"
1230 "\n"
1231 "By default, a trace of an allocated memory block only stores\n"
1232 "the most recent frame: the limit is 1.");
1233
1234static PyObject*
1235py_tracemalloc_get_traceback_limit(PyObject *self)
1236{
1237 return PyLong_FromLong(tracemalloc_config.max_nframe);
1238}
1239
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001240PyDoc_STRVAR(tracemalloc_get_tracemalloc_memory_doc,
1241 "get_tracemalloc_memory() -> int\n"
1242 "\n"
1243 "Get the memory usage in bytes of the tracemalloc module\n"
1244 "used internally to trace memory allocations.");
1245
1246static PyObject*
1247tracemalloc_get_tracemalloc_memory(PyObject *self)
1248{
1249 size_t size;
1250 PyObject *size_obj;
1251
1252 size = _Py_hashtable_size(tracemalloc_tracebacks);
1253 size += _Py_hashtable_size(tracemalloc_filenames);
1254
1255 TABLES_LOCK();
1256 size += _Py_hashtable_size(tracemalloc_traces);
1257 TABLES_UNLOCK();
1258
1259 size_obj = PyLong_FromSize_t(size);
1260 return Py_BuildValue("N", size_obj);
1261}
1262
1263PyDoc_STRVAR(tracemalloc_get_traced_memory_doc,
Victor Stinner59463d82013-11-26 10:46:06 +01001264 "get_traced_memory() -> (int, int)\n"
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001265 "\n"
Victor Stinner3c0481d2013-11-27 21:39:49 +01001266 "Get the current size and peak size of memory blocks traced\n"
1267 "by the tracemalloc module as a tuple: (current: int, peak: int).");
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001268
1269static PyObject*
1270tracemalloc_get_traced_memory(PyObject *self)
1271{
Victor Stinner3c0481d2013-11-27 21:39:49 +01001272 Py_ssize_t size, peak_size;
1273 PyObject *size_obj, *peak_size_obj;
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001274
1275 if (!tracemalloc_config.tracing)
1276 return Py_BuildValue("ii", 0, 0);
1277
1278 TABLES_LOCK();
1279 size = tracemalloc_traced_memory;
Victor Stinner3c0481d2013-11-27 21:39:49 +01001280 peak_size = tracemalloc_peak_traced_memory;
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001281 TABLES_UNLOCK();
1282
1283 size_obj = PyLong_FromSize_t(size);
Victor Stinner3c0481d2013-11-27 21:39:49 +01001284 peak_size_obj = PyLong_FromSize_t(peak_size);
1285 return Py_BuildValue("NN", size_obj, peak_size_obj);
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001286}
1287
1288static PyMethodDef module_methods[] = {
1289 {"is_tracing", (PyCFunction)py_tracemalloc_is_tracing,
1290 METH_NOARGS, tracemalloc_is_tracing_doc},
1291 {"clear_traces", (PyCFunction)py_tracemalloc_clear_traces,
1292 METH_NOARGS, tracemalloc_clear_traces_doc},
1293 {"_get_traces", (PyCFunction)py_tracemalloc_get_traces,
1294 METH_NOARGS, tracemalloc_get_traces_doc},
1295 {"_get_object_traceback", (PyCFunction)py_tracemalloc_get_object_traceback,
1296 METH_O, tracemalloc_get_object_traceback_doc},
1297 {"start", (PyCFunction)py_tracemalloc_start,
Victor Stinner3728d6c2013-11-23 12:37:20 +01001298 METH_VARARGS, tracemalloc_start_doc},
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001299 {"stop", (PyCFunction)py_tracemalloc_stop,
1300 METH_NOARGS, tracemalloc_stop_doc},
1301 {"get_traceback_limit", (PyCFunction)py_tracemalloc_get_traceback_limit,
1302 METH_NOARGS, tracemalloc_get_traceback_limit_doc},
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001303 {"get_tracemalloc_memory", (PyCFunction)tracemalloc_get_tracemalloc_memory,
1304 METH_NOARGS, tracemalloc_get_tracemalloc_memory_doc},
1305 {"get_traced_memory", (PyCFunction)tracemalloc_get_traced_memory,
1306 METH_NOARGS, tracemalloc_get_traced_memory_doc},
1307
1308 /* sentinel */
1309 {NULL, NULL}
1310};
1311
1312PyDoc_STRVAR(module_doc,
1313"Debug module to trace memory blocks allocated by Python.");
1314
1315static struct PyModuleDef module_def = {
1316 PyModuleDef_HEAD_INIT,
1317 "_tracemalloc",
1318 module_doc,
1319 0, /* non-negative size to be able to unload the module */
1320 module_methods,
1321 NULL,
1322};
1323
1324PyMODINIT_FUNC
1325PyInit__tracemalloc(void)
1326{
1327 PyObject *m;
1328 m = PyModule_Create(&module_def);
1329 if (m == NULL)
1330 return NULL;
1331
1332 if (tracemalloc_init() < 0)
1333 return NULL;
1334
1335 return m;
1336}
1337
1338static int
1339parse_sys_xoptions(PyObject *value)
1340{
1341 PyObject *valuelong;
1342 long nframe;
1343
1344 if (value == Py_True)
1345 return 1;
1346
1347 assert(PyUnicode_Check(value));
1348 if (PyUnicode_GetLength(value) == 0)
1349 return -1;
1350
1351 valuelong = PyLong_FromUnicodeObject(value, 10);
1352 if (valuelong == NULL)
1353 return -1;
1354
1355 nframe = PyLong_AsLong(valuelong);
1356 Py_DECREF(valuelong);
1357 if (nframe == -1 && PyErr_Occurred())
1358 return -1;
1359
1360 if (nframe < 1 || nframe > MAX_NFRAME)
1361 return -1;
1362
1363 return Py_SAFE_DOWNCAST(nframe, long, int);
1364}
1365
1366int
1367_PyTraceMalloc_Init(void)
1368{
1369 char *p;
1370 int nframe;
1371
1372#ifdef WITH_THREAD
1373 assert(PyGILState_Check());
1374#endif
1375
1376 if ((p = Py_GETENV("PYTHONTRACEMALLOC")) && *p != '\0') {
1377 char *endptr = p;
Victor Stinnerf28ce602013-11-27 22:27:13 +01001378 long value;
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001379
Victor Stinnerf28ce602013-11-27 22:27:13 +01001380 value = strtol(p, &endptr, 10);
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001381 if (*endptr != '\0'
1382 || value < 1
1383 || value > MAX_NFRAME
1384 || (errno == ERANGE && value == ULONG_MAX))
1385 {
Victor Stinnerf28ce602013-11-27 22:27:13 +01001386 Py_FatalError("PYTHONTRACEMALLOC: invalid number of frames");
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001387 return -1;
1388 }
1389
1390 nframe = (int)value;
1391 }
1392 else {
1393 PyObject *xoptions, *key, *value;
1394
1395 xoptions = PySys_GetXOptions();
1396 if (xoptions == NULL)
1397 return -1;
1398
1399 key = PyUnicode_FromString("tracemalloc");
1400 if (key == NULL)
1401 return -1;
1402
1403 value = PyDict_GetItemWithError(xoptions, key);
1404 Py_DECREF(key);
1405 if (value == NULL) {
1406 if (PyErr_Occurred())
1407 return -1;
1408
1409 /* -X tracemalloc is not used */
1410 return 0;
1411 }
1412
1413 nframe = parse_sys_xoptions(value);
1414 Py_DECREF(value);
1415 if (nframe < 0) {
Victor Stinnerf28ce602013-11-27 22:27:13 +01001416 Py_FatalError("-X tracemalloc=NFRAME: invalid number of frames");
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001417 }
1418 }
1419
Victor Stinnerf28ce602013-11-27 22:27:13 +01001420 return tracemalloc_start(nframe);
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001421}
1422
Victor Stinnerbe0708f2013-12-01 10:03:26 +01001423void
1424_PyTraceMalloc_Fini(void)
1425{
1426#ifdef WITH_THREAD
1427 assert(PyGILState_Check());
1428#endif
1429 tracemalloc_deinit();
1430}
1431