blob: 7e6113dc1ae20596b5afd513256c3991c887894e [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);
Victor Stinner590cebe2013-12-13 11:08:56 +0100171 PyThread_set_key_value(tracemalloc_reentrant_key, REENTRANT);
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100172 }
173 else {
Victor Stinner590cebe2013-12-13 11:08:56 +0100174 assert(PyThread_get_key_value(tracemalloc_reentrant_key) == REENTRANT);
175 PyThread_set_key_value(tracemalloc_reentrant_key, NULL);
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100176 }
177}
178
179#else
180
181/* WITH_THREAD not defined: Python compiled without threads,
182 or TRACE_RAW_MALLOC not defined: variable protected by the GIL */
183static int tracemalloc_reentrant = 0;
184
185static int
186get_reentrant(void)
187{
188 return tracemalloc_reentrant;
189}
190
191static void
192set_reentrant(int reentrant)
193{
194 assert(!reentrant || !get_reentrant());
195 tracemalloc_reentrant = reentrant;
196}
197#endif
198
199static int
200hashtable_compare_unicode(const void *key, const _Py_hashtable_entry_t *entry)
201{
202 if (key != NULL && entry->key != NULL)
203 return (PyUnicode_Compare((PyObject *)key, (PyObject *)entry->key) == 0);
204 else
205 return key == entry->key;
206}
207
208static _Py_hashtable_allocator_t hashtable_alloc = {malloc, free};
209
210static _Py_hashtable_t *
211hashtable_new(size_t data_size,
212 _Py_hashtable_hash_func hash_func,
213 _Py_hashtable_compare_func compare_func)
214{
215 return _Py_hashtable_new_full(data_size, 0,
216 hash_func, compare_func,
217 NULL, NULL, NULL, &hashtable_alloc);
218}
219
220static void*
221raw_malloc(size_t size)
222{
223 return allocators.raw.malloc(allocators.raw.ctx, size);
224}
225
226static void
227raw_free(void *ptr)
228{
229 allocators.raw.free(allocators.raw.ctx, ptr);
230}
231
232static Py_uhash_t
233hashtable_hash_traceback(const void *key)
234{
235 const traceback_t *traceback = key;
236 return traceback->hash;
237}
238
239static int
240hashtable_compare_traceback(const traceback_t *traceback1,
241 const _Py_hashtable_entry_t *he)
242{
243 const traceback_t *traceback2 = he->key;
244 const frame_t *frame1, *frame2;
245 int i;
246
247 if (traceback1->nframe != traceback2->nframe)
248 return 0;
249
250 for (i=0; i < traceback1->nframe; i++) {
251 frame1 = &traceback1->frames[i];
252 frame2 = &traceback2->frames[i];
253
254 if (frame1->lineno != frame2->lineno)
255 return 0;
256
257 if (frame1->filename != frame2->filename) {
258 assert(PyUnicode_Compare(frame1->filename, frame2->filename) != 0);
259 return 0;
260 }
261 }
262 return 1;
263}
264
265static void
266tracemalloc_get_frame(PyFrameObject *pyframe, frame_t *frame)
267{
268 PyCodeObject *code;
269 PyObject *filename;
270 _Py_hashtable_entry_t *entry;
271
272 frame->filename = unknown_filename;
273 frame->lineno = PyFrame_GetLineNumber(pyframe);
274 assert(frame->lineno >= 0);
275 if (frame->lineno < 0)
276 frame->lineno = 0;
277
278 code = pyframe->f_code;
279 if (code == NULL) {
280#ifdef TRACE_DEBUG
Victor Stinner4dc74202013-11-26 01:18:52 +0100281 tracemalloc_error("failed to get the code object of the frame");
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100282#endif
283 return;
284 }
285
286 if (code->co_filename == NULL) {
287#ifdef TRACE_DEBUG
288 tracemalloc_error("failed to get the filename of the code object");
289#endif
290 return;
291 }
292
293 filename = code->co_filename;
294 assert(filename != NULL);
295 if (filename == NULL)
296 return;
297
298 if (!PyUnicode_Check(filename)) {
299#ifdef TRACE_DEBUG
300 tracemalloc_error("filename is not an unicode string");
301#endif
302 return;
303 }
304 if (!PyUnicode_IS_READY(filename)) {
305 /* Don't make a Unicode string ready to avoid reentrant calls
306 to tracemalloc_malloc() or tracemalloc_realloc() */
307#ifdef TRACE_DEBUG
308 tracemalloc_error("filename is not a ready unicode string");
309#endif
310 return;
311 }
312
313 /* intern the filename */
314 entry = _Py_hashtable_get_entry(tracemalloc_filenames, filename);
315 if (entry != NULL) {
316 filename = (PyObject *)entry->key;
317 }
318 else {
319 /* tracemalloc_filenames is responsible to keep a reference
320 to the filename */
321 Py_INCREF(filename);
322 if (_Py_hashtable_set(tracemalloc_filenames, filename, NULL, 0) < 0) {
323 Py_DECREF(filename);
324#ifdef TRACE_DEBUG
325 tracemalloc_error("failed to intern the filename");
326#endif
327 return;
328 }
329 }
330
331 /* the tracemalloc_filenames table keeps a reference to the filename */
332 frame->filename = filename;
333}
334
335static Py_uhash_t
336traceback_hash(traceback_t *traceback)
337{
338 /* code based on tuplehash() of Objects/tupleobject.c */
Victor Stinner4d8c29c2013-12-16 23:05:13 +0100339 Py_uhash_t x, y; /* Unsigned for defined overflow behavior. */
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100340 int len = traceback->nframe;
341 Py_uhash_t mult = _PyHASH_MULTIPLIER;
342 frame_t *frame;
343
344 x = 0x345678UL;
345 frame = traceback->frames;
346 while (--len >= 0) {
Victor Stinner4d8c29c2013-12-16 23:05:13 +0100347 y = (Py_uhash_t)PyObject_Hash(frame->filename);
348 y ^= (Py_uhash_t)frame->lineno;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100349 frame++;
350
351 x = (x ^ y) * mult;
352 /* the cast might truncate len; that doesn't change hash stability */
Victor Stinner4d8c29c2013-12-16 23:05:13 +0100353 mult += (Py_uhash_t)(82520UL + len + len);
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100354 }
355 x += 97531UL;
356 return x;
357}
358
359static void
360traceback_get_frames(traceback_t *traceback)
361{
362 PyThreadState *tstate;
363 PyFrameObject *pyframe;
364
365#ifdef WITH_THREAD
366 tstate = PyGILState_GetThisThreadState();
367#else
368 tstate = PyThreadState_Get();
369#endif
370 if (tstate == NULL) {
371#ifdef TRACE_DEBUG
372 tracemalloc_error("failed to get the current thread state");
373#endif
374 return;
375 }
376
377 for (pyframe = tstate->frame; pyframe != NULL; pyframe = pyframe->f_back) {
378 tracemalloc_get_frame(pyframe, &traceback->frames[traceback->nframe]);
379 assert(traceback->frames[traceback->nframe].filename != NULL);
380 assert(traceback->frames[traceback->nframe].lineno >= 0);
381 traceback->nframe++;
382 if (traceback->nframe == tracemalloc_config.max_nframe)
383 break;
384 }
385}
386
387static traceback_t *
388traceback_new(void)
389{
Victor Stinnerf28ce602013-11-27 22:27:13 +0100390 traceback_t *traceback;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100391 _Py_hashtable_entry_t *entry;
392
393#ifdef WITH_THREAD
394 assert(PyGILState_Check());
395#endif
396
397 /* get frames */
Victor Stinnerf28ce602013-11-27 22:27:13 +0100398 traceback = tracemalloc_traceback;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100399 traceback->nframe = 0;
400 traceback_get_frames(traceback);
401 if (traceback->nframe == 0)
402 return &tracemalloc_empty_traceback;
403 traceback->hash = traceback_hash(traceback);
404
405 /* intern the traceback */
406 entry = _Py_hashtable_get_entry(tracemalloc_tracebacks, traceback);
407 if (entry != NULL) {
408 traceback = (traceback_t *)entry->key;
409 }
410 else {
411 traceback_t *copy;
412 size_t traceback_size;
413
414 traceback_size = TRACEBACK_SIZE(traceback->nframe);
415
416 copy = raw_malloc(traceback_size);
417 if (copy == NULL) {
418#ifdef TRACE_DEBUG
419 tracemalloc_error("failed to intern the traceback: malloc failed");
420#endif
421 return NULL;
422 }
423 memcpy(copy, traceback, traceback_size);
424
425 if (_Py_hashtable_set(tracemalloc_tracebacks, copy, NULL, 0) < 0) {
426 raw_free(copy);
427#ifdef TRACE_DEBUG
428 tracemalloc_error("failed to intern the traceback: putdata failed");
429#endif
430 return NULL;
431 }
432 traceback = copy;
433 }
434 return traceback;
435}
436
Victor Stinner52968672013-11-24 11:37:15 +0100437static int
Victor Stinner15116802013-12-04 01:29:35 +0100438tracemalloc_add_trace(void *ptr, size_t size)
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100439{
440 traceback_t *traceback;
441 trace_t trace;
Victor Stinner52968672013-11-24 11:37:15 +0100442 int res;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100443
444#ifdef WITH_THREAD
445 assert(PyGILState_Check());
446#endif
447
448 traceback = traceback_new();
Victor Stinner52968672013-11-24 11:37:15 +0100449 if (traceback == NULL)
450 return -1;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100451
452 trace.size = size;
453 trace.traceback = traceback;
454
Victor Stinner52968672013-11-24 11:37:15 +0100455 res = _Py_HASHTABLE_SET(tracemalloc_traces, ptr, trace);
456 if (res == 0) {
Victor Stinnerd606ba72013-11-24 11:28:20 +0100457 assert(tracemalloc_traced_memory <= PY_SIZE_MAX - size);
458 tracemalloc_traced_memory += size;
Victor Stinner3c0481d2013-11-27 21:39:49 +0100459 if (tracemalloc_traced_memory > tracemalloc_peak_traced_memory)
460 tracemalloc_peak_traced_memory = tracemalloc_traced_memory;
Victor Stinnerd606ba72013-11-24 11:28:20 +0100461 }
Victor Stinner52968672013-11-24 11:37:15 +0100462
463 return res;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100464}
465
466static void
Victor Stinner15116802013-12-04 01:29:35 +0100467tracemalloc_remove_trace(void *ptr)
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100468{
469 trace_t trace;
470
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100471 if (_Py_hashtable_pop(tracemalloc_traces, ptr, &trace, sizeof(trace))) {
472 assert(tracemalloc_traced_memory >= trace.size);
473 tracemalloc_traced_memory -= trace.size;
474 }
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100475}
476
477static void*
Victor Stinner15116802013-12-04 01:29:35 +0100478tracemalloc_malloc(void *ctx, size_t size)
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100479{
480 PyMemAllocator *alloc = (PyMemAllocator *)ctx;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100481 void *ptr;
482
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100483 ptr = alloc->malloc(alloc->ctx, size);
Victor Stinner15116802013-12-04 01:29:35 +0100484 if (ptr == NULL)
485 return NULL;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100486
Victor Stinner88c29872013-12-04 01:47:46 +0100487 TABLES_LOCK();
Victor Stinner15116802013-12-04 01:29:35 +0100488 if (tracemalloc_add_trace(ptr, size) < 0) {
489 /* Failed to allocate a trace for the new memory block */
Victor Stinner88c29872013-12-04 01:47:46 +0100490 TABLES_UNLOCK();
Victor Stinner15116802013-12-04 01:29:35 +0100491 alloc->free(alloc->ctx, ptr);
492 return NULL;
Victor Stinner52968672013-11-24 11:37:15 +0100493 }
Victor Stinner88c29872013-12-04 01:47:46 +0100494 TABLES_UNLOCK();
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100495 return ptr;
496}
497
498static void*
Victor Stinner15116802013-12-04 01:29:35 +0100499tracemalloc_realloc(void *ctx, void *ptr, size_t new_size)
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100500{
501 PyMemAllocator *alloc = (PyMemAllocator *)ctx;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100502 void *ptr2;
503
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100504 ptr2 = alloc->realloc(alloc->ctx, ptr, new_size);
Victor Stinner15116802013-12-04 01:29:35 +0100505 if (ptr2 == NULL)
506 return NULL;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100507
Victor Stinner15116802013-12-04 01:29:35 +0100508 if (ptr != NULL) {
509 /* an existing memory block has been resized */
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100510
Victor Stinner88c29872013-12-04 01:47:46 +0100511 TABLES_LOCK();
Victor Stinner15116802013-12-04 01:29:35 +0100512 tracemalloc_remove_trace(ptr);
Victor Stinner08facd22013-11-24 12:27:59 +0100513
Victor Stinner15116802013-12-04 01:29:35 +0100514 if (tracemalloc_add_trace(ptr2, new_size) < 0) {
515 /* Memory allocation failed. The error cannot be reported to
516 the caller, because realloc() may already have shrinked the
517 memory block and so removed bytes.
518
Victor Stinner88c29872013-12-04 01:47:46 +0100519 This case is very unlikely: an hash entry has just been
520 released, so the hash table should have at least one free entry.
521
522 The GIL and the table lock ensures that only one thread is
523 allocating memory. */
524 assert(0 && "should never happen");
Victor Stinner52968672013-11-24 11:37:15 +0100525 }
Victor Stinner88c29872013-12-04 01:47:46 +0100526 TABLES_UNLOCK();
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100527 }
Victor Stinner15116802013-12-04 01:29:35 +0100528 else {
529 /* new allocation */
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100530
Victor Stinner88c29872013-12-04 01:47:46 +0100531 TABLES_LOCK();
Victor Stinner15116802013-12-04 01:29:35 +0100532 if (tracemalloc_add_trace(ptr2, new_size) < 0) {
533 /* Failed to allocate a trace for the new memory block */
Victor Stinner88c29872013-12-04 01:47:46 +0100534 TABLES_UNLOCK();
Victor Stinner15116802013-12-04 01:29:35 +0100535 alloc->free(alloc->ctx, ptr2);
536 return NULL;
537 }
Victor Stinner88c29872013-12-04 01:47:46 +0100538 TABLES_UNLOCK();
Victor Stinner15116802013-12-04 01:29:35 +0100539 }
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100540 return ptr2;
541}
542
543static void
544tracemalloc_free(void *ctx, void *ptr)
545{
546 PyMemAllocator *alloc = (PyMemAllocator *)ctx;
547
548 if (ptr == NULL)
549 return;
550
551 /* GIL cannot be locked in PyMem_RawFree() because it would introduce
552 a deadlock in PyThreadState_DeleteCurrent(). */
553
554 alloc->free(alloc->ctx, ptr);
Victor Stinner88c29872013-12-04 01:47:46 +0100555
556 TABLES_LOCK();
Victor Stinner15116802013-12-04 01:29:35 +0100557 tracemalloc_remove_trace(ptr);
Victor Stinner88c29872013-12-04 01:47:46 +0100558 TABLES_UNLOCK();
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100559}
560
561static void*
562tracemalloc_malloc_gil(void *ctx, size_t size)
563{
Victor Stinner15116802013-12-04 01:29:35 +0100564 void *ptr;
565
566 if (get_reentrant()) {
567 PyMemAllocator *alloc = (PyMemAllocator *)ctx;
568 return alloc->malloc(alloc->ctx, size);
569 }
570
571 /* Ignore reentrant call. PyObjet_Malloc() calls PyMem_Malloc() for
572 allocations larger than 512 bytes, don't trace the same memory
573 allocation twice. */
574 set_reentrant(1);
575
576 ptr = tracemalloc_malloc(ctx, size);
577
578 set_reentrant(0);
579 return ptr;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100580}
581
582static void*
583tracemalloc_realloc_gil(void *ctx, void *ptr, size_t new_size)
584{
Victor Stinner15116802013-12-04 01:29:35 +0100585 void *ptr2;
586
587 if (get_reentrant()) {
588 /* Reentrant call to PyMem_Realloc() and PyMem_RawRealloc().
589 Example: PyMem_RawRealloc() is called internally by pymalloc
590 (_PyObject_Malloc() and _PyObject_Realloc()) to allocate a new
591 arena (new_arena()). */
592 PyMemAllocator *alloc = (PyMemAllocator *)ctx;
593
594 ptr2 = alloc->realloc(alloc->ctx, ptr, new_size);
Victor Stinner88c29872013-12-04 01:47:46 +0100595 if (ptr2 != NULL && ptr != NULL) {
596 TABLES_LOCK();
Victor Stinner15116802013-12-04 01:29:35 +0100597 tracemalloc_remove_trace(ptr);
Victor Stinner88c29872013-12-04 01:47:46 +0100598 TABLES_UNLOCK();
599 }
Victor Stinner15116802013-12-04 01:29:35 +0100600 return ptr2;
601 }
602
603 /* Ignore reentrant call. PyObjet_Realloc() calls PyMem_Realloc() for
604 allocations larger than 512 bytes. Don't trace the same memory
605 allocation twice. */
606 set_reentrant(1);
607
608 ptr2 = tracemalloc_realloc(ctx, ptr, new_size);
609
610 set_reentrant(0);
611 return ptr2;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100612}
613
614#ifdef TRACE_RAW_MALLOC
615static void*
616tracemalloc_raw_malloc(void *ctx, size_t size)
617{
Victor Stinner15116802013-12-04 01:29:35 +0100618#ifdef WITH_THREAD
619 PyGILState_STATE gil_state;
620#endif
621 void *ptr;
622
623 if (get_reentrant()) {
624 PyMemAllocator *alloc = (PyMemAllocator *)ctx;
625 return alloc->malloc(alloc->ctx, size);
626 }
627
628 /* Ignore reentrant call. PyGILState_Ensure() may call PyMem_RawMalloc()
629 indirectly which would call PyGILState_Ensure() if reentrant are not
630 disabled. */
631 set_reentrant(1);
632
633#ifdef WITH_THREAD
634 gil_state = PyGILState_Ensure();
635 ptr = tracemalloc_malloc(ctx, size);
636 PyGILState_Release(gil_state);
637#else
638 ptr = tracemalloc_malloc(ctx, size);
639#endif
640
641 set_reentrant(0);
642 return ptr;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100643}
644
645static void*
646tracemalloc_raw_realloc(void *ctx, void *ptr, size_t new_size)
647{
Victor Stinner15116802013-12-04 01:29:35 +0100648#ifdef WITH_THREAD
649 PyGILState_STATE gil_state;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100650#endif
Victor Stinner15116802013-12-04 01:29:35 +0100651 void *ptr2;
652
653 if (get_reentrant()) {
654 /* Reentrant call to PyMem_RawRealloc(). */
655 PyMemAllocator *alloc = (PyMemAllocator *)ctx;
656
657 ptr2 = alloc->realloc(alloc->ctx, ptr, new_size);
Victor Stinner15116802013-12-04 01:29:35 +0100658
Victor Stinner88c29872013-12-04 01:47:46 +0100659 if (ptr2 != NULL && ptr != NULL) {
660 TABLES_LOCK();
661 tracemalloc_remove_trace(ptr);
662 TABLES_UNLOCK();
663 }
Victor Stinner15116802013-12-04 01:29:35 +0100664 return ptr2;
665 }
666
667 /* Ignore reentrant call. PyGILState_Ensure() may call PyMem_RawMalloc()
668 indirectly which would call PyGILState_Ensure() if reentrant calls are
669 not disabled. */
670 set_reentrant(1);
671
672#ifdef WITH_THREAD
673 gil_state = PyGILState_Ensure();
674 ptr2 = tracemalloc_realloc(ctx, ptr, new_size);
675 PyGILState_Release(gil_state);
676#else
677 ptr2 = tracemalloc_realloc(ctx, ptr, new_size);
678#endif
679
680 set_reentrant(0);
681 return ptr2;
682}
683#endif /* TRACE_RAW_MALLOC */
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100684
685static int
686tracemalloc_clear_filename(_Py_hashtable_entry_t *entry, void *user_data)
687{
688 PyObject *filename = (PyObject *)entry->key;
689 Py_DECREF(filename);
690 return 0;
691}
692
693static int
694traceback_free_traceback(_Py_hashtable_entry_t *entry, void *user_data)
695{
696 traceback_t *traceback = (traceback_t *)entry->key;
697 raw_free(traceback);
698 return 0;
699}
700
701/* reentrant flag must be set to call this function and GIL must be held */
702static void
703tracemalloc_clear_traces(void)
704{
705#ifdef WITH_THREAD
706 /* The GIL protects variables againt concurrent access */
707 assert(PyGILState_Check());
708#endif
709
710 /* Disable also reentrant calls to tracemalloc_malloc() to not add a new
711 trace while we are clearing traces */
712 assert(get_reentrant());
713
714 TABLES_LOCK();
715 _Py_hashtable_clear(tracemalloc_traces);
716 tracemalloc_traced_memory = 0;
Victor Stinner3c0481d2013-11-27 21:39:49 +0100717 tracemalloc_peak_traced_memory = 0;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100718 TABLES_UNLOCK();
719
720 _Py_hashtable_foreach(tracemalloc_tracebacks, traceback_free_traceback, NULL);
721 _Py_hashtable_clear(tracemalloc_tracebacks);
722
723 _Py_hashtable_foreach(tracemalloc_filenames, tracemalloc_clear_filename, NULL);
724 _Py_hashtable_clear(tracemalloc_filenames);
725}
726
727static int
728tracemalloc_init(void)
729{
730 if (tracemalloc_config.initialized == TRACEMALLOC_FINALIZED) {
731 PyErr_SetString(PyExc_RuntimeError,
732 "the tracemalloc module has been unloaded");
733 return -1;
734 }
735
736 if (tracemalloc_config.initialized == TRACEMALLOC_INITIALIZED)
737 return 0;
738
739 PyMem_GetAllocator(PYMEM_DOMAIN_RAW, &allocators.raw);
740
741#ifdef REENTRANT_THREADLOCAL
742 tracemalloc_reentrant_key = PyThread_create_key();
743 if (tracemalloc_reentrant_key == -1) {
744#ifdef MS_WINDOWS
745 PyErr_SetFromWindowsErr(0);
746#else
747 PyErr_SetFromErrno(PyExc_OSError);
748#endif
749 return -1;
750 }
751#endif
752
753#if defined(WITH_THREAD) && defined(TRACE_RAW_MALLOC)
754 if (tables_lock == NULL) {
755 tables_lock = PyThread_allocate_lock();
756 if (tables_lock == NULL) {
757 PyErr_SetString(PyExc_RuntimeError, "cannot allocate lock");
758 return -1;
759 }
760 }
761#endif
762
763 tracemalloc_filenames = hashtable_new(0,
764 (_Py_hashtable_hash_func)PyObject_Hash,
765 hashtable_compare_unicode);
766
767 tracemalloc_tracebacks = hashtable_new(0,
768 (_Py_hashtable_hash_func)hashtable_hash_traceback,
769 (_Py_hashtable_compare_func)hashtable_compare_traceback);
770
771 tracemalloc_traces = hashtable_new(sizeof(trace_t),
772 _Py_hashtable_hash_ptr,
773 _Py_hashtable_compare_direct);
774
775 if (tracemalloc_filenames == NULL || tracemalloc_tracebacks == NULL
776 || tracemalloc_traces == NULL)
777 {
778 PyErr_NoMemory();
779 return -1;
780 }
781
782 unknown_filename = PyUnicode_FromString("<unknown>");
783 if (unknown_filename == NULL)
784 return -1;
785 PyUnicode_InternInPlace(&unknown_filename);
786
787 tracemalloc_empty_traceback.nframe = 1;
788 /* borrowed reference */
789 tracemalloc_empty_traceback.frames[0].filename = unknown_filename;
790 tracemalloc_empty_traceback.frames[0].lineno = 0;
791 tracemalloc_empty_traceback.hash = traceback_hash(&tracemalloc_empty_traceback);
792
793 /* Disable tracing allocations until hooks are installed. Set
794 also the reentrant flag to detect bugs: fail with an assertion error
795 if set_reentrant(1) is called while tracing is disabled. */
796 set_reentrant(1);
797
798 tracemalloc_config.initialized = TRACEMALLOC_INITIALIZED;
799 return 0;
800}
801
802static void
803tracemalloc_deinit(void)
804{
805 if (tracemalloc_config.initialized != TRACEMALLOC_INITIALIZED)
806 return;
807 tracemalloc_config.initialized = TRACEMALLOC_FINALIZED;
808
809 tracemalloc_stop();
810
811 /* destroy hash tables */
812 _Py_hashtable_destroy(tracemalloc_traces);
813 _Py_hashtable_destroy(tracemalloc_tracebacks);
814 _Py_hashtable_destroy(tracemalloc_filenames);
815
816#if defined(WITH_THREAD) && defined(TRACE_RAW_MALLOC)
817 if (tables_lock != NULL) {
818 PyThread_free_lock(tables_lock);
819 tables_lock = NULL;
820 }
821#endif
822
823#ifdef REENTRANT_THREADLOCAL
824 PyThread_delete_key(tracemalloc_reentrant_key);
825#endif
826
827 Py_XDECREF(unknown_filename);
828}
829
830static int
Victor Stinnerf28ce602013-11-27 22:27:13 +0100831tracemalloc_start(int max_nframe)
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100832{
833 PyMemAllocator alloc;
Victor Stinnerf28ce602013-11-27 22:27:13 +0100834 size_t size;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100835
836 if (tracemalloc_init() < 0)
837 return -1;
838
839 if (tracemalloc_config.tracing) {
840 /* hook already installed: do nothing */
841 return 0;
842 }
843
Victor Stinnerf28ce602013-11-27 22:27:13 +0100844 assert(1 <= max_nframe && max_nframe <= MAX_NFRAME);
845 tracemalloc_config.max_nframe = max_nframe;
846
847 /* allocate a buffer to store a new traceback */
848 size = TRACEBACK_SIZE(max_nframe);
849 assert(tracemalloc_traceback == NULL);
850 tracemalloc_traceback = raw_malloc(size);
851 if (tracemalloc_traceback == NULL) {
852 PyErr_NoMemory();
853 return -1;
854 }
855
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100856#ifdef TRACE_RAW_MALLOC
857 alloc.malloc = tracemalloc_raw_malloc;
858 alloc.realloc = tracemalloc_raw_realloc;
859 alloc.free = tracemalloc_free;
860
861 alloc.ctx = &allocators.raw;
862 PyMem_GetAllocator(PYMEM_DOMAIN_RAW, &allocators.raw);
863 PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &alloc);
864#endif
865
866 alloc.malloc = tracemalloc_malloc_gil;
867 alloc.realloc = tracemalloc_realloc_gil;
868 alloc.free = tracemalloc_free;
869
870 alloc.ctx = &allocators.mem;
871 PyMem_GetAllocator(PYMEM_DOMAIN_MEM, &allocators.mem);
872 PyMem_SetAllocator(PYMEM_DOMAIN_MEM, &alloc);
873
874 alloc.ctx = &allocators.obj;
875 PyMem_GetAllocator(PYMEM_DOMAIN_OBJ, &allocators.obj);
876 PyMem_SetAllocator(PYMEM_DOMAIN_OBJ, &alloc);
877
878 /* everything is ready: start tracing Python memory allocations */
879 tracemalloc_config.tracing = 1;
880 set_reentrant(0);
881
882 return 0;
883}
884
885static void
886tracemalloc_stop(void)
887{
888 if (!tracemalloc_config.tracing)
889 return;
890
891 /* stop tracing Python memory allocations */
892 tracemalloc_config.tracing = 0;
893
894 /* set the reentrant flag to detect bugs: fail with an assertion error if
895 set_reentrant(1) is called while tracing is disabled. */
896 set_reentrant(1);
897
898 /* unregister the hook on memory allocators */
899#ifdef TRACE_RAW_MALLOC
900 PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &allocators.raw);
901#endif
902 PyMem_SetAllocator(PYMEM_DOMAIN_MEM, &allocators.mem);
903 PyMem_SetAllocator(PYMEM_DOMAIN_OBJ, &allocators.obj);
904
905 /* release memory */
906 tracemalloc_clear_traces();
Victor Stinnerf28ce602013-11-27 22:27:13 +0100907 raw_free(tracemalloc_traceback);
908 tracemalloc_traceback = NULL;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100909}
910
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100911static PyObject*
912lineno_as_obj(int lineno)
913{
914 if (lineno >= 0)
915 return PyLong_FromLong(lineno);
916 else
917 Py_RETURN_NONE;
918}
919
920PyDoc_STRVAR(tracemalloc_is_tracing_doc,
921 "is_tracing()->bool\n"
922 "\n"
923 "True if the tracemalloc module is tracing Python memory allocations,\n"
924 "False otherwise.");
925
926static PyObject*
927py_tracemalloc_is_tracing(PyObject *self)
928{
929 return PyBool_FromLong(tracemalloc_config.tracing);
930}
931
932PyDoc_STRVAR(tracemalloc_clear_traces_doc,
933 "clear_traces()\n"
934 "\n"
935 "Clear traces of memory blocks allocated by Python.");
936
937static PyObject*
938py_tracemalloc_clear_traces(PyObject *self)
939{
940 if (!tracemalloc_config.tracing)
941 Py_RETURN_NONE;
942
943 set_reentrant(1);
944 tracemalloc_clear_traces();
945 set_reentrant(0);
946
947 Py_RETURN_NONE;
948}
949
950static PyObject*
951frame_to_pyobject(frame_t *frame)
952{
953 PyObject *frame_obj, *lineno_obj;
954
955 frame_obj = PyTuple_New(2);
956 if (frame_obj == NULL)
957 return NULL;
958
959 if (frame->filename == NULL)
960 frame->filename = Py_None;
961 Py_INCREF(frame->filename);
962 PyTuple_SET_ITEM(frame_obj, 0, frame->filename);
963
964 assert(frame->lineno >= 0);
965 lineno_obj = lineno_as_obj(frame->lineno);
966 if (lineno_obj == NULL) {
967 Py_DECREF(frame_obj);
968 return NULL;
969 }
970 PyTuple_SET_ITEM(frame_obj, 1, lineno_obj);
971
972 return frame_obj;
973}
974
975static PyObject*
976traceback_to_pyobject(traceback_t *traceback, _Py_hashtable_t *intern_table)
977{
978 int i;
979 PyObject *frames, *frame;
980
981 if (intern_table != NULL) {
982 if (_Py_HASHTABLE_GET(intern_table, traceback, frames)) {
983 Py_INCREF(frames);
984 return frames;
985 }
986 }
987
988 frames = PyTuple_New(traceback->nframe);
989 if (frames == NULL)
990 return NULL;
991
992 for (i=0; i < traceback->nframe; i++) {
993 frame = frame_to_pyobject(&traceback->frames[i]);
994 if (frame == NULL) {
995 Py_DECREF(frames);
996 return NULL;
997 }
998 PyTuple_SET_ITEM(frames, i, frame);
999 }
1000
1001 if (intern_table != NULL) {
1002 if (_Py_HASHTABLE_SET(intern_table, traceback, frames) < 0) {
1003 Py_DECREF(frames);
1004 PyErr_NoMemory();
1005 return NULL;
1006 }
1007 /* intern_table keeps a new reference to frames */
1008 Py_INCREF(frames);
1009 }
1010 return frames;
1011}
1012
1013static PyObject*
1014trace_to_pyobject(trace_t *trace, _Py_hashtable_t *intern_tracebacks)
1015{
1016 PyObject *trace_obj = NULL;
1017 PyObject *size, *traceback;
1018
1019 trace_obj = PyTuple_New(2);
1020 if (trace_obj == NULL)
1021 return NULL;
1022
1023 size = PyLong_FromSize_t(trace->size);
1024 if (size == NULL) {
1025 Py_DECREF(trace_obj);
1026 return NULL;
1027 }
1028 PyTuple_SET_ITEM(trace_obj, 0, size);
1029
1030 traceback = traceback_to_pyobject(trace->traceback, intern_tracebacks);
1031 if (traceback == NULL) {
1032 Py_DECREF(trace_obj);
1033 return NULL;
1034 }
1035 PyTuple_SET_ITEM(trace_obj, 1, traceback);
1036
1037 return trace_obj;
1038}
1039
1040typedef struct {
1041 _Py_hashtable_t *traces;
1042 _Py_hashtable_t *tracebacks;
1043 PyObject *list;
1044} get_traces_t;
1045
1046static int
1047tracemalloc_get_traces_fill(_Py_hashtable_entry_t *entry, void *user_data)
1048{
1049 get_traces_t *get_traces = user_data;
1050 trace_t *trace;
1051 PyObject *tracemalloc_obj;
1052 int res;
1053
1054 trace = (trace_t *)_PY_HASHTABLE_ENTRY_DATA(entry);
1055
1056 tracemalloc_obj = trace_to_pyobject(trace, get_traces->tracebacks);
1057 if (tracemalloc_obj == NULL)
1058 return 1;
1059
1060 res = PyList_Append(get_traces->list, tracemalloc_obj);
1061 Py_DECREF(tracemalloc_obj);
1062 if (res < 0)
1063 return 1;
1064
1065 return 0;
1066}
1067
1068static int
1069tracemalloc_pyobject_decref_cb(_Py_hashtable_entry_t *entry, void *user_data)
1070{
1071 PyObject *obj = (PyObject *)_Py_HASHTABLE_ENTRY_DATA_AS_VOID_P(entry);
1072 Py_DECREF(obj);
1073 return 0;
1074}
1075
1076PyDoc_STRVAR(tracemalloc_get_traces_doc,
Victor Stinner4fbefdb2013-11-25 09:33:18 +01001077 "_get_traces() -> list\n"
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001078 "\n"
1079 "Get traces of all memory blocks allocated by Python.\n"
1080 "Return a list of (size: int, traceback: tuple) tuples.\n"
1081 "traceback is a tuple of (filename: str, lineno: int) tuples.\n"
1082 "\n"
1083 "Return an empty list if the tracemalloc module is disabled.");
1084
1085static PyObject*
1086py_tracemalloc_get_traces(PyObject *self, PyObject *obj)
1087{
1088 get_traces_t get_traces;
1089 int err;
1090
1091 get_traces.traces = NULL;
1092 get_traces.tracebacks = NULL;
1093 get_traces.list = PyList_New(0);
1094 if (get_traces.list == NULL)
1095 goto error;
1096
1097 if (!tracemalloc_config.tracing)
1098 return get_traces.list;
1099
Victor Stinnerde2f1322013-11-26 00:26:23 +01001100 /* the traceback hash table is used temporarily to intern traceback tuple
1101 of (filename, lineno) tuples */
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001102 get_traces.tracebacks = hashtable_new(sizeof(PyObject *),
1103 _Py_hashtable_hash_ptr,
1104 _Py_hashtable_compare_direct);
1105 if (get_traces.tracebacks == NULL) {
1106 PyErr_NoMemory();
1107 goto error;
1108 }
1109
1110 TABLES_LOCK();
1111 get_traces.traces = _Py_hashtable_copy(tracemalloc_traces);
1112 TABLES_UNLOCK();
1113
1114 if (get_traces.traces == NULL) {
1115 PyErr_NoMemory();
1116 goto error;
1117 }
1118
1119 set_reentrant(1);
1120 err = _Py_hashtable_foreach(get_traces.traces,
1121 tracemalloc_get_traces_fill, &get_traces);
1122 set_reentrant(0);
1123 if (err)
1124 goto error;
1125
1126 goto finally;
1127
1128error:
1129 Py_CLEAR(get_traces.list);
1130
1131finally:
1132 if (get_traces.tracebacks != NULL) {
1133 _Py_hashtable_foreach(get_traces.tracebacks,
1134 tracemalloc_pyobject_decref_cb, NULL);
1135 _Py_hashtable_destroy(get_traces.tracebacks);
1136 }
1137 if (get_traces.traces != NULL)
1138 _Py_hashtable_destroy(get_traces.traces);
1139
1140 return get_traces.list;
1141}
1142
1143PyDoc_STRVAR(tracemalloc_get_object_traceback_doc,
Victor Stinner4fbefdb2013-11-25 09:33:18 +01001144 "_get_object_traceback(obj)\n"
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001145 "\n"
1146 "Get the traceback where the Python object obj was allocated.\n"
1147 "Return a tuple of (filename: str, lineno: int) tuples.\n"
1148 "\n"
1149 "Return None if the tracemalloc module is disabled or did not\n"
1150 "trace the allocation of the object.");
1151
1152static PyObject*
1153py_tracemalloc_get_object_traceback(PyObject *self, PyObject *obj)
1154{
1155 PyTypeObject *type;
1156 void *ptr;
1157 trace_t trace;
1158 int found;
1159
1160 if (!tracemalloc_config.tracing)
1161 Py_RETURN_NONE;
1162
1163 type = Py_TYPE(obj);
1164 if (PyType_IS_GC(type))
1165 ptr = (void *)((char *)obj - sizeof(PyGC_Head));
1166 else
1167 ptr = (void *)obj;
1168
1169 TABLES_LOCK();
1170 found = _Py_HASHTABLE_GET(tracemalloc_traces, ptr, trace);
1171 TABLES_UNLOCK();
1172
1173 if (!found)
1174 Py_RETURN_NONE;
1175
1176 return traceback_to_pyobject(trace.traceback, NULL);
1177}
1178
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001179PyDoc_STRVAR(tracemalloc_start_doc,
Victor Stinner3728d6c2013-11-23 12:37:20 +01001180 "start(nframe: int=1)\n"
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001181 "\n"
Victor Stinner3728d6c2013-11-23 12:37:20 +01001182 "Start tracing Python memory allocations. Set also the maximum number \n"
1183 "of frames stored in the traceback of a trace to nframe.");
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001184
1185static PyObject*
Victor Stinner3728d6c2013-11-23 12:37:20 +01001186py_tracemalloc_start(PyObject *self, PyObject *args)
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001187{
Victor Stinner3728d6c2013-11-23 12:37:20 +01001188 Py_ssize_t nframe = 1;
Victor Stinnerf28ce602013-11-27 22:27:13 +01001189 int nframe_int;
Victor Stinner3728d6c2013-11-23 12:37:20 +01001190
1191 if (!PyArg_ParseTuple(args, "|n:start", &nframe))
1192 return NULL;
1193
1194 if (nframe < 1 || nframe > MAX_NFRAME) {
1195 PyErr_Format(PyExc_ValueError,
1196 "the number of frames must be in range [1; %i]",
Victor Stinnerf28ce602013-11-27 22:27:13 +01001197 (int)MAX_NFRAME);
Victor Stinner3728d6c2013-11-23 12:37:20 +01001198 return NULL;
1199 }
Victor Stinnerf28ce602013-11-27 22:27:13 +01001200 nframe_int = Py_SAFE_DOWNCAST(nframe, Py_ssize_t, int);
Victor Stinner3728d6c2013-11-23 12:37:20 +01001201
Victor Stinnerf28ce602013-11-27 22:27:13 +01001202 if (tracemalloc_start(nframe_int) < 0)
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001203 return NULL;
1204
1205 Py_RETURN_NONE;
1206}
1207
1208PyDoc_STRVAR(tracemalloc_stop_doc,
1209 "stop()\n"
1210 "\n"
1211 "Stop tracing Python memory allocations and clear traces\n"
1212 "of memory blocks allocated by Python.");
1213
1214static PyObject*
1215py_tracemalloc_stop(PyObject *self)
1216{
1217 tracemalloc_stop();
1218 Py_RETURN_NONE;
1219}
1220
1221PyDoc_STRVAR(tracemalloc_get_traceback_limit_doc,
1222 "get_traceback_limit() -> int\n"
1223 "\n"
1224 "Get the maximum number of frames stored in the traceback\n"
1225 "of a trace.\n"
1226 "\n"
1227 "By default, a trace of an allocated memory block only stores\n"
1228 "the most recent frame: the limit is 1.");
1229
1230static PyObject*
1231py_tracemalloc_get_traceback_limit(PyObject *self)
1232{
1233 return PyLong_FromLong(tracemalloc_config.max_nframe);
1234}
1235
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001236PyDoc_STRVAR(tracemalloc_get_tracemalloc_memory_doc,
1237 "get_tracemalloc_memory() -> int\n"
1238 "\n"
1239 "Get the memory usage in bytes of the tracemalloc module\n"
1240 "used internally to trace memory allocations.");
1241
1242static PyObject*
1243tracemalloc_get_tracemalloc_memory(PyObject *self)
1244{
1245 size_t size;
1246 PyObject *size_obj;
1247
1248 size = _Py_hashtable_size(tracemalloc_tracebacks);
1249 size += _Py_hashtable_size(tracemalloc_filenames);
1250
1251 TABLES_LOCK();
1252 size += _Py_hashtable_size(tracemalloc_traces);
1253 TABLES_UNLOCK();
1254
1255 size_obj = PyLong_FromSize_t(size);
1256 return Py_BuildValue("N", size_obj);
1257}
1258
1259PyDoc_STRVAR(tracemalloc_get_traced_memory_doc,
Victor Stinner59463d82013-11-26 10:46:06 +01001260 "get_traced_memory() -> (int, int)\n"
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001261 "\n"
Victor Stinner3c0481d2013-11-27 21:39:49 +01001262 "Get the current size and peak size of memory blocks traced\n"
1263 "by the tracemalloc module as a tuple: (current: int, peak: int).");
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001264
1265static PyObject*
1266tracemalloc_get_traced_memory(PyObject *self)
1267{
Victor Stinner3c0481d2013-11-27 21:39:49 +01001268 Py_ssize_t size, peak_size;
1269 PyObject *size_obj, *peak_size_obj;
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001270
1271 if (!tracemalloc_config.tracing)
1272 return Py_BuildValue("ii", 0, 0);
1273
1274 TABLES_LOCK();
1275 size = tracemalloc_traced_memory;
Victor Stinner3c0481d2013-11-27 21:39:49 +01001276 peak_size = tracemalloc_peak_traced_memory;
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001277 TABLES_UNLOCK();
1278
1279 size_obj = PyLong_FromSize_t(size);
Victor Stinner3c0481d2013-11-27 21:39:49 +01001280 peak_size_obj = PyLong_FromSize_t(peak_size);
1281 return Py_BuildValue("NN", size_obj, peak_size_obj);
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001282}
1283
1284static PyMethodDef module_methods[] = {
1285 {"is_tracing", (PyCFunction)py_tracemalloc_is_tracing,
1286 METH_NOARGS, tracemalloc_is_tracing_doc},
1287 {"clear_traces", (PyCFunction)py_tracemalloc_clear_traces,
1288 METH_NOARGS, tracemalloc_clear_traces_doc},
1289 {"_get_traces", (PyCFunction)py_tracemalloc_get_traces,
1290 METH_NOARGS, tracemalloc_get_traces_doc},
1291 {"_get_object_traceback", (PyCFunction)py_tracemalloc_get_object_traceback,
1292 METH_O, tracemalloc_get_object_traceback_doc},
1293 {"start", (PyCFunction)py_tracemalloc_start,
Victor Stinner3728d6c2013-11-23 12:37:20 +01001294 METH_VARARGS, tracemalloc_start_doc},
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001295 {"stop", (PyCFunction)py_tracemalloc_stop,
1296 METH_NOARGS, tracemalloc_stop_doc},
1297 {"get_traceback_limit", (PyCFunction)py_tracemalloc_get_traceback_limit,
1298 METH_NOARGS, tracemalloc_get_traceback_limit_doc},
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001299 {"get_tracemalloc_memory", (PyCFunction)tracemalloc_get_tracemalloc_memory,
1300 METH_NOARGS, tracemalloc_get_tracemalloc_memory_doc},
1301 {"get_traced_memory", (PyCFunction)tracemalloc_get_traced_memory,
1302 METH_NOARGS, tracemalloc_get_traced_memory_doc},
1303
1304 /* sentinel */
1305 {NULL, NULL}
1306};
1307
1308PyDoc_STRVAR(module_doc,
1309"Debug module to trace memory blocks allocated by Python.");
1310
1311static struct PyModuleDef module_def = {
1312 PyModuleDef_HEAD_INIT,
1313 "_tracemalloc",
1314 module_doc,
1315 0, /* non-negative size to be able to unload the module */
1316 module_methods,
1317 NULL,
1318};
1319
1320PyMODINIT_FUNC
1321PyInit__tracemalloc(void)
1322{
1323 PyObject *m;
1324 m = PyModule_Create(&module_def);
1325 if (m == NULL)
1326 return NULL;
1327
1328 if (tracemalloc_init() < 0)
1329 return NULL;
1330
1331 return m;
1332}
1333
1334static int
1335parse_sys_xoptions(PyObject *value)
1336{
1337 PyObject *valuelong;
1338 long nframe;
1339
1340 if (value == Py_True)
1341 return 1;
1342
1343 assert(PyUnicode_Check(value));
1344 if (PyUnicode_GetLength(value) == 0)
1345 return -1;
1346
1347 valuelong = PyLong_FromUnicodeObject(value, 10);
1348 if (valuelong == NULL)
1349 return -1;
1350
1351 nframe = PyLong_AsLong(valuelong);
1352 Py_DECREF(valuelong);
1353 if (nframe == -1 && PyErr_Occurred())
1354 return -1;
1355
1356 if (nframe < 1 || nframe > MAX_NFRAME)
1357 return -1;
1358
1359 return Py_SAFE_DOWNCAST(nframe, long, int);
1360}
1361
1362int
1363_PyTraceMalloc_Init(void)
1364{
1365 char *p;
1366 int nframe;
1367
1368#ifdef WITH_THREAD
1369 assert(PyGILState_Check());
1370#endif
1371
1372 if ((p = Py_GETENV("PYTHONTRACEMALLOC")) && *p != '\0') {
1373 char *endptr = p;
Victor Stinnerf28ce602013-11-27 22:27:13 +01001374 long value;
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001375
Victor Stinnerf28ce602013-11-27 22:27:13 +01001376 value = strtol(p, &endptr, 10);
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001377 if (*endptr != '\0'
1378 || value < 1
1379 || value > MAX_NFRAME
1380 || (errno == ERANGE && value == ULONG_MAX))
1381 {
Victor Stinnerf28ce602013-11-27 22:27:13 +01001382 Py_FatalError("PYTHONTRACEMALLOC: invalid number of frames");
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001383 return -1;
1384 }
1385
1386 nframe = (int)value;
1387 }
1388 else {
1389 PyObject *xoptions, *key, *value;
1390
1391 xoptions = PySys_GetXOptions();
1392 if (xoptions == NULL)
1393 return -1;
1394
1395 key = PyUnicode_FromString("tracemalloc");
1396 if (key == NULL)
1397 return -1;
1398
1399 value = PyDict_GetItemWithError(xoptions, key);
1400 Py_DECREF(key);
1401 if (value == NULL) {
1402 if (PyErr_Occurred())
1403 return -1;
1404
1405 /* -X tracemalloc is not used */
1406 return 0;
1407 }
1408
1409 nframe = parse_sys_xoptions(value);
1410 Py_DECREF(value);
1411 if (nframe < 0) {
Victor Stinnerf28ce602013-11-27 22:27:13 +01001412 Py_FatalError("-X tracemalloc=NFRAME: invalid number of frames");
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001413 }
1414 }
1415
Victor Stinnerf28ce602013-11-27 22:27:13 +01001416 return tracemalloc_start(nframe);
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001417}
1418
Victor Stinnerbe0708f2013-12-01 10:03:26 +01001419void
1420_PyTraceMalloc_Fini(void)
1421{
1422#ifdef WITH_THREAD
1423 assert(PyGILState_Check());
1424#endif
1425 tracemalloc_deinit();
1426}
1427