blob: 796ac0fa33914c404b20b1b37d08c1456cc0d1e8 [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
Serhiy Storchaka6a7b3a72016-04-17 08:32:47 +0300522 This case is very unlikely: a hash entry has just been
Victor Stinner88c29872013-12-04 01:47:46 +0100523 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