blob: e254a9029dbbd6a4147b9b6e6eb7fa380e24f9b8 [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
107/* Hash table used as a set to to intern filenames:
108 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 Stinnerdb067af2014-05-02 22:31:14 +0200479tracemalloc_alloc(int use_calloc, void *ctx, size_t nelem, size_t elsize)
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 Stinnerdb067af2014-05-02 22:31:14 +0200484 assert(nelem <= PY_SIZE_MAX / elsize);
485
486 if (use_calloc)
487 ptr = alloc->calloc(alloc->ctx, nelem, elsize);
488 else
489 ptr = alloc->malloc(alloc->ctx, nelem * elsize);
Victor Stinner15116802013-12-04 01:29:35 +0100490 if (ptr == NULL)
491 return NULL;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100492
Victor Stinner88c29872013-12-04 01:47:46 +0100493 TABLES_LOCK();
Victor Stinnerdb067af2014-05-02 22:31:14 +0200494 if (tracemalloc_add_trace(ptr, nelem * elsize) < 0) {
Victor Stinner15116802013-12-04 01:29:35 +0100495 /* Failed to allocate a trace for the new memory block */
Victor Stinner88c29872013-12-04 01:47:46 +0100496 TABLES_UNLOCK();
Victor Stinner15116802013-12-04 01:29:35 +0100497 alloc->free(alloc->ctx, ptr);
498 return NULL;
Victor Stinner52968672013-11-24 11:37:15 +0100499 }
Victor Stinner88c29872013-12-04 01:47:46 +0100500 TABLES_UNLOCK();
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100501 return ptr;
502}
503
504static void*
Victor Stinner15116802013-12-04 01:29:35 +0100505tracemalloc_realloc(void *ctx, void *ptr, size_t new_size)
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100506{
507 PyMemAllocator *alloc = (PyMemAllocator *)ctx;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100508 void *ptr2;
509
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100510 ptr2 = alloc->realloc(alloc->ctx, ptr, new_size);
Victor Stinner15116802013-12-04 01:29:35 +0100511 if (ptr2 == NULL)
512 return NULL;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100513
Victor Stinner15116802013-12-04 01:29:35 +0100514 if (ptr != NULL) {
515 /* an existing memory block has been resized */
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100516
Victor Stinner88c29872013-12-04 01:47:46 +0100517 TABLES_LOCK();
Victor Stinner15116802013-12-04 01:29:35 +0100518 tracemalloc_remove_trace(ptr);
Victor Stinner08facd22013-11-24 12:27:59 +0100519
Victor Stinner15116802013-12-04 01:29:35 +0100520 if (tracemalloc_add_trace(ptr2, new_size) < 0) {
521 /* Memory allocation failed. The error cannot be reported to
522 the caller, because realloc() may already have shrinked the
523 memory block and so removed bytes.
524
Victor Stinner88c29872013-12-04 01:47:46 +0100525 This case is very unlikely: an hash entry has just been
526 released, so the hash table should have at least one free entry.
527
528 The GIL and the table lock ensures that only one thread is
529 allocating memory. */
530 assert(0 && "should never happen");
Victor Stinner52968672013-11-24 11:37:15 +0100531 }
Victor Stinner88c29872013-12-04 01:47:46 +0100532 TABLES_UNLOCK();
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100533 }
Victor Stinner15116802013-12-04 01:29:35 +0100534 else {
535 /* new allocation */
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100536
Victor Stinner88c29872013-12-04 01:47:46 +0100537 TABLES_LOCK();
Victor Stinner15116802013-12-04 01:29:35 +0100538 if (tracemalloc_add_trace(ptr2, new_size) < 0) {
539 /* Failed to allocate a trace for the new memory block */
Victor Stinner88c29872013-12-04 01:47:46 +0100540 TABLES_UNLOCK();
Victor Stinner15116802013-12-04 01:29:35 +0100541 alloc->free(alloc->ctx, ptr2);
542 return NULL;
543 }
Victor Stinner88c29872013-12-04 01:47:46 +0100544 TABLES_UNLOCK();
Victor Stinner15116802013-12-04 01:29:35 +0100545 }
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100546 return ptr2;
547}
548
549static void
550tracemalloc_free(void *ctx, void *ptr)
551{
552 PyMemAllocator *alloc = (PyMemAllocator *)ctx;
553
554 if (ptr == NULL)
555 return;
556
557 /* GIL cannot be locked in PyMem_RawFree() because it would introduce
558 a deadlock in PyThreadState_DeleteCurrent(). */
559
560 alloc->free(alloc->ctx, ptr);
Victor Stinner88c29872013-12-04 01:47:46 +0100561
562 TABLES_LOCK();
Victor Stinner15116802013-12-04 01:29:35 +0100563 tracemalloc_remove_trace(ptr);
Victor Stinner88c29872013-12-04 01:47:46 +0100564 TABLES_UNLOCK();
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100565}
566
567static void*
Victor Stinnerdb067af2014-05-02 22:31:14 +0200568tracemalloc_alloc_gil(int use_calloc, void *ctx, size_t nelem, size_t elsize)
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100569{
Victor Stinner15116802013-12-04 01:29:35 +0100570 void *ptr;
571
572 if (get_reentrant()) {
573 PyMemAllocator *alloc = (PyMemAllocator *)ctx;
Victor Stinnerdb067af2014-05-02 22:31:14 +0200574 if (use_calloc)
575 return alloc->calloc(alloc->ctx, nelem, elsize);
576 else
577 return alloc->malloc(alloc->ctx, nelem * elsize);
Victor Stinner15116802013-12-04 01:29:35 +0100578 }
579
580 /* Ignore reentrant call. PyObjet_Malloc() calls PyMem_Malloc() for
581 allocations larger than 512 bytes, don't trace the same memory
582 allocation twice. */
583 set_reentrant(1);
584
Victor Stinnerdb067af2014-05-02 22:31:14 +0200585 ptr = tracemalloc_alloc(use_calloc, ctx, nelem, elsize);
Victor Stinner15116802013-12-04 01:29:35 +0100586
587 set_reentrant(0);
588 return ptr;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100589}
590
591static void*
Victor Stinnerdb067af2014-05-02 22:31:14 +0200592tracemalloc_malloc_gil(void *ctx, size_t size)
593{
594 return tracemalloc_alloc_gil(0, ctx, 1, size);
595}
596
597static void*
598tracemalloc_calloc_gil(void *ctx, size_t nelem, size_t elsize)
599{
600 return tracemalloc_alloc_gil(1, ctx, nelem, elsize);
601}
602
603static void*
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100604tracemalloc_realloc_gil(void *ctx, void *ptr, size_t new_size)
605{
Victor Stinner15116802013-12-04 01:29:35 +0100606 void *ptr2;
607
608 if (get_reentrant()) {
609 /* Reentrant call to PyMem_Realloc() and PyMem_RawRealloc().
610 Example: PyMem_RawRealloc() is called internally by pymalloc
611 (_PyObject_Malloc() and _PyObject_Realloc()) to allocate a new
612 arena (new_arena()). */
613 PyMemAllocator *alloc = (PyMemAllocator *)ctx;
614
615 ptr2 = alloc->realloc(alloc->ctx, ptr, new_size);
Victor Stinner88c29872013-12-04 01:47:46 +0100616 if (ptr2 != NULL && ptr != NULL) {
617 TABLES_LOCK();
Victor Stinner15116802013-12-04 01:29:35 +0100618 tracemalloc_remove_trace(ptr);
Victor Stinner88c29872013-12-04 01:47:46 +0100619 TABLES_UNLOCK();
620 }
Victor Stinner15116802013-12-04 01:29:35 +0100621 return ptr2;
622 }
623
624 /* Ignore reentrant call. PyObjet_Realloc() calls PyMem_Realloc() for
625 allocations larger than 512 bytes. Don't trace the same memory
626 allocation twice. */
627 set_reentrant(1);
628
629 ptr2 = tracemalloc_realloc(ctx, ptr, new_size);
630
631 set_reentrant(0);
632 return ptr2;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100633}
634
635#ifdef TRACE_RAW_MALLOC
636static void*
Victor Stinnerdb067af2014-05-02 22:31:14 +0200637tracemalloc_raw_alloc(int use_calloc, void *ctx, size_t nelem, size_t elsize)
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100638{
Victor Stinner15116802013-12-04 01:29:35 +0100639#ifdef WITH_THREAD
640 PyGILState_STATE gil_state;
641#endif
642 void *ptr;
643
644 if (get_reentrant()) {
645 PyMemAllocator *alloc = (PyMemAllocator *)ctx;
Victor Stinnerdb067af2014-05-02 22:31:14 +0200646 if (use_calloc)
647 return alloc->calloc(alloc->ctx, nelem, elsize);
648 else
649 return alloc->malloc(alloc->ctx, nelem * elsize);
Victor Stinner15116802013-12-04 01:29:35 +0100650 }
651
652 /* Ignore reentrant call. PyGILState_Ensure() may call PyMem_RawMalloc()
653 indirectly which would call PyGILState_Ensure() if reentrant are not
654 disabled. */
655 set_reentrant(1);
656
657#ifdef WITH_THREAD
658 gil_state = PyGILState_Ensure();
Victor Stinnerdb067af2014-05-02 22:31:14 +0200659 ptr = tracemalloc_alloc(use_calloc, ctx, nelem, elsize);
Victor Stinner15116802013-12-04 01:29:35 +0100660 PyGILState_Release(gil_state);
661#else
Victor Stinnerdb067af2014-05-02 22:31:14 +0200662 ptr = tracemalloc_alloc(use_calloc, ctx, nelem, elsize);
Victor Stinner15116802013-12-04 01:29:35 +0100663#endif
664
665 set_reentrant(0);
666 return ptr;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100667}
668
669static void*
Victor Stinnerdb067af2014-05-02 22:31:14 +0200670tracemalloc_raw_malloc(void *ctx, size_t size)
671{
672 return tracemalloc_raw_alloc(0, ctx, 1, size);
673}
674
675static void*
676tracemalloc_raw_calloc(void *ctx, size_t nelem, size_t elsize)
677{
678 return tracemalloc_raw_alloc(1, ctx, nelem, elsize);
679}
680
681static void*
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100682tracemalloc_raw_realloc(void *ctx, void *ptr, size_t new_size)
683{
Victor Stinner15116802013-12-04 01:29:35 +0100684#ifdef WITH_THREAD
685 PyGILState_STATE gil_state;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100686#endif
Victor Stinner15116802013-12-04 01:29:35 +0100687 void *ptr2;
688
689 if (get_reentrant()) {
690 /* Reentrant call to PyMem_RawRealloc(). */
691 PyMemAllocator *alloc = (PyMemAllocator *)ctx;
692
693 ptr2 = alloc->realloc(alloc->ctx, ptr, new_size);
Victor Stinner15116802013-12-04 01:29:35 +0100694
Victor Stinner88c29872013-12-04 01:47:46 +0100695 if (ptr2 != NULL && ptr != NULL) {
696 TABLES_LOCK();
697 tracemalloc_remove_trace(ptr);
698 TABLES_UNLOCK();
699 }
Victor Stinner15116802013-12-04 01:29:35 +0100700 return ptr2;
701 }
702
703 /* Ignore reentrant call. PyGILState_Ensure() may call PyMem_RawMalloc()
704 indirectly which would call PyGILState_Ensure() if reentrant calls are
705 not disabled. */
706 set_reentrant(1);
707
708#ifdef WITH_THREAD
709 gil_state = PyGILState_Ensure();
710 ptr2 = tracemalloc_realloc(ctx, ptr, new_size);
711 PyGILState_Release(gil_state);
712#else
713 ptr2 = tracemalloc_realloc(ctx, ptr, new_size);
714#endif
715
716 set_reentrant(0);
717 return ptr2;
718}
719#endif /* TRACE_RAW_MALLOC */
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100720
721static int
722tracemalloc_clear_filename(_Py_hashtable_entry_t *entry, void *user_data)
723{
724 PyObject *filename = (PyObject *)entry->key;
725 Py_DECREF(filename);
726 return 0;
727}
728
729static int
730traceback_free_traceback(_Py_hashtable_entry_t *entry, void *user_data)
731{
732 traceback_t *traceback = (traceback_t *)entry->key;
733 raw_free(traceback);
734 return 0;
735}
736
737/* reentrant flag must be set to call this function and GIL must be held */
738static void
739tracemalloc_clear_traces(void)
740{
741#ifdef WITH_THREAD
742 /* The GIL protects variables againt concurrent access */
743 assert(PyGILState_Check());
744#endif
745
746 /* Disable also reentrant calls to tracemalloc_malloc() to not add a new
747 trace while we are clearing traces */
748 assert(get_reentrant());
749
750 TABLES_LOCK();
751 _Py_hashtable_clear(tracemalloc_traces);
752 tracemalloc_traced_memory = 0;
Victor Stinner3c0481d2013-11-27 21:39:49 +0100753 tracemalloc_peak_traced_memory = 0;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100754 TABLES_UNLOCK();
755
756 _Py_hashtable_foreach(tracemalloc_tracebacks, traceback_free_traceback, NULL);
757 _Py_hashtable_clear(tracemalloc_tracebacks);
758
759 _Py_hashtable_foreach(tracemalloc_filenames, tracemalloc_clear_filename, NULL);
760 _Py_hashtable_clear(tracemalloc_filenames);
761}
762
763static int
764tracemalloc_init(void)
765{
766 if (tracemalloc_config.initialized == TRACEMALLOC_FINALIZED) {
767 PyErr_SetString(PyExc_RuntimeError,
768 "the tracemalloc module has been unloaded");
769 return -1;
770 }
771
772 if (tracemalloc_config.initialized == TRACEMALLOC_INITIALIZED)
773 return 0;
774
775 PyMem_GetAllocator(PYMEM_DOMAIN_RAW, &allocators.raw);
776
777#ifdef REENTRANT_THREADLOCAL
778 tracemalloc_reentrant_key = PyThread_create_key();
779 if (tracemalloc_reentrant_key == -1) {
780#ifdef MS_WINDOWS
781 PyErr_SetFromWindowsErr(0);
782#else
783 PyErr_SetFromErrno(PyExc_OSError);
784#endif
785 return -1;
786 }
787#endif
788
789#if defined(WITH_THREAD) && defined(TRACE_RAW_MALLOC)
790 if (tables_lock == NULL) {
791 tables_lock = PyThread_allocate_lock();
792 if (tables_lock == NULL) {
793 PyErr_SetString(PyExc_RuntimeError, "cannot allocate lock");
794 return -1;
795 }
796 }
797#endif
798
799 tracemalloc_filenames = hashtable_new(0,
800 (_Py_hashtable_hash_func)PyObject_Hash,
801 hashtable_compare_unicode);
802
803 tracemalloc_tracebacks = hashtable_new(0,
804 (_Py_hashtable_hash_func)hashtable_hash_traceback,
805 (_Py_hashtable_compare_func)hashtable_compare_traceback);
806
807 tracemalloc_traces = hashtable_new(sizeof(trace_t),
808 _Py_hashtable_hash_ptr,
809 _Py_hashtable_compare_direct);
810
811 if (tracemalloc_filenames == NULL || tracemalloc_tracebacks == NULL
812 || tracemalloc_traces == NULL)
813 {
814 PyErr_NoMemory();
815 return -1;
816 }
817
818 unknown_filename = PyUnicode_FromString("<unknown>");
819 if (unknown_filename == NULL)
820 return -1;
821 PyUnicode_InternInPlace(&unknown_filename);
822
823 tracemalloc_empty_traceback.nframe = 1;
824 /* borrowed reference */
825 tracemalloc_empty_traceback.frames[0].filename = unknown_filename;
826 tracemalloc_empty_traceback.frames[0].lineno = 0;
827 tracemalloc_empty_traceback.hash = traceback_hash(&tracemalloc_empty_traceback);
828
829 /* Disable tracing allocations until hooks are installed. Set
830 also the reentrant flag to detect bugs: fail with an assertion error
831 if set_reentrant(1) is called while tracing is disabled. */
832 set_reentrant(1);
833
834 tracemalloc_config.initialized = TRACEMALLOC_INITIALIZED;
835 return 0;
836}
837
838static void
839tracemalloc_deinit(void)
840{
841 if (tracemalloc_config.initialized != TRACEMALLOC_INITIALIZED)
842 return;
843 tracemalloc_config.initialized = TRACEMALLOC_FINALIZED;
844
845 tracemalloc_stop();
846
847 /* destroy hash tables */
848 _Py_hashtable_destroy(tracemalloc_traces);
849 _Py_hashtable_destroy(tracemalloc_tracebacks);
850 _Py_hashtable_destroy(tracemalloc_filenames);
851
852#if defined(WITH_THREAD) && defined(TRACE_RAW_MALLOC)
853 if (tables_lock != NULL) {
854 PyThread_free_lock(tables_lock);
855 tables_lock = NULL;
856 }
857#endif
858
859#ifdef REENTRANT_THREADLOCAL
860 PyThread_delete_key(tracemalloc_reentrant_key);
861#endif
862
863 Py_XDECREF(unknown_filename);
864}
865
866static int
Victor Stinnerf28ce602013-11-27 22:27:13 +0100867tracemalloc_start(int max_nframe)
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100868{
869 PyMemAllocator alloc;
Victor Stinnerf28ce602013-11-27 22:27:13 +0100870 size_t size;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100871
872 if (tracemalloc_init() < 0)
873 return -1;
874
875 if (tracemalloc_config.tracing) {
876 /* hook already installed: do nothing */
877 return 0;
878 }
879
Victor Stinnerf28ce602013-11-27 22:27:13 +0100880 assert(1 <= max_nframe && max_nframe <= MAX_NFRAME);
881 tracemalloc_config.max_nframe = max_nframe;
882
883 /* allocate a buffer to store a new traceback */
884 size = TRACEBACK_SIZE(max_nframe);
885 assert(tracemalloc_traceback == NULL);
886 tracemalloc_traceback = raw_malloc(size);
887 if (tracemalloc_traceback == NULL) {
888 PyErr_NoMemory();
889 return -1;
890 }
891
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100892#ifdef TRACE_RAW_MALLOC
893 alloc.malloc = tracemalloc_raw_malloc;
Victor Stinnerdb067af2014-05-02 22:31:14 +0200894 alloc.calloc = tracemalloc_raw_calloc;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100895 alloc.realloc = tracemalloc_raw_realloc;
896 alloc.free = tracemalloc_free;
897
898 alloc.ctx = &allocators.raw;
899 PyMem_GetAllocator(PYMEM_DOMAIN_RAW, &allocators.raw);
900 PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &alloc);
901#endif
902
903 alloc.malloc = tracemalloc_malloc_gil;
Victor Stinnerdb067af2014-05-02 22:31:14 +0200904 alloc.calloc = tracemalloc_calloc_gil;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100905 alloc.realloc = tracemalloc_realloc_gil;
906 alloc.free = tracemalloc_free;
907
908 alloc.ctx = &allocators.mem;
909 PyMem_GetAllocator(PYMEM_DOMAIN_MEM, &allocators.mem);
910 PyMem_SetAllocator(PYMEM_DOMAIN_MEM, &alloc);
911
912 alloc.ctx = &allocators.obj;
913 PyMem_GetAllocator(PYMEM_DOMAIN_OBJ, &allocators.obj);
914 PyMem_SetAllocator(PYMEM_DOMAIN_OBJ, &alloc);
915
916 /* everything is ready: start tracing Python memory allocations */
917 tracemalloc_config.tracing = 1;
918 set_reentrant(0);
919
920 return 0;
921}
922
923static void
924tracemalloc_stop(void)
925{
926 if (!tracemalloc_config.tracing)
927 return;
928
929 /* stop tracing Python memory allocations */
930 tracemalloc_config.tracing = 0;
931
932 /* set the reentrant flag to detect bugs: fail with an assertion error if
933 set_reentrant(1) is called while tracing is disabled. */
934 set_reentrant(1);
935
936 /* unregister the hook on memory allocators */
937#ifdef TRACE_RAW_MALLOC
938 PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &allocators.raw);
939#endif
940 PyMem_SetAllocator(PYMEM_DOMAIN_MEM, &allocators.mem);
941 PyMem_SetAllocator(PYMEM_DOMAIN_OBJ, &allocators.obj);
942
943 /* release memory */
944 tracemalloc_clear_traces();
Victor Stinnerf28ce602013-11-27 22:27:13 +0100945 raw_free(tracemalloc_traceback);
946 tracemalloc_traceback = NULL;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100947}
948
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100949static PyObject*
950lineno_as_obj(int lineno)
951{
952 if (lineno >= 0)
953 return PyLong_FromLong(lineno);
954 else
955 Py_RETURN_NONE;
956}
957
958PyDoc_STRVAR(tracemalloc_is_tracing_doc,
959 "is_tracing()->bool\n"
960 "\n"
961 "True if the tracemalloc module is tracing Python memory allocations,\n"
962 "False otherwise.");
963
964static PyObject*
965py_tracemalloc_is_tracing(PyObject *self)
966{
967 return PyBool_FromLong(tracemalloc_config.tracing);
968}
969
970PyDoc_STRVAR(tracemalloc_clear_traces_doc,
971 "clear_traces()\n"
972 "\n"
973 "Clear traces of memory blocks allocated by Python.");
974
975static PyObject*
976py_tracemalloc_clear_traces(PyObject *self)
977{
978 if (!tracemalloc_config.tracing)
979 Py_RETURN_NONE;
980
981 set_reentrant(1);
982 tracemalloc_clear_traces();
983 set_reentrant(0);
984
985 Py_RETURN_NONE;
986}
987
988static PyObject*
989frame_to_pyobject(frame_t *frame)
990{
991 PyObject *frame_obj, *lineno_obj;
992
993 frame_obj = PyTuple_New(2);
994 if (frame_obj == NULL)
995 return NULL;
996
997 if (frame->filename == NULL)
998 frame->filename = Py_None;
999 Py_INCREF(frame->filename);
1000 PyTuple_SET_ITEM(frame_obj, 0, frame->filename);
1001
1002 assert(frame->lineno >= 0);
1003 lineno_obj = lineno_as_obj(frame->lineno);
1004 if (lineno_obj == NULL) {
1005 Py_DECREF(frame_obj);
1006 return NULL;
1007 }
1008 PyTuple_SET_ITEM(frame_obj, 1, lineno_obj);
1009
1010 return frame_obj;
1011}
1012
1013static PyObject*
1014traceback_to_pyobject(traceback_t *traceback, _Py_hashtable_t *intern_table)
1015{
1016 int i;
1017 PyObject *frames, *frame;
1018
1019 if (intern_table != NULL) {
1020 if (_Py_HASHTABLE_GET(intern_table, traceback, frames)) {
1021 Py_INCREF(frames);
1022 return frames;
1023 }
1024 }
1025
1026 frames = PyTuple_New(traceback->nframe);
1027 if (frames == NULL)
1028 return NULL;
1029
1030 for (i=0; i < traceback->nframe; i++) {
1031 frame = frame_to_pyobject(&traceback->frames[i]);
1032 if (frame == NULL) {
1033 Py_DECREF(frames);
1034 return NULL;
1035 }
1036 PyTuple_SET_ITEM(frames, i, frame);
1037 }
1038
1039 if (intern_table != NULL) {
1040 if (_Py_HASHTABLE_SET(intern_table, traceback, frames) < 0) {
1041 Py_DECREF(frames);
1042 PyErr_NoMemory();
1043 return NULL;
1044 }
1045 /* intern_table keeps a new reference to frames */
1046 Py_INCREF(frames);
1047 }
1048 return frames;
1049}
1050
1051static PyObject*
1052trace_to_pyobject(trace_t *trace, _Py_hashtable_t *intern_tracebacks)
1053{
1054 PyObject *trace_obj = NULL;
1055 PyObject *size, *traceback;
1056
1057 trace_obj = PyTuple_New(2);
1058 if (trace_obj == NULL)
1059 return NULL;
1060
1061 size = PyLong_FromSize_t(trace->size);
1062 if (size == NULL) {
1063 Py_DECREF(trace_obj);
1064 return NULL;
1065 }
1066 PyTuple_SET_ITEM(trace_obj, 0, size);
1067
1068 traceback = traceback_to_pyobject(trace->traceback, intern_tracebacks);
1069 if (traceback == NULL) {
1070 Py_DECREF(trace_obj);
1071 return NULL;
1072 }
1073 PyTuple_SET_ITEM(trace_obj, 1, traceback);
1074
1075 return trace_obj;
1076}
1077
1078typedef struct {
1079 _Py_hashtable_t *traces;
1080 _Py_hashtable_t *tracebacks;
1081 PyObject *list;
1082} get_traces_t;
1083
1084static int
1085tracemalloc_get_traces_fill(_Py_hashtable_entry_t *entry, void *user_data)
1086{
1087 get_traces_t *get_traces = user_data;
1088 trace_t *trace;
1089 PyObject *tracemalloc_obj;
1090 int res;
1091
Victor Stinnerd9a73522014-03-24 22:34:34 +01001092 trace = (trace_t *)_Py_HASHTABLE_ENTRY_DATA(entry);
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001093
1094 tracemalloc_obj = trace_to_pyobject(trace, get_traces->tracebacks);
1095 if (tracemalloc_obj == NULL)
1096 return 1;
1097
1098 res = PyList_Append(get_traces->list, tracemalloc_obj);
1099 Py_DECREF(tracemalloc_obj);
1100 if (res < 0)
1101 return 1;
1102
1103 return 0;
1104}
1105
1106static int
1107tracemalloc_pyobject_decref_cb(_Py_hashtable_entry_t *entry, void *user_data)
1108{
1109 PyObject *obj = (PyObject *)_Py_HASHTABLE_ENTRY_DATA_AS_VOID_P(entry);
1110 Py_DECREF(obj);
1111 return 0;
1112}
1113
1114PyDoc_STRVAR(tracemalloc_get_traces_doc,
Victor Stinner4fbefdb2013-11-25 09:33:18 +01001115 "_get_traces() -> list\n"
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001116 "\n"
1117 "Get traces of all memory blocks allocated by Python.\n"
1118 "Return a list of (size: int, traceback: tuple) tuples.\n"
1119 "traceback is a tuple of (filename: str, lineno: int) tuples.\n"
1120 "\n"
1121 "Return an empty list if the tracemalloc module is disabled.");
1122
1123static PyObject*
1124py_tracemalloc_get_traces(PyObject *self, PyObject *obj)
1125{
1126 get_traces_t get_traces;
1127 int err;
1128
1129 get_traces.traces = NULL;
1130 get_traces.tracebacks = NULL;
1131 get_traces.list = PyList_New(0);
1132 if (get_traces.list == NULL)
1133 goto error;
1134
1135 if (!tracemalloc_config.tracing)
1136 return get_traces.list;
1137
Victor Stinnerde2f1322013-11-26 00:26:23 +01001138 /* the traceback hash table is used temporarily to intern traceback tuple
1139 of (filename, lineno) tuples */
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001140 get_traces.tracebacks = hashtable_new(sizeof(PyObject *),
1141 _Py_hashtable_hash_ptr,
1142 _Py_hashtable_compare_direct);
1143 if (get_traces.tracebacks == NULL) {
1144 PyErr_NoMemory();
1145 goto error;
1146 }
1147
1148 TABLES_LOCK();
1149 get_traces.traces = _Py_hashtable_copy(tracemalloc_traces);
1150 TABLES_UNLOCK();
1151
1152 if (get_traces.traces == NULL) {
1153 PyErr_NoMemory();
1154 goto error;
1155 }
1156
1157 set_reentrant(1);
1158 err = _Py_hashtable_foreach(get_traces.traces,
1159 tracemalloc_get_traces_fill, &get_traces);
1160 set_reentrant(0);
1161 if (err)
1162 goto error;
1163
1164 goto finally;
1165
1166error:
1167 Py_CLEAR(get_traces.list);
1168
1169finally:
1170 if (get_traces.tracebacks != NULL) {
1171 _Py_hashtable_foreach(get_traces.tracebacks,
1172 tracemalloc_pyobject_decref_cb, NULL);
1173 _Py_hashtable_destroy(get_traces.tracebacks);
1174 }
1175 if (get_traces.traces != NULL)
1176 _Py_hashtable_destroy(get_traces.traces);
1177
1178 return get_traces.list;
1179}
1180
1181PyDoc_STRVAR(tracemalloc_get_object_traceback_doc,
Victor Stinner4fbefdb2013-11-25 09:33:18 +01001182 "_get_object_traceback(obj)\n"
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001183 "\n"
1184 "Get the traceback where the Python object obj was allocated.\n"
1185 "Return a tuple of (filename: str, lineno: int) tuples.\n"
1186 "\n"
1187 "Return None if the tracemalloc module is disabled or did not\n"
1188 "trace the allocation of the object.");
1189
1190static PyObject*
1191py_tracemalloc_get_object_traceback(PyObject *self, PyObject *obj)
1192{
1193 PyTypeObject *type;
1194 void *ptr;
1195 trace_t trace;
1196 int found;
1197
1198 if (!tracemalloc_config.tracing)
1199 Py_RETURN_NONE;
1200
1201 type = Py_TYPE(obj);
1202 if (PyType_IS_GC(type))
1203 ptr = (void *)((char *)obj - sizeof(PyGC_Head));
1204 else
1205 ptr = (void *)obj;
1206
1207 TABLES_LOCK();
1208 found = _Py_HASHTABLE_GET(tracemalloc_traces, ptr, trace);
1209 TABLES_UNLOCK();
1210
1211 if (!found)
1212 Py_RETURN_NONE;
1213
1214 return traceback_to_pyobject(trace.traceback, NULL);
1215}
1216
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001217PyDoc_STRVAR(tracemalloc_start_doc,
Victor Stinner3728d6c2013-11-23 12:37:20 +01001218 "start(nframe: int=1)\n"
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001219 "\n"
Victor Stinner3728d6c2013-11-23 12:37:20 +01001220 "Start tracing Python memory allocations. Set also the maximum number \n"
1221 "of frames stored in the traceback of a trace to nframe.");
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001222
1223static PyObject*
Victor Stinner3728d6c2013-11-23 12:37:20 +01001224py_tracemalloc_start(PyObject *self, PyObject *args)
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001225{
Victor Stinner3728d6c2013-11-23 12:37:20 +01001226 Py_ssize_t nframe = 1;
Victor Stinnerf28ce602013-11-27 22:27:13 +01001227 int nframe_int;
Victor Stinner3728d6c2013-11-23 12:37:20 +01001228
1229 if (!PyArg_ParseTuple(args, "|n:start", &nframe))
1230 return NULL;
1231
1232 if (nframe < 1 || nframe > MAX_NFRAME) {
1233 PyErr_Format(PyExc_ValueError,
1234 "the number of frames must be in range [1; %i]",
Victor Stinnerf28ce602013-11-27 22:27:13 +01001235 (int)MAX_NFRAME);
Victor Stinner3728d6c2013-11-23 12:37:20 +01001236 return NULL;
1237 }
Victor Stinnerf28ce602013-11-27 22:27:13 +01001238 nframe_int = Py_SAFE_DOWNCAST(nframe, Py_ssize_t, int);
Victor Stinner3728d6c2013-11-23 12:37:20 +01001239
Victor Stinnerf28ce602013-11-27 22:27:13 +01001240 if (tracemalloc_start(nframe_int) < 0)
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001241 return NULL;
1242
1243 Py_RETURN_NONE;
1244}
1245
1246PyDoc_STRVAR(tracemalloc_stop_doc,
1247 "stop()\n"
1248 "\n"
1249 "Stop tracing Python memory allocations and clear traces\n"
1250 "of memory blocks allocated by Python.");
1251
1252static PyObject*
1253py_tracemalloc_stop(PyObject *self)
1254{
1255 tracemalloc_stop();
1256 Py_RETURN_NONE;
1257}
1258
1259PyDoc_STRVAR(tracemalloc_get_traceback_limit_doc,
1260 "get_traceback_limit() -> int\n"
1261 "\n"
1262 "Get the maximum number of frames stored in the traceback\n"
1263 "of a trace.\n"
1264 "\n"
1265 "By default, a trace of an allocated memory block only stores\n"
1266 "the most recent frame: the limit is 1.");
1267
1268static PyObject*
1269py_tracemalloc_get_traceback_limit(PyObject *self)
1270{
1271 return PyLong_FromLong(tracemalloc_config.max_nframe);
1272}
1273
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001274PyDoc_STRVAR(tracemalloc_get_tracemalloc_memory_doc,
1275 "get_tracemalloc_memory() -> int\n"
1276 "\n"
1277 "Get the memory usage in bytes of the tracemalloc module\n"
1278 "used internally to trace memory allocations.");
1279
1280static PyObject*
1281tracemalloc_get_tracemalloc_memory(PyObject *self)
1282{
1283 size_t size;
1284 PyObject *size_obj;
1285
1286 size = _Py_hashtable_size(tracemalloc_tracebacks);
1287 size += _Py_hashtable_size(tracemalloc_filenames);
1288
1289 TABLES_LOCK();
1290 size += _Py_hashtable_size(tracemalloc_traces);
1291 TABLES_UNLOCK();
1292
1293 size_obj = PyLong_FromSize_t(size);
1294 return Py_BuildValue("N", size_obj);
1295}
1296
1297PyDoc_STRVAR(tracemalloc_get_traced_memory_doc,
Victor Stinner59463d82013-11-26 10:46:06 +01001298 "get_traced_memory() -> (int, int)\n"
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001299 "\n"
Victor Stinner3c0481d2013-11-27 21:39:49 +01001300 "Get the current size and peak size of memory blocks traced\n"
1301 "by the tracemalloc module as a tuple: (current: int, peak: int).");
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001302
1303static PyObject*
1304tracemalloc_get_traced_memory(PyObject *self)
1305{
Victor Stinner3c0481d2013-11-27 21:39:49 +01001306 Py_ssize_t size, peak_size;
1307 PyObject *size_obj, *peak_size_obj;
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001308
1309 if (!tracemalloc_config.tracing)
1310 return Py_BuildValue("ii", 0, 0);
1311
1312 TABLES_LOCK();
1313 size = tracemalloc_traced_memory;
Victor Stinner3c0481d2013-11-27 21:39:49 +01001314 peak_size = tracemalloc_peak_traced_memory;
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001315 TABLES_UNLOCK();
1316
1317 size_obj = PyLong_FromSize_t(size);
Victor Stinner3c0481d2013-11-27 21:39:49 +01001318 peak_size_obj = PyLong_FromSize_t(peak_size);
1319 return Py_BuildValue("NN", size_obj, peak_size_obj);
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001320}
1321
1322static PyMethodDef module_methods[] = {
1323 {"is_tracing", (PyCFunction)py_tracemalloc_is_tracing,
1324 METH_NOARGS, tracemalloc_is_tracing_doc},
1325 {"clear_traces", (PyCFunction)py_tracemalloc_clear_traces,
1326 METH_NOARGS, tracemalloc_clear_traces_doc},
1327 {"_get_traces", (PyCFunction)py_tracemalloc_get_traces,
1328 METH_NOARGS, tracemalloc_get_traces_doc},
1329 {"_get_object_traceback", (PyCFunction)py_tracemalloc_get_object_traceback,
1330 METH_O, tracemalloc_get_object_traceback_doc},
1331 {"start", (PyCFunction)py_tracemalloc_start,
Victor Stinner3728d6c2013-11-23 12:37:20 +01001332 METH_VARARGS, tracemalloc_start_doc},
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001333 {"stop", (PyCFunction)py_tracemalloc_stop,
1334 METH_NOARGS, tracemalloc_stop_doc},
1335 {"get_traceback_limit", (PyCFunction)py_tracemalloc_get_traceback_limit,
1336 METH_NOARGS, tracemalloc_get_traceback_limit_doc},
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001337 {"get_tracemalloc_memory", (PyCFunction)tracemalloc_get_tracemalloc_memory,
1338 METH_NOARGS, tracemalloc_get_tracemalloc_memory_doc},
1339 {"get_traced_memory", (PyCFunction)tracemalloc_get_traced_memory,
1340 METH_NOARGS, tracemalloc_get_traced_memory_doc},
1341
1342 /* sentinel */
1343 {NULL, NULL}
1344};
1345
1346PyDoc_STRVAR(module_doc,
1347"Debug module to trace memory blocks allocated by Python.");
1348
1349static struct PyModuleDef module_def = {
1350 PyModuleDef_HEAD_INIT,
1351 "_tracemalloc",
1352 module_doc,
1353 0, /* non-negative size to be able to unload the module */
1354 module_methods,
1355 NULL,
1356};
1357
1358PyMODINIT_FUNC
1359PyInit__tracemalloc(void)
1360{
1361 PyObject *m;
1362 m = PyModule_Create(&module_def);
1363 if (m == NULL)
1364 return NULL;
1365
1366 if (tracemalloc_init() < 0)
1367 return NULL;
1368
1369 return m;
1370}
1371
1372static int
1373parse_sys_xoptions(PyObject *value)
1374{
1375 PyObject *valuelong;
1376 long nframe;
1377
1378 if (value == Py_True)
1379 return 1;
1380
1381 assert(PyUnicode_Check(value));
1382 if (PyUnicode_GetLength(value) == 0)
1383 return -1;
1384
1385 valuelong = PyLong_FromUnicodeObject(value, 10);
1386 if (valuelong == NULL)
1387 return -1;
1388
1389 nframe = PyLong_AsLong(valuelong);
1390 Py_DECREF(valuelong);
1391 if (nframe == -1 && PyErr_Occurred())
1392 return -1;
1393
1394 if (nframe < 1 || nframe > MAX_NFRAME)
1395 return -1;
1396
1397 return Py_SAFE_DOWNCAST(nframe, long, int);
1398}
1399
1400int
1401_PyTraceMalloc_Init(void)
1402{
1403 char *p;
1404 int nframe;
1405
1406#ifdef WITH_THREAD
1407 assert(PyGILState_Check());
1408#endif
1409
1410 if ((p = Py_GETENV("PYTHONTRACEMALLOC")) && *p != '\0') {
1411 char *endptr = p;
Victor Stinnerf28ce602013-11-27 22:27:13 +01001412 long value;
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001413
Victor Stinner711e27c2013-12-16 23:06:19 +01001414 errno = 0;
Victor Stinnerf28ce602013-11-27 22:27:13 +01001415 value = strtol(p, &endptr, 10);
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001416 if (*endptr != '\0'
1417 || value < 1
1418 || value > MAX_NFRAME
Victor Stinner711e27c2013-12-16 23:06:19 +01001419 || errno == ERANGE)
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001420 {
Victor Stinnerf28ce602013-11-27 22:27:13 +01001421 Py_FatalError("PYTHONTRACEMALLOC: invalid number of frames");
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001422 return -1;
1423 }
1424
1425 nframe = (int)value;
1426 }
1427 else {
1428 PyObject *xoptions, *key, *value;
1429
1430 xoptions = PySys_GetXOptions();
1431 if (xoptions == NULL)
1432 return -1;
1433
1434 key = PyUnicode_FromString("tracemalloc");
1435 if (key == NULL)
1436 return -1;
1437
1438 value = PyDict_GetItemWithError(xoptions, key);
1439 Py_DECREF(key);
1440 if (value == NULL) {
1441 if (PyErr_Occurred())
1442 return -1;
1443
1444 /* -X tracemalloc is not used */
1445 return 0;
1446 }
1447
1448 nframe = parse_sys_xoptions(value);
1449 Py_DECREF(value);
1450 if (nframe < 0) {
Victor Stinnerf28ce602013-11-27 22:27:13 +01001451 Py_FatalError("-X tracemalloc=NFRAME: invalid number of frames");
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001452 }
1453 }
1454
Victor Stinnerf28ce602013-11-27 22:27:13 +01001455 return tracemalloc_start(nframe);
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001456}
1457
Victor Stinnerbe0708f2013-12-01 10:03:26 +01001458void
1459_PyTraceMalloc_Fini(void)
1460{
1461#ifdef WITH_THREAD
1462 assert(PyGILState_Check());
1463#endif
1464 tracemalloc_deinit();
1465}
1466