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