blob: bbe7259959a084d3e242cb15a5cc805c661fe476 [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. */
Victor Stinnered3b0bc2013-11-23 12:27:24 +010064typedef struct
65#ifdef __GNUC__
66__attribute__((packed))
Victor Stinnerdd382ef2014-02-01 03:43:58 +010067#elif defined(_MSC_VER)
68_declspec(align(4))
Victor Stinnered3b0bc2013-11-23 12:27:24 +010069#endif
70{
71 PyObject *filename;
72 int lineno;
73} frame_t;
74
75typedef struct {
76 Py_uhash_t hash;
77 int nframe;
78 frame_t frames[1];
79} traceback_t;
80
81#define TRACEBACK_SIZE(NFRAME) \
82 (sizeof(traceback_t) + sizeof(frame_t) * (NFRAME - 1))
Victor Stinnerf28ce602013-11-27 22:27:13 +010083
84#define MAX_NFRAME \
85 ((INT_MAX - sizeof(traceback_t)) / sizeof(frame_t) + 1)
Victor Stinnered3b0bc2013-11-23 12:27:24 +010086
87static PyObject *unknown_filename = NULL;
88static traceback_t tracemalloc_empty_traceback;
89
Victor Stinner7a5be142013-11-26 01:06:02 +010090/* Trace of a memory block */
Victor Stinnered3b0bc2013-11-23 12:27:24 +010091typedef struct {
Victor Stinner7a5be142013-11-26 01:06:02 +010092 /* Size of the memory block in bytes */
Victor Stinnered3b0bc2013-11-23 12:27:24 +010093 size_t size;
Victor Stinner7a5be142013-11-26 01:06:02 +010094
95 /* Traceback where the memory block was allocated */
Victor Stinnered3b0bc2013-11-23 12:27:24 +010096 traceback_t *traceback;
97} trace_t;
98
99/* Size in bytes of currently traced memory.
100 Protected by TABLES_LOCK(). */
101static size_t tracemalloc_traced_memory = 0;
102
Victor Stinner3c0481d2013-11-27 21:39:49 +0100103/* Peak size in bytes of traced memory.
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100104 Protected by TABLES_LOCK(). */
Victor Stinner3c0481d2013-11-27 21:39:49 +0100105static size_t tracemalloc_peak_traced_memory = 0;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100106
Serhiy Storchaka56a6d852014-12-01 18:28:43 +0200107/* Hash table used as a set to intern filenames:
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100108 PyObject* => PyObject*.
109 Protected by the GIL */
110static _Py_hashtable_t *tracemalloc_filenames = NULL;
111
Victor Stinnerf28ce602013-11-27 22:27:13 +0100112/* Buffer to store a new traceback in traceback_new().
113 Protected by the GIL. */
114static traceback_t *tracemalloc_traceback = NULL;
115
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100116/* Hash table used as a set to intern tracebacks:
117 traceback_t* => traceback_t*
118 Protected by the GIL */
119static _Py_hashtable_t *tracemalloc_tracebacks = NULL;
120
121/* pointer (void*) => trace (trace_t).
122 Protected by TABLES_LOCK(). */
123static _Py_hashtable_t *tracemalloc_traces = NULL;
124
125#ifdef TRACE_DEBUG
126static void
127tracemalloc_error(const char *format, ...)
128{
129 va_list ap;
130 fprintf(stderr, "tracemalloc: ");
131 va_start(ap, format);
132 vfprintf(stderr, format, ap);
133 va_end(ap);
134 fprintf(stderr, "\n");
135 fflush(stderr);
136}
137#endif
138
139#if defined(WITH_THREAD) && defined(TRACE_RAW_MALLOC)
140#define REENTRANT_THREADLOCAL
141
142/* If your OS does not provide native thread local storage, you can implement
143 it manually using a lock. Functions of thread.c cannot be used because
144 they use PyMem_RawMalloc() which leads to a reentrant call. */
145#if !(defined(_POSIX_THREADS) || defined(NT_THREADS))
146# error "need native thread local storage (TLS)"
147#endif
148
149static int tracemalloc_reentrant_key;
150
151/* Any non-NULL pointer can be used */
152#define REENTRANT Py_True
153
154static int
155get_reentrant(void)
156{
157 void *ptr = PyThread_get_key_value(tracemalloc_reentrant_key);
158 if (ptr != NULL) {
159 assert(ptr == REENTRANT);
160 return 1;
161 }
162 else
163 return 0;
164}
165
166static void
167set_reentrant(int reentrant)
168{
Victor Stinner2ead3d22013-11-26 01:08:53 +0100169 assert(reentrant == 0 || reentrant == 1);
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100170 if (reentrant) {
171 assert(PyThread_get_key_value(tracemalloc_reentrant_key) == NULL);
Victor Stinner590cebe2013-12-13 11:08:56 +0100172 PyThread_set_key_value(tracemalloc_reentrant_key, REENTRANT);
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100173 }
174 else {
Victor Stinner590cebe2013-12-13 11:08:56 +0100175 assert(PyThread_get_key_value(tracemalloc_reentrant_key) == REENTRANT);
176 PyThread_set_key_value(tracemalloc_reentrant_key, NULL);
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100177 }
178}
179
180#else
181
182/* WITH_THREAD not defined: Python compiled without threads,
183 or TRACE_RAW_MALLOC not defined: variable protected by the GIL */
184static int tracemalloc_reentrant = 0;
185
186static int
187get_reentrant(void)
188{
189 return tracemalloc_reentrant;
190}
191
192static void
193set_reentrant(int reentrant)
194{
195 assert(!reentrant || !get_reentrant());
196 tracemalloc_reentrant = reentrant;
197}
198#endif
199
200static int
201hashtable_compare_unicode(const void *key, const _Py_hashtable_entry_t *entry)
202{
203 if (key != NULL && entry->key != NULL)
204 return (PyUnicode_Compare((PyObject *)key, (PyObject *)entry->key) == 0);
205 else
206 return key == entry->key;
207}
208
209static _Py_hashtable_allocator_t hashtable_alloc = {malloc, free};
210
211static _Py_hashtable_t *
212hashtable_new(size_t data_size,
213 _Py_hashtable_hash_func hash_func,
214 _Py_hashtable_compare_func compare_func)
215{
216 return _Py_hashtable_new_full(data_size, 0,
217 hash_func, compare_func,
218 NULL, NULL, NULL, &hashtable_alloc);
219}
220
221static void*
222raw_malloc(size_t size)
223{
224 return allocators.raw.malloc(allocators.raw.ctx, size);
225}
226
227static void
228raw_free(void *ptr)
229{
230 allocators.raw.free(allocators.raw.ctx, ptr);
231}
232
233static Py_uhash_t
234hashtable_hash_traceback(const void *key)
235{
236 const traceback_t *traceback = key;
237 return traceback->hash;
238}
239
240static int
241hashtable_compare_traceback(const traceback_t *traceback1,
242 const _Py_hashtable_entry_t *he)
243{
244 const traceback_t *traceback2 = he->key;
245 const frame_t *frame1, *frame2;
246 int i;
247
248 if (traceback1->nframe != traceback2->nframe)
249 return 0;
250
251 for (i=0; i < traceback1->nframe; i++) {
252 frame1 = &traceback1->frames[i];
253 frame2 = &traceback2->frames[i];
254
255 if (frame1->lineno != frame2->lineno)
256 return 0;
257
258 if (frame1->filename != frame2->filename) {
259 assert(PyUnicode_Compare(frame1->filename, frame2->filename) != 0);
260 return 0;
261 }
262 }
263 return 1;
264}
265
266static void
267tracemalloc_get_frame(PyFrameObject *pyframe, frame_t *frame)
268{
269 PyCodeObject *code;
270 PyObject *filename;
271 _Py_hashtable_entry_t *entry;
272
273 frame->filename = unknown_filename;
274 frame->lineno = PyFrame_GetLineNumber(pyframe);
275 assert(frame->lineno >= 0);
276 if (frame->lineno < 0)
277 frame->lineno = 0;
278
279 code = pyframe->f_code;
280 if (code == NULL) {
281#ifdef TRACE_DEBUG
Victor Stinner4dc74202013-11-26 01:18:52 +0100282 tracemalloc_error("failed to get the code object of the frame");
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100283#endif
284 return;
285 }
286
287 if (code->co_filename == NULL) {
288#ifdef TRACE_DEBUG
289 tracemalloc_error("failed to get the filename of the code object");
290#endif
291 return;
292 }
293
294 filename = code->co_filename;
295 assert(filename != NULL);
296 if (filename == NULL)
297 return;
298
299 if (!PyUnicode_Check(filename)) {
300#ifdef TRACE_DEBUG
301 tracemalloc_error("filename is not an unicode string");
302#endif
303 return;
304 }
305 if (!PyUnicode_IS_READY(filename)) {
306 /* Don't make a Unicode string ready to avoid reentrant calls
307 to tracemalloc_malloc() or tracemalloc_realloc() */
308#ifdef TRACE_DEBUG
309 tracemalloc_error("filename is not a ready unicode string");
310#endif
311 return;
312 }
313
314 /* intern the filename */
315 entry = _Py_hashtable_get_entry(tracemalloc_filenames, filename);
316 if (entry != NULL) {
317 filename = (PyObject *)entry->key;
318 }
319 else {
320 /* tracemalloc_filenames is responsible to keep a reference
321 to the filename */
322 Py_INCREF(filename);
323 if (_Py_hashtable_set(tracemalloc_filenames, filename, NULL, 0) < 0) {
324 Py_DECREF(filename);
325#ifdef TRACE_DEBUG
326 tracemalloc_error("failed to intern the filename");
327#endif
328 return;
329 }
330 }
331
332 /* the tracemalloc_filenames table keeps a reference to the filename */
333 frame->filename = filename;
334}
335
336static Py_uhash_t
337traceback_hash(traceback_t *traceback)
338{
339 /* code based on tuplehash() of Objects/tupleobject.c */
Victor Stinner4d8c29c2013-12-16 23:05:13 +0100340 Py_uhash_t x, y; /* Unsigned for defined overflow behavior. */
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100341 int len = traceback->nframe;
342 Py_uhash_t mult = _PyHASH_MULTIPLIER;
343 frame_t *frame;
344
345 x = 0x345678UL;
346 frame = traceback->frames;
347 while (--len >= 0) {
Victor Stinner4d8c29c2013-12-16 23:05:13 +0100348 y = (Py_uhash_t)PyObject_Hash(frame->filename);
349 y ^= (Py_uhash_t)frame->lineno;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100350 frame++;
351
352 x = (x ^ y) * mult;
353 /* the cast might truncate len; that doesn't change hash stability */
Victor Stinner4d8c29c2013-12-16 23:05:13 +0100354 mult += (Py_uhash_t)(82520UL + len + len);
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100355 }
356 x += 97531UL;
357 return x;
358}
359
360static void
361traceback_get_frames(traceback_t *traceback)
362{
363 PyThreadState *tstate;
364 PyFrameObject *pyframe;
365
366#ifdef WITH_THREAD
367 tstate = PyGILState_GetThisThreadState();
368#else
369 tstate = PyThreadState_Get();
370#endif
371 if (tstate == NULL) {
372#ifdef TRACE_DEBUG
373 tracemalloc_error("failed to get the current thread state");
374#endif
375 return;
376 }
377
378 for (pyframe = tstate->frame; pyframe != NULL; pyframe = pyframe->f_back) {
379 tracemalloc_get_frame(pyframe, &traceback->frames[traceback->nframe]);
380 assert(traceback->frames[traceback->nframe].filename != NULL);
381 assert(traceback->frames[traceback->nframe].lineno >= 0);
382 traceback->nframe++;
383 if (traceback->nframe == tracemalloc_config.max_nframe)
384 break;
385 }
386}
387
388static traceback_t *
389traceback_new(void)
390{
Victor Stinnerf28ce602013-11-27 22:27:13 +0100391 traceback_t *traceback;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100392 _Py_hashtable_entry_t *entry;
393
394#ifdef WITH_THREAD
395 assert(PyGILState_Check());
396#endif
397
398 /* get frames */
Victor Stinnerf28ce602013-11-27 22:27:13 +0100399 traceback = tracemalloc_traceback;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100400 traceback->nframe = 0;
401 traceback_get_frames(traceback);
402 if (traceback->nframe == 0)
403 return &tracemalloc_empty_traceback;
404 traceback->hash = traceback_hash(traceback);
405
406 /* intern the traceback */
407 entry = _Py_hashtable_get_entry(tracemalloc_tracebacks, traceback);
408 if (entry != NULL) {
409 traceback = (traceback_t *)entry->key;
410 }
411 else {
412 traceback_t *copy;
413 size_t traceback_size;
414
415 traceback_size = TRACEBACK_SIZE(traceback->nframe);
416
417 copy = raw_malloc(traceback_size);
418 if (copy == NULL) {
419#ifdef TRACE_DEBUG
420 tracemalloc_error("failed to intern the traceback: malloc failed");
421#endif
422 return NULL;
423 }
424 memcpy(copy, traceback, traceback_size);
425
426 if (_Py_hashtable_set(tracemalloc_tracebacks, copy, NULL, 0) < 0) {
427 raw_free(copy);
428#ifdef TRACE_DEBUG
429 tracemalloc_error("failed to intern the traceback: putdata failed");
430#endif
431 return NULL;
432 }
433 traceback = copy;
434 }
435 return traceback;
436}
437
Victor Stinner52968672013-11-24 11:37:15 +0100438static int
Victor Stinner15116802013-12-04 01:29:35 +0100439tracemalloc_add_trace(void *ptr, size_t size)
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100440{
441 traceback_t *traceback;
442 trace_t trace;
Victor Stinner52968672013-11-24 11:37:15 +0100443 int res;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100444
445#ifdef WITH_THREAD
446 assert(PyGILState_Check());
447#endif
448
449 traceback = traceback_new();
Victor Stinner52968672013-11-24 11:37:15 +0100450 if (traceback == NULL)
451 return -1;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100452
453 trace.size = size;
454 trace.traceback = traceback;
455
Victor Stinner52968672013-11-24 11:37:15 +0100456 res = _Py_HASHTABLE_SET(tracemalloc_traces, ptr, trace);
457 if (res == 0) {
Victor Stinnerd606ba72013-11-24 11:28:20 +0100458 assert(tracemalloc_traced_memory <= PY_SIZE_MAX - size);
459 tracemalloc_traced_memory += size;
Victor Stinner3c0481d2013-11-27 21:39:49 +0100460 if (tracemalloc_traced_memory > tracemalloc_peak_traced_memory)
461 tracemalloc_peak_traced_memory = tracemalloc_traced_memory;
Victor Stinnerd606ba72013-11-24 11:28:20 +0100462 }
Victor Stinner52968672013-11-24 11:37:15 +0100463
464 return res;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100465}
466
467static void
Victor Stinner15116802013-12-04 01:29:35 +0100468tracemalloc_remove_trace(void *ptr)
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100469{
470 trace_t trace;
471
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100472 if (_Py_hashtable_pop(tracemalloc_traces, ptr, &trace, sizeof(trace))) {
473 assert(tracemalloc_traced_memory >= trace.size);
474 tracemalloc_traced_memory -= trace.size;
475 }
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100476}
477
478static void*
Victor Stinner15116802013-12-04 01:29:35 +0100479tracemalloc_malloc(void *ctx, size_t size)
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100480{
481 PyMemAllocator *alloc = (PyMemAllocator *)ctx;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100482 void *ptr;
483
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100484 ptr = alloc->malloc(alloc->ctx, size);
Victor Stinner15116802013-12-04 01:29:35 +0100485 if (ptr == NULL)
486 return NULL;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100487
Victor Stinner88c29872013-12-04 01:47:46 +0100488 TABLES_LOCK();
Victor Stinner15116802013-12-04 01:29:35 +0100489 if (tracemalloc_add_trace(ptr, size) < 0) {
490 /* Failed to allocate a trace for the new memory block */
Victor Stinner88c29872013-12-04 01:47:46 +0100491 TABLES_UNLOCK();
Victor Stinner15116802013-12-04 01:29:35 +0100492 alloc->free(alloc->ctx, ptr);
493 return NULL;
Victor Stinner52968672013-11-24 11:37:15 +0100494 }
Victor Stinner88c29872013-12-04 01:47:46 +0100495 TABLES_UNLOCK();
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100496 return ptr;
497}
498
499static void*
Victor Stinner15116802013-12-04 01:29:35 +0100500tracemalloc_realloc(void *ctx, void *ptr, size_t new_size)
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100501{
502 PyMemAllocator *alloc = (PyMemAllocator *)ctx;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100503 void *ptr2;
504
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100505 ptr2 = alloc->realloc(alloc->ctx, ptr, new_size);
Victor Stinner15116802013-12-04 01:29:35 +0100506 if (ptr2 == NULL)
507 return NULL;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100508
Victor Stinner15116802013-12-04 01:29:35 +0100509 if (ptr != NULL) {
510 /* an existing memory block has been resized */
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100511
Victor Stinner88c29872013-12-04 01:47:46 +0100512 TABLES_LOCK();
Victor Stinner15116802013-12-04 01:29:35 +0100513 tracemalloc_remove_trace(ptr);
Victor Stinner08facd22013-11-24 12:27:59 +0100514
Victor Stinner15116802013-12-04 01:29:35 +0100515 if (tracemalloc_add_trace(ptr2, new_size) < 0) {
516 /* Memory allocation failed. The error cannot be reported to
517 the caller, because realloc() may already have shrinked the
518 memory block and so removed bytes.
519
Victor Stinner88c29872013-12-04 01:47:46 +0100520 This case is very unlikely: an hash entry has just been
521 released, so the hash table should have at least one free entry.
522
523 The GIL and the table lock ensures that only one thread is
524 allocating memory. */
525 assert(0 && "should never happen");
Victor Stinner52968672013-11-24 11:37:15 +0100526 }
Victor Stinner88c29872013-12-04 01:47:46 +0100527 TABLES_UNLOCK();
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100528 }
Victor Stinner15116802013-12-04 01:29:35 +0100529 else {
530 /* new allocation */
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100531
Victor Stinner88c29872013-12-04 01:47:46 +0100532 TABLES_LOCK();
Victor Stinner15116802013-12-04 01:29:35 +0100533 if (tracemalloc_add_trace(ptr2, new_size) < 0) {
534 /* Failed to allocate a trace for the new memory block */
Victor Stinner88c29872013-12-04 01:47:46 +0100535 TABLES_UNLOCK();
Victor Stinner15116802013-12-04 01:29:35 +0100536 alloc->free(alloc->ctx, ptr2);
537 return NULL;
538 }
Victor Stinner88c29872013-12-04 01:47:46 +0100539 TABLES_UNLOCK();
Victor Stinner15116802013-12-04 01:29:35 +0100540 }
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100541 return ptr2;
542}
543
544static void
545tracemalloc_free(void *ctx, void *ptr)
546{
547 PyMemAllocator *alloc = (PyMemAllocator *)ctx;
548
549 if (ptr == NULL)
550 return;
551
552 /* GIL cannot be locked in PyMem_RawFree() because it would introduce
553 a deadlock in PyThreadState_DeleteCurrent(). */
554
555 alloc->free(alloc->ctx, ptr);
Victor Stinner88c29872013-12-04 01:47:46 +0100556
557 TABLES_LOCK();
Victor Stinner15116802013-12-04 01:29:35 +0100558 tracemalloc_remove_trace(ptr);
Victor Stinner88c29872013-12-04 01:47:46 +0100559 TABLES_UNLOCK();
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100560}
561
562static void*
563tracemalloc_malloc_gil(void *ctx, size_t size)
564{
Victor Stinner15116802013-12-04 01:29:35 +0100565 void *ptr;
566
567 if (get_reentrant()) {
568 PyMemAllocator *alloc = (PyMemAllocator *)ctx;
569 return alloc->malloc(alloc->ctx, size);
570 }
571
572 /* Ignore reentrant call. PyObjet_Malloc() calls PyMem_Malloc() for
573 allocations larger than 512 bytes, don't trace the same memory
574 allocation twice. */
575 set_reentrant(1);
576
577 ptr = tracemalloc_malloc(ctx, size);
578
579 set_reentrant(0);
580 return ptr;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100581}
582
583static void*
584tracemalloc_realloc_gil(void *ctx, void *ptr, size_t new_size)
585{
Victor Stinner15116802013-12-04 01:29:35 +0100586 void *ptr2;
587
588 if (get_reentrant()) {
589 /* Reentrant call to PyMem_Realloc() and PyMem_RawRealloc().
590 Example: PyMem_RawRealloc() is called internally by pymalloc
591 (_PyObject_Malloc() and _PyObject_Realloc()) to allocate a new
592 arena (new_arena()). */
593 PyMemAllocator *alloc = (PyMemAllocator *)ctx;
594
595 ptr2 = alloc->realloc(alloc->ctx, ptr, new_size);
Victor Stinner88c29872013-12-04 01:47:46 +0100596 if (ptr2 != NULL && ptr != NULL) {
597 TABLES_LOCK();
Victor Stinner15116802013-12-04 01:29:35 +0100598 tracemalloc_remove_trace(ptr);
Victor Stinner88c29872013-12-04 01:47:46 +0100599 TABLES_UNLOCK();
600 }
Victor Stinner15116802013-12-04 01:29:35 +0100601 return ptr2;
602 }
603
604 /* Ignore reentrant call. PyObjet_Realloc() calls PyMem_Realloc() for
605 allocations larger than 512 bytes. Don't trace the same memory
606 allocation twice. */
607 set_reentrant(1);
608
609 ptr2 = tracemalloc_realloc(ctx, ptr, new_size);
610
611 set_reentrant(0);
612 return ptr2;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100613}
614
615#ifdef TRACE_RAW_MALLOC
616static void*
617tracemalloc_raw_malloc(void *ctx, size_t size)
618{
Victor Stinner15116802013-12-04 01:29:35 +0100619#ifdef WITH_THREAD
620 PyGILState_STATE gil_state;
621#endif
622 void *ptr;
623
624 if (get_reentrant()) {
625 PyMemAllocator *alloc = (PyMemAllocator *)ctx;
626 return alloc->malloc(alloc->ctx, size);
627 }
628
629 /* Ignore reentrant call. PyGILState_Ensure() may call PyMem_RawMalloc()
630 indirectly which would call PyGILState_Ensure() if reentrant are not
631 disabled. */
632 set_reentrant(1);
633
634#ifdef WITH_THREAD
635 gil_state = PyGILState_Ensure();
636 ptr = tracemalloc_malloc(ctx, size);
637 PyGILState_Release(gil_state);
638#else
639 ptr = tracemalloc_malloc(ctx, size);
640#endif
641
642 set_reentrant(0);
643 return ptr;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100644}
645
646static void*
647tracemalloc_raw_realloc(void *ctx, void *ptr, size_t new_size)
648{
Victor Stinner15116802013-12-04 01:29:35 +0100649#ifdef WITH_THREAD
650 PyGILState_STATE gil_state;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100651#endif
Victor Stinner15116802013-12-04 01:29:35 +0100652 void *ptr2;
653
654 if (get_reentrant()) {
655 /* Reentrant call to PyMem_RawRealloc(). */
656 PyMemAllocator *alloc = (PyMemAllocator *)ctx;
657
658 ptr2 = alloc->realloc(alloc->ctx, ptr, new_size);
Victor Stinner15116802013-12-04 01:29:35 +0100659
Victor Stinner88c29872013-12-04 01:47:46 +0100660 if (ptr2 != NULL && ptr != NULL) {
661 TABLES_LOCK();
662 tracemalloc_remove_trace(ptr);
663 TABLES_UNLOCK();
664 }
Victor Stinner15116802013-12-04 01:29:35 +0100665 return ptr2;
666 }
667
668 /* Ignore reentrant call. PyGILState_Ensure() may call PyMem_RawMalloc()
669 indirectly which would call PyGILState_Ensure() if reentrant calls are
670 not disabled. */
671 set_reentrant(1);
672
673#ifdef WITH_THREAD
674 gil_state = PyGILState_Ensure();
675 ptr2 = tracemalloc_realloc(ctx, ptr, new_size);
676 PyGILState_Release(gil_state);
677#else
678 ptr2 = tracemalloc_realloc(ctx, ptr, new_size);
679#endif
680
681 set_reentrant(0);
682 return ptr2;
683}
684#endif /* TRACE_RAW_MALLOC */
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100685
686static int
687tracemalloc_clear_filename(_Py_hashtable_entry_t *entry, void *user_data)
688{
689 PyObject *filename = (PyObject *)entry->key;
690 Py_DECREF(filename);
691 return 0;
692}
693
694static int
695traceback_free_traceback(_Py_hashtable_entry_t *entry, void *user_data)
696{
697 traceback_t *traceback = (traceback_t *)entry->key;
698 raw_free(traceback);
699 return 0;
700}
701
702/* reentrant flag must be set to call this function and GIL must be held */
703static void
704tracemalloc_clear_traces(void)
705{
706#ifdef WITH_THREAD
707 /* The GIL protects variables againt concurrent access */
708 assert(PyGILState_Check());
709#endif
710
711 /* Disable also reentrant calls to tracemalloc_malloc() to not add a new
712 trace while we are clearing traces */
713 assert(get_reentrant());
714
715 TABLES_LOCK();
716 _Py_hashtable_clear(tracemalloc_traces);
717 tracemalloc_traced_memory = 0;
Victor Stinner3c0481d2013-11-27 21:39:49 +0100718 tracemalloc_peak_traced_memory = 0;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100719 TABLES_UNLOCK();
720
721 _Py_hashtable_foreach(tracemalloc_tracebacks, traceback_free_traceback, NULL);
722 _Py_hashtable_clear(tracemalloc_tracebacks);
723
724 _Py_hashtable_foreach(tracemalloc_filenames, tracemalloc_clear_filename, NULL);
725 _Py_hashtable_clear(tracemalloc_filenames);
726}
727
728static int
729tracemalloc_init(void)
730{
731 if (tracemalloc_config.initialized == TRACEMALLOC_FINALIZED) {
732 PyErr_SetString(PyExc_RuntimeError,
733 "the tracemalloc module has been unloaded");
734 return -1;
735 }
736
737 if (tracemalloc_config.initialized == TRACEMALLOC_INITIALIZED)
738 return 0;
739
740 PyMem_GetAllocator(PYMEM_DOMAIN_RAW, &allocators.raw);
741
742#ifdef REENTRANT_THREADLOCAL
743 tracemalloc_reentrant_key = PyThread_create_key();
744 if (tracemalloc_reentrant_key == -1) {
745#ifdef MS_WINDOWS
746 PyErr_SetFromWindowsErr(0);
747#else
748 PyErr_SetFromErrno(PyExc_OSError);
749#endif
750 return -1;
751 }
752#endif
753
754#if defined(WITH_THREAD) && defined(TRACE_RAW_MALLOC)
755 if (tables_lock == NULL) {
756 tables_lock = PyThread_allocate_lock();
757 if (tables_lock == NULL) {
758 PyErr_SetString(PyExc_RuntimeError, "cannot allocate lock");
759 return -1;
760 }
761 }
762#endif
763
764 tracemalloc_filenames = hashtable_new(0,
765 (_Py_hashtable_hash_func)PyObject_Hash,
766 hashtable_compare_unicode);
767
768 tracemalloc_tracebacks = hashtable_new(0,
769 (_Py_hashtable_hash_func)hashtable_hash_traceback,
770 (_Py_hashtable_compare_func)hashtable_compare_traceback);
771
772 tracemalloc_traces = hashtable_new(sizeof(trace_t),
773 _Py_hashtable_hash_ptr,
774 _Py_hashtable_compare_direct);
775
776 if (tracemalloc_filenames == NULL || tracemalloc_tracebacks == NULL
777 || tracemalloc_traces == NULL)
778 {
779 PyErr_NoMemory();
780 return -1;
781 }
782
783 unknown_filename = PyUnicode_FromString("<unknown>");
784 if (unknown_filename == NULL)
785 return -1;
786 PyUnicode_InternInPlace(&unknown_filename);
787
788 tracemalloc_empty_traceback.nframe = 1;
789 /* borrowed reference */
790 tracemalloc_empty_traceback.frames[0].filename = unknown_filename;
791 tracemalloc_empty_traceback.frames[0].lineno = 0;
792 tracemalloc_empty_traceback.hash = traceback_hash(&tracemalloc_empty_traceback);
793
794 /* Disable tracing allocations until hooks are installed. Set
795 also the reentrant flag to detect bugs: fail with an assertion error
796 if set_reentrant(1) is called while tracing is disabled. */
797 set_reentrant(1);
798
799 tracemalloc_config.initialized = TRACEMALLOC_INITIALIZED;
800 return 0;
801}
802
803static void
804tracemalloc_deinit(void)
805{
806 if (tracemalloc_config.initialized != TRACEMALLOC_INITIALIZED)
807 return;
808 tracemalloc_config.initialized = TRACEMALLOC_FINALIZED;
809
810 tracemalloc_stop();
811
812 /* destroy hash tables */
813 _Py_hashtable_destroy(tracemalloc_traces);
814 _Py_hashtable_destroy(tracemalloc_tracebacks);
815 _Py_hashtable_destroy(tracemalloc_filenames);
816
817#if defined(WITH_THREAD) && defined(TRACE_RAW_MALLOC)
818 if (tables_lock != NULL) {
819 PyThread_free_lock(tables_lock);
820 tables_lock = NULL;
821 }
822#endif
823
824#ifdef REENTRANT_THREADLOCAL
825 PyThread_delete_key(tracemalloc_reentrant_key);
826#endif
827
828 Py_XDECREF(unknown_filename);
829}
830
831static int
Victor Stinnerf28ce602013-11-27 22:27:13 +0100832tracemalloc_start(int max_nframe)
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100833{
834 PyMemAllocator alloc;
Victor Stinnerf28ce602013-11-27 22:27:13 +0100835 size_t size;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100836
837 if (tracemalloc_init() < 0)
838 return -1;
839
840 if (tracemalloc_config.tracing) {
841 /* hook already installed: do nothing */
842 return 0;
843 }
844
Victor Stinnerf28ce602013-11-27 22:27:13 +0100845 assert(1 <= max_nframe && max_nframe <= MAX_NFRAME);
846 tracemalloc_config.max_nframe = max_nframe;
847
848 /* allocate a buffer to store a new traceback */
849 size = TRACEBACK_SIZE(max_nframe);
850 assert(tracemalloc_traceback == NULL);
851 tracemalloc_traceback = raw_malloc(size);
852 if (tracemalloc_traceback == NULL) {
853 PyErr_NoMemory();
854 return -1;
855 }
856
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100857#ifdef TRACE_RAW_MALLOC
858 alloc.malloc = tracemalloc_raw_malloc;
859 alloc.realloc = tracemalloc_raw_realloc;
860 alloc.free = tracemalloc_free;
861
862 alloc.ctx = &allocators.raw;
863 PyMem_GetAllocator(PYMEM_DOMAIN_RAW, &allocators.raw);
864 PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &alloc);
865#endif
866
867 alloc.malloc = tracemalloc_malloc_gil;
868 alloc.realloc = tracemalloc_realloc_gil;
869 alloc.free = tracemalloc_free;
870
871 alloc.ctx = &allocators.mem;
872 PyMem_GetAllocator(PYMEM_DOMAIN_MEM, &allocators.mem);
873 PyMem_SetAllocator(PYMEM_DOMAIN_MEM, &alloc);
874
875 alloc.ctx = &allocators.obj;
876 PyMem_GetAllocator(PYMEM_DOMAIN_OBJ, &allocators.obj);
877 PyMem_SetAllocator(PYMEM_DOMAIN_OBJ, &alloc);
878
879 /* everything is ready: start tracing Python memory allocations */
880 tracemalloc_config.tracing = 1;
881 set_reentrant(0);
882
883 return 0;
884}
885
886static void
887tracemalloc_stop(void)
888{
889 if (!tracemalloc_config.tracing)
890 return;
891
892 /* stop tracing Python memory allocations */
893 tracemalloc_config.tracing = 0;
894
895 /* set the reentrant flag to detect bugs: fail with an assertion error if
896 set_reentrant(1) is called while tracing is disabled. */
897 set_reentrant(1);
898
899 /* unregister the hook on memory allocators */
900#ifdef TRACE_RAW_MALLOC
901 PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &allocators.raw);
902#endif
903 PyMem_SetAllocator(PYMEM_DOMAIN_MEM, &allocators.mem);
904 PyMem_SetAllocator(PYMEM_DOMAIN_OBJ, &allocators.obj);
905
906 /* release memory */
907 tracemalloc_clear_traces();
Victor Stinnerf28ce602013-11-27 22:27:13 +0100908 raw_free(tracemalloc_traceback);
909 tracemalloc_traceback = NULL;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100910}
911
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100912static PyObject*
913lineno_as_obj(int lineno)
914{
915 if (lineno >= 0)
916 return PyLong_FromLong(lineno);
917 else
918 Py_RETURN_NONE;
919}
920
921PyDoc_STRVAR(tracemalloc_is_tracing_doc,
922 "is_tracing()->bool\n"
923 "\n"
924 "True if the tracemalloc module is tracing Python memory allocations,\n"
925 "False otherwise.");
926
927static PyObject*
928py_tracemalloc_is_tracing(PyObject *self)
929{
930 return PyBool_FromLong(tracemalloc_config.tracing);
931}
932
933PyDoc_STRVAR(tracemalloc_clear_traces_doc,
934 "clear_traces()\n"
935 "\n"
936 "Clear traces of memory blocks allocated by Python.");
937
938static PyObject*
939py_tracemalloc_clear_traces(PyObject *self)
940{
941 if (!tracemalloc_config.tracing)
942 Py_RETURN_NONE;
943
944 set_reentrant(1);
945 tracemalloc_clear_traces();
946 set_reentrant(0);
947
948 Py_RETURN_NONE;
949}
950
951static PyObject*
952frame_to_pyobject(frame_t *frame)
953{
954 PyObject *frame_obj, *lineno_obj;
955
956 frame_obj = PyTuple_New(2);
957 if (frame_obj == NULL)
958 return NULL;
959
960 if (frame->filename == NULL)
961 frame->filename = Py_None;
962 Py_INCREF(frame->filename);
963 PyTuple_SET_ITEM(frame_obj, 0, frame->filename);
964
965 assert(frame->lineno >= 0);
966 lineno_obj = lineno_as_obj(frame->lineno);
967 if (lineno_obj == NULL) {
968 Py_DECREF(frame_obj);
969 return NULL;
970 }
971 PyTuple_SET_ITEM(frame_obj, 1, lineno_obj);
972
973 return frame_obj;
974}
975
976static PyObject*
977traceback_to_pyobject(traceback_t *traceback, _Py_hashtable_t *intern_table)
978{
979 int i;
980 PyObject *frames, *frame;
981
982 if (intern_table != NULL) {
983 if (_Py_HASHTABLE_GET(intern_table, traceback, frames)) {
984 Py_INCREF(frames);
985 return frames;
986 }
987 }
988
989 frames = PyTuple_New(traceback->nframe);
990 if (frames == NULL)
991 return NULL;
992
993 for (i=0; i < traceback->nframe; i++) {
994 frame = frame_to_pyobject(&traceback->frames[i]);
995 if (frame == NULL) {
996 Py_DECREF(frames);
997 return NULL;
998 }
999 PyTuple_SET_ITEM(frames, i, frame);
1000 }
1001
1002 if (intern_table != NULL) {
1003 if (_Py_HASHTABLE_SET(intern_table, traceback, frames) < 0) {
1004 Py_DECREF(frames);
1005 PyErr_NoMemory();
1006 return NULL;
1007 }
1008 /* intern_table keeps a new reference to frames */
1009 Py_INCREF(frames);
1010 }
1011 return frames;
1012}
1013
1014static PyObject*
1015trace_to_pyobject(trace_t *trace, _Py_hashtable_t *intern_tracebacks)
1016{
1017 PyObject *trace_obj = NULL;
1018 PyObject *size, *traceback;
1019
1020 trace_obj = PyTuple_New(2);
1021 if (trace_obj == NULL)
1022 return NULL;
1023
1024 size = PyLong_FromSize_t(trace->size);
1025 if (size == NULL) {
1026 Py_DECREF(trace_obj);
1027 return NULL;
1028 }
1029 PyTuple_SET_ITEM(trace_obj, 0, size);
1030
1031 traceback = traceback_to_pyobject(trace->traceback, intern_tracebacks);
1032 if (traceback == NULL) {
1033 Py_DECREF(trace_obj);
1034 return NULL;
1035 }
1036 PyTuple_SET_ITEM(trace_obj, 1, traceback);
1037
1038 return trace_obj;
1039}
1040
1041typedef struct {
1042 _Py_hashtable_t *traces;
1043 _Py_hashtable_t *tracebacks;
1044 PyObject *list;
1045} get_traces_t;
1046
1047static int
1048tracemalloc_get_traces_fill(_Py_hashtable_entry_t *entry, void *user_data)
1049{
1050 get_traces_t *get_traces = user_data;
1051 trace_t *trace;
1052 PyObject *tracemalloc_obj;
1053 int res;
1054
Victor Stinnerd9a73522014-03-24 22:34:34 +01001055 trace = (trace_t *)_Py_HASHTABLE_ENTRY_DATA(entry);
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001056
1057 tracemalloc_obj = trace_to_pyobject(trace, get_traces->tracebacks);
1058 if (tracemalloc_obj == NULL)
1059 return 1;
1060
1061 res = PyList_Append(get_traces->list, tracemalloc_obj);
1062 Py_DECREF(tracemalloc_obj);
1063 if (res < 0)
1064 return 1;
1065
1066 return 0;
1067}
1068
1069static int
1070tracemalloc_pyobject_decref_cb(_Py_hashtable_entry_t *entry, void *user_data)
1071{
1072 PyObject *obj = (PyObject *)_Py_HASHTABLE_ENTRY_DATA_AS_VOID_P(entry);
1073 Py_DECREF(obj);
1074 return 0;
1075}
1076
1077PyDoc_STRVAR(tracemalloc_get_traces_doc,
Victor Stinner4fbefdb2013-11-25 09:33:18 +01001078 "_get_traces() -> list\n"
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001079 "\n"
1080 "Get traces of all memory blocks allocated by Python.\n"
1081 "Return a list of (size: int, traceback: tuple) tuples.\n"
1082 "traceback is a tuple of (filename: str, lineno: int) tuples.\n"
1083 "\n"
1084 "Return an empty list if the tracemalloc module is disabled.");
1085
1086static PyObject*
1087py_tracemalloc_get_traces(PyObject *self, PyObject *obj)
1088{
1089 get_traces_t get_traces;
1090 int err;
1091
1092 get_traces.traces = NULL;
1093 get_traces.tracebacks = NULL;
1094 get_traces.list = PyList_New(0);
1095 if (get_traces.list == NULL)
1096 goto error;
1097
1098 if (!tracemalloc_config.tracing)
1099 return get_traces.list;
1100
Victor Stinnerde2f1322013-11-26 00:26:23 +01001101 /* the traceback hash table is used temporarily to intern traceback tuple
1102 of (filename, lineno) tuples */
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001103 get_traces.tracebacks = hashtable_new(sizeof(PyObject *),
1104 _Py_hashtable_hash_ptr,
1105 _Py_hashtable_compare_direct);
1106 if (get_traces.tracebacks == NULL) {
1107 PyErr_NoMemory();
1108 goto error;
1109 }
1110
1111 TABLES_LOCK();
1112 get_traces.traces = _Py_hashtable_copy(tracemalloc_traces);
1113 TABLES_UNLOCK();
1114
1115 if (get_traces.traces == NULL) {
1116 PyErr_NoMemory();
1117 goto error;
1118 }
1119
1120 set_reentrant(1);
1121 err = _Py_hashtable_foreach(get_traces.traces,
1122 tracemalloc_get_traces_fill, &get_traces);
1123 set_reentrant(0);
1124 if (err)
1125 goto error;
1126
1127 goto finally;
1128
1129error:
1130 Py_CLEAR(get_traces.list);
1131
1132finally:
1133 if (get_traces.tracebacks != NULL) {
1134 _Py_hashtable_foreach(get_traces.tracebacks,
1135 tracemalloc_pyobject_decref_cb, NULL);
1136 _Py_hashtable_destroy(get_traces.tracebacks);
1137 }
1138 if (get_traces.traces != NULL)
1139 _Py_hashtable_destroy(get_traces.traces);
1140
1141 return get_traces.list;
1142}
1143
1144PyDoc_STRVAR(tracemalloc_get_object_traceback_doc,
Victor Stinner4fbefdb2013-11-25 09:33:18 +01001145 "_get_object_traceback(obj)\n"
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001146 "\n"
1147 "Get the traceback where the Python object obj was allocated.\n"
1148 "Return a tuple of (filename: str, lineno: int) tuples.\n"
1149 "\n"
1150 "Return None if the tracemalloc module is disabled or did not\n"
1151 "trace the allocation of the object.");
1152
1153static PyObject*
1154py_tracemalloc_get_object_traceback(PyObject *self, PyObject *obj)
1155{
1156 PyTypeObject *type;
1157 void *ptr;
1158 trace_t trace;
1159 int found;
1160
1161 if (!tracemalloc_config.tracing)
1162 Py_RETURN_NONE;
1163
1164 type = Py_TYPE(obj);
1165 if (PyType_IS_GC(type))
1166 ptr = (void *)((char *)obj - sizeof(PyGC_Head));
1167 else
1168 ptr = (void *)obj;
1169
1170 TABLES_LOCK();
1171 found = _Py_HASHTABLE_GET(tracemalloc_traces, ptr, trace);
1172 TABLES_UNLOCK();
1173
1174 if (!found)
1175 Py_RETURN_NONE;
1176
1177 return traceback_to_pyobject(trace.traceback, NULL);
1178}
1179
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001180PyDoc_STRVAR(tracemalloc_start_doc,
Victor Stinner3728d6c2013-11-23 12:37:20 +01001181 "start(nframe: int=1)\n"
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001182 "\n"
Victor Stinner3728d6c2013-11-23 12:37:20 +01001183 "Start tracing Python memory allocations. Set also the maximum number \n"
1184 "of frames stored in the traceback of a trace to nframe.");
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001185
1186static PyObject*
Victor Stinner3728d6c2013-11-23 12:37:20 +01001187py_tracemalloc_start(PyObject *self, PyObject *args)
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001188{
Victor Stinner3728d6c2013-11-23 12:37:20 +01001189 Py_ssize_t nframe = 1;
Victor Stinnerf28ce602013-11-27 22:27:13 +01001190 int nframe_int;
Victor Stinner3728d6c2013-11-23 12:37:20 +01001191
1192 if (!PyArg_ParseTuple(args, "|n:start", &nframe))
1193 return NULL;
1194
1195 if (nframe < 1 || nframe > MAX_NFRAME) {
1196 PyErr_Format(PyExc_ValueError,
1197 "the number of frames must be in range [1; %i]",
Victor Stinnerf28ce602013-11-27 22:27:13 +01001198 (int)MAX_NFRAME);
Victor Stinner3728d6c2013-11-23 12:37:20 +01001199 return NULL;
1200 }
Victor Stinnerf28ce602013-11-27 22:27:13 +01001201 nframe_int = Py_SAFE_DOWNCAST(nframe, Py_ssize_t, int);
Victor Stinner3728d6c2013-11-23 12:37:20 +01001202
Victor Stinnerf28ce602013-11-27 22:27:13 +01001203 if (tracemalloc_start(nframe_int) < 0)
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001204 return NULL;
1205
1206 Py_RETURN_NONE;
1207}
1208
1209PyDoc_STRVAR(tracemalloc_stop_doc,
1210 "stop()\n"
1211 "\n"
1212 "Stop tracing Python memory allocations and clear traces\n"
1213 "of memory blocks allocated by Python.");
1214
1215static PyObject*
1216py_tracemalloc_stop(PyObject *self)
1217{
1218 tracemalloc_stop();
1219 Py_RETURN_NONE;
1220}
1221
1222PyDoc_STRVAR(tracemalloc_get_traceback_limit_doc,
1223 "get_traceback_limit() -> int\n"
1224 "\n"
1225 "Get the maximum number of frames stored in the traceback\n"
1226 "of a trace.\n"
1227 "\n"
1228 "By default, a trace of an allocated memory block only stores\n"
1229 "the most recent frame: the limit is 1.");
1230
1231static PyObject*
1232py_tracemalloc_get_traceback_limit(PyObject *self)
1233{
1234 return PyLong_FromLong(tracemalloc_config.max_nframe);
1235}
1236
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001237PyDoc_STRVAR(tracemalloc_get_tracemalloc_memory_doc,
1238 "get_tracemalloc_memory() -> int\n"
1239 "\n"
1240 "Get the memory usage in bytes of the tracemalloc module\n"
1241 "used internally to trace memory allocations.");
1242
1243static PyObject*
1244tracemalloc_get_tracemalloc_memory(PyObject *self)
1245{
1246 size_t size;
1247 PyObject *size_obj;
1248
1249 size = _Py_hashtable_size(tracemalloc_tracebacks);
1250 size += _Py_hashtable_size(tracemalloc_filenames);
1251
1252 TABLES_LOCK();
1253 size += _Py_hashtable_size(tracemalloc_traces);
1254 TABLES_UNLOCK();
1255
1256 size_obj = PyLong_FromSize_t(size);
1257 return Py_BuildValue("N", size_obj);
1258}
1259
1260PyDoc_STRVAR(tracemalloc_get_traced_memory_doc,
Victor Stinner59463d82013-11-26 10:46:06 +01001261 "get_traced_memory() -> (int, int)\n"
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001262 "\n"
Victor Stinner3c0481d2013-11-27 21:39:49 +01001263 "Get the current size and peak size of memory blocks traced\n"
1264 "by the tracemalloc module as a tuple: (current: int, peak: int).");
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001265
1266static PyObject*
1267tracemalloc_get_traced_memory(PyObject *self)
1268{
Victor Stinner3c0481d2013-11-27 21:39:49 +01001269 Py_ssize_t size, peak_size;
1270 PyObject *size_obj, *peak_size_obj;
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001271
1272 if (!tracemalloc_config.tracing)
1273 return Py_BuildValue("ii", 0, 0);
1274
1275 TABLES_LOCK();
1276 size = tracemalloc_traced_memory;
Victor Stinner3c0481d2013-11-27 21:39:49 +01001277 peak_size = tracemalloc_peak_traced_memory;
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001278 TABLES_UNLOCK();
1279
1280 size_obj = PyLong_FromSize_t(size);
Victor Stinner3c0481d2013-11-27 21:39:49 +01001281 peak_size_obj = PyLong_FromSize_t(peak_size);
1282 return Py_BuildValue("NN", size_obj, peak_size_obj);
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001283}
1284
1285static PyMethodDef module_methods[] = {
1286 {"is_tracing", (PyCFunction)py_tracemalloc_is_tracing,
1287 METH_NOARGS, tracemalloc_is_tracing_doc},
1288 {"clear_traces", (PyCFunction)py_tracemalloc_clear_traces,
1289 METH_NOARGS, tracemalloc_clear_traces_doc},
1290 {"_get_traces", (PyCFunction)py_tracemalloc_get_traces,
1291 METH_NOARGS, tracemalloc_get_traces_doc},
1292 {"_get_object_traceback", (PyCFunction)py_tracemalloc_get_object_traceback,
1293 METH_O, tracemalloc_get_object_traceback_doc},
1294 {"start", (PyCFunction)py_tracemalloc_start,
Victor Stinner3728d6c2013-11-23 12:37:20 +01001295 METH_VARARGS, tracemalloc_start_doc},
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001296 {"stop", (PyCFunction)py_tracemalloc_stop,
1297 METH_NOARGS, tracemalloc_stop_doc},
1298 {"get_traceback_limit", (PyCFunction)py_tracemalloc_get_traceback_limit,
1299 METH_NOARGS, tracemalloc_get_traceback_limit_doc},
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001300 {"get_tracemalloc_memory", (PyCFunction)tracemalloc_get_tracemalloc_memory,
1301 METH_NOARGS, tracemalloc_get_tracemalloc_memory_doc},
1302 {"get_traced_memory", (PyCFunction)tracemalloc_get_traced_memory,
1303 METH_NOARGS, tracemalloc_get_traced_memory_doc},
1304
1305 /* sentinel */
1306 {NULL, NULL}
1307};
1308
1309PyDoc_STRVAR(module_doc,
1310"Debug module to trace memory blocks allocated by Python.");
1311
1312static struct PyModuleDef module_def = {
1313 PyModuleDef_HEAD_INIT,
1314 "_tracemalloc",
1315 module_doc,
1316 0, /* non-negative size to be able to unload the module */
1317 module_methods,
1318 NULL,
1319};
1320
1321PyMODINIT_FUNC
1322PyInit__tracemalloc(void)
1323{
1324 PyObject *m;
1325 m = PyModule_Create(&module_def);
1326 if (m == NULL)
1327 return NULL;
1328
1329 if (tracemalloc_init() < 0)
1330 return NULL;
1331
1332 return m;
1333}
1334
1335static int
1336parse_sys_xoptions(PyObject *value)
1337{
1338 PyObject *valuelong;
1339 long nframe;
1340
1341 if (value == Py_True)
1342 return 1;
1343
1344 assert(PyUnicode_Check(value));
1345 if (PyUnicode_GetLength(value) == 0)
1346 return -1;
1347
1348 valuelong = PyLong_FromUnicodeObject(value, 10);
1349 if (valuelong == NULL)
1350 return -1;
1351
1352 nframe = PyLong_AsLong(valuelong);
1353 Py_DECREF(valuelong);
1354 if (nframe == -1 && PyErr_Occurred())
1355 return -1;
1356
1357 if (nframe < 1 || nframe > MAX_NFRAME)
1358 return -1;
1359
1360 return Py_SAFE_DOWNCAST(nframe, long, int);
1361}
1362
1363int
1364_PyTraceMalloc_Init(void)
1365{
1366 char *p;
1367 int nframe;
1368
1369#ifdef WITH_THREAD
1370 assert(PyGILState_Check());
1371#endif
1372
1373 if ((p = Py_GETENV("PYTHONTRACEMALLOC")) && *p != '\0') {
1374 char *endptr = p;
Victor Stinnerf28ce602013-11-27 22:27:13 +01001375 long value;
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001376
Victor Stinner711e27c2013-12-16 23:06:19 +01001377 errno = 0;
Victor Stinnerf28ce602013-11-27 22:27:13 +01001378 value = strtol(p, &endptr, 10);
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001379 if (*endptr != '\0'
1380 || value < 1
1381 || value > MAX_NFRAME
Victor Stinner711e27c2013-12-16 23:06:19 +01001382 || errno == ERANGE)
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001383 {
Victor Stinnerf28ce602013-11-27 22:27:13 +01001384 Py_FatalError("PYTHONTRACEMALLOC: invalid number of frames");
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001385 return -1;
1386 }
1387
1388 nframe = (int)value;
1389 }
1390 else {
1391 PyObject *xoptions, *key, *value;
1392
1393 xoptions = PySys_GetXOptions();
1394 if (xoptions == NULL)
1395 return -1;
1396
1397 key = PyUnicode_FromString("tracemalloc");
1398 if (key == NULL)
1399 return -1;
1400
1401 value = PyDict_GetItemWithError(xoptions, key);
1402 Py_DECREF(key);
1403 if (value == NULL) {
1404 if (PyErr_Occurred())
1405 return -1;
1406
1407 /* -X tracemalloc is not used */
1408 return 0;
1409 }
1410
1411 nframe = parse_sys_xoptions(value);
1412 Py_DECREF(value);
1413 if (nframe < 0) {
Victor Stinnerf28ce602013-11-27 22:27:13 +01001414 Py_FatalError("-X tracemalloc=NFRAME: invalid number of frames");
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001415 }
1416 }
1417
Victor Stinnerf28ce602013-11-27 22:27:13 +01001418 return tracemalloc_start(nframe);
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001419}
1420
Victor Stinnerbe0708f2013-12-01 10:03:26 +01001421void
1422_PyTraceMalloc_Fini(void)
1423{
1424#ifdef WITH_THREAD
1425 assert(PyGILState_Check());
1426#endif
1427 tracemalloc_deinit();
1428}
1429