tracemalloc.c 39 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560
  1. #include "Python.h"
  2. #include "pycore_fileutils.h" // _Py_write_noraise()
  3. #include "pycore_gc.h" // PyGC_Head
  4. #include "pycore_hashtable.h" // _Py_hashtable_t
  5. #include "pycore_object.h" // _PyType_PreHeaderSize
  6. #include "pycore_pymem.h" // _Py_tracemalloc_config
  7. #include "pycore_runtime.h" // _Py_ID()
  8. #include "pycore_traceback.h"
  9. #include <pycore_frame.h>
  10. #include "frameobject.h" // _PyInterpreterFrame_GetLine
  11. #include <stdlib.h> // malloc()
  12. #define tracemalloc_config _PyRuntime.tracemalloc.config
  13. _Py_DECLARE_STR(anon_unknown, "<unknown>");
  14. /* Forward declaration */
  15. static void* raw_malloc(size_t size);
  16. static void raw_free(void *ptr);
  17. #ifdef Py_DEBUG
  18. # define TRACE_DEBUG
  19. #endif
  20. #define TO_PTR(key) ((const void *)(uintptr_t)(key))
  21. #define FROM_PTR(key) ((uintptr_t)(key))
  22. #define allocators _PyRuntime.tracemalloc.allocators
  23. #if defined(TRACE_RAW_MALLOC)
  24. /* This lock is needed because tracemalloc_free() is called without
  25. the GIL held from PyMem_RawFree(). It cannot acquire the lock because it
  26. would introduce a deadlock in _PyThreadState_DeleteCurrent(). */
  27. # define tables_lock _PyRuntime.tracemalloc.tables_lock
  28. # define TABLES_LOCK() PyThread_acquire_lock(tables_lock, 1)
  29. # define TABLES_UNLOCK() PyThread_release_lock(tables_lock)
  30. #else
  31. /* variables are protected by the GIL */
  32. # define TABLES_LOCK()
  33. # define TABLES_UNLOCK()
  34. #endif
  35. #define DEFAULT_DOMAIN 0
  36. typedef struct tracemalloc_frame frame_t;
  37. typedef struct tracemalloc_traceback traceback_t;
  38. #define TRACEBACK_SIZE(NFRAME) \
  39. (sizeof(traceback_t) + sizeof(frame_t) * (NFRAME - 1))
  40. /* The maximum number of frames is either:
  41. - The maximum number of frames we can store in `traceback_t.nframe`
  42. - The maximum memory size_t we can allocate */
  43. static const unsigned long MAX_NFRAME = Py_MIN(UINT16_MAX, ((SIZE_MAX - sizeof(traceback_t)) / sizeof(frame_t) + 1));
  44. #define tracemalloc_empty_traceback _PyRuntime.tracemalloc.empty_traceback
  45. /* Trace of a memory block */
  46. typedef struct {
  47. /* Size of the memory block in bytes */
  48. size_t size;
  49. /* Traceback where the memory block was allocated */
  50. traceback_t *traceback;
  51. } trace_t;
  52. #define tracemalloc_traced_memory _PyRuntime.tracemalloc.traced_memory
  53. #define tracemalloc_peak_traced_memory _PyRuntime.tracemalloc.peak_traced_memory
  54. #define tracemalloc_filenames _PyRuntime.tracemalloc.filenames
  55. #define tracemalloc_traceback _PyRuntime.tracemalloc.traceback
  56. #define tracemalloc_tracebacks _PyRuntime.tracemalloc.tracebacks
  57. #define tracemalloc_traces _PyRuntime.tracemalloc.traces
  58. #define tracemalloc_domains _PyRuntime.tracemalloc.domains
  59. #ifdef TRACE_DEBUG
  60. static void
  61. tracemalloc_error(const char *format, ...)
  62. {
  63. va_list ap;
  64. fprintf(stderr, "tracemalloc: ");
  65. va_start(ap, format);
  66. vfprintf(stderr, format, ap);
  67. va_end(ap);
  68. fprintf(stderr, "\n");
  69. fflush(stderr);
  70. }
  71. #endif
  72. #if defined(TRACE_RAW_MALLOC)
  73. #define REENTRANT_THREADLOCAL
  74. #define tracemalloc_reentrant_key _PyRuntime.tracemalloc.reentrant_key
  75. /* Any non-NULL pointer can be used */
  76. #define REENTRANT Py_True
  77. static int
  78. get_reentrant(void)
  79. {
  80. void *ptr;
  81. assert(PyThread_tss_is_created(&tracemalloc_reentrant_key));
  82. ptr = PyThread_tss_get(&tracemalloc_reentrant_key);
  83. if (ptr != NULL) {
  84. assert(ptr == REENTRANT);
  85. return 1;
  86. }
  87. else
  88. return 0;
  89. }
  90. static void
  91. set_reentrant(int reentrant)
  92. {
  93. assert(reentrant == 0 || reentrant == 1);
  94. assert(PyThread_tss_is_created(&tracemalloc_reentrant_key));
  95. if (reentrant) {
  96. assert(!get_reentrant());
  97. PyThread_tss_set(&tracemalloc_reentrant_key, REENTRANT);
  98. }
  99. else {
  100. assert(get_reentrant());
  101. PyThread_tss_set(&tracemalloc_reentrant_key, NULL);
  102. }
  103. }
  104. #else
  105. /* TRACE_RAW_MALLOC not defined: variable protected by the GIL */
  106. static int tracemalloc_reentrant = 0;
  107. static int
  108. get_reentrant(void)
  109. {
  110. return tracemalloc_reentrant;
  111. }
  112. static void
  113. set_reentrant(int reentrant)
  114. {
  115. assert(reentrant != tracemalloc_reentrant);
  116. tracemalloc_reentrant = reentrant;
  117. }
  118. #endif
  119. static Py_uhash_t
  120. hashtable_hash_pyobject(const void *key)
  121. {
  122. PyObject *obj = (PyObject *)key;
  123. return PyObject_Hash(obj);
  124. }
  125. static int
  126. hashtable_compare_unicode(const void *key1, const void *key2)
  127. {
  128. PyObject *obj1 = (PyObject *)key1;
  129. PyObject *obj2 = (PyObject *)key2;
  130. if (obj1 != NULL && obj2 != NULL) {
  131. return (PyUnicode_Compare(obj1, obj2) == 0);
  132. }
  133. else {
  134. return obj1 == obj2;
  135. }
  136. }
  137. static Py_uhash_t
  138. hashtable_hash_uint(const void *key_raw)
  139. {
  140. unsigned int key = (unsigned int)FROM_PTR(key_raw);
  141. return (Py_uhash_t)key;
  142. }
  143. static _Py_hashtable_t *
  144. hashtable_new(_Py_hashtable_hash_func hash_func,
  145. _Py_hashtable_compare_func compare_func,
  146. _Py_hashtable_destroy_func key_destroy_func,
  147. _Py_hashtable_destroy_func value_destroy_func)
  148. {
  149. _Py_hashtable_allocator_t hashtable_alloc = {malloc, free};
  150. return _Py_hashtable_new_full(hash_func, compare_func,
  151. key_destroy_func, value_destroy_func,
  152. &hashtable_alloc);
  153. }
  154. static void*
  155. raw_malloc(size_t size)
  156. {
  157. return allocators.raw.malloc(allocators.raw.ctx, size);
  158. }
  159. static void
  160. raw_free(void *ptr)
  161. {
  162. allocators.raw.free(allocators.raw.ctx, ptr);
  163. }
  164. static Py_uhash_t
  165. hashtable_hash_traceback(const void *key)
  166. {
  167. const traceback_t *traceback = (const traceback_t *)key;
  168. return traceback->hash;
  169. }
  170. static int
  171. hashtable_compare_traceback(const void *key1, const void *key2)
  172. {
  173. const traceback_t *traceback1 = (const traceback_t *)key1;
  174. const traceback_t *traceback2 = (const traceback_t *)key2;
  175. if (traceback1->nframe != traceback2->nframe) {
  176. return 0;
  177. }
  178. if (traceback1->total_nframe != traceback2->total_nframe) {
  179. return 0;
  180. }
  181. for (int i=0; i < traceback1->nframe; i++) {
  182. const frame_t *frame1 = &traceback1->frames[i];
  183. const frame_t *frame2 = &traceback2->frames[i];
  184. if (frame1->lineno != frame2->lineno) {
  185. return 0;
  186. }
  187. if (frame1->filename != frame2->filename) {
  188. assert(PyUnicode_Compare(frame1->filename, frame2->filename) != 0);
  189. return 0;
  190. }
  191. }
  192. return 1;
  193. }
  194. static void
  195. tracemalloc_get_frame(_PyInterpreterFrame *pyframe, frame_t *frame)
  196. {
  197. frame->filename = &_Py_STR(anon_unknown);
  198. int lineno = PyUnstable_InterpreterFrame_GetLine(pyframe);
  199. if (lineno < 0) {
  200. lineno = 0;
  201. }
  202. frame->lineno = (unsigned int)lineno;
  203. PyObject *filename = pyframe->f_code->co_filename;
  204. if (filename == NULL) {
  205. #ifdef TRACE_DEBUG
  206. tracemalloc_error("failed to get the filename of the code object");
  207. #endif
  208. return;
  209. }
  210. if (!PyUnicode_Check(filename)) {
  211. #ifdef TRACE_DEBUG
  212. tracemalloc_error("filename is not a unicode string");
  213. #endif
  214. return;
  215. }
  216. if (!PyUnicode_IS_READY(filename)) {
  217. /* Don't make a Unicode string ready to avoid reentrant calls
  218. to tracemalloc_malloc() or tracemalloc_realloc() */
  219. #ifdef TRACE_DEBUG
  220. tracemalloc_error("filename is not a ready unicode string");
  221. #endif
  222. return;
  223. }
  224. /* intern the filename */
  225. _Py_hashtable_entry_t *entry;
  226. entry = _Py_hashtable_get_entry(tracemalloc_filenames, filename);
  227. if (entry != NULL) {
  228. filename = (PyObject *)entry->key;
  229. }
  230. else {
  231. /* tracemalloc_filenames is responsible to keep a reference
  232. to the filename */
  233. if (_Py_hashtable_set(tracemalloc_filenames, Py_NewRef(filename),
  234. NULL) < 0) {
  235. Py_DECREF(filename);
  236. #ifdef TRACE_DEBUG
  237. tracemalloc_error("failed to intern the filename");
  238. #endif
  239. return;
  240. }
  241. }
  242. /* the tracemalloc_filenames table keeps a reference to the filename */
  243. frame->filename = filename;
  244. }
  245. static Py_uhash_t
  246. traceback_hash(traceback_t *traceback)
  247. {
  248. /* code based on tuplehash() of Objects/tupleobject.c */
  249. Py_uhash_t x, y; /* Unsigned for defined overflow behavior. */
  250. int len = traceback->nframe;
  251. Py_uhash_t mult = _PyHASH_MULTIPLIER;
  252. frame_t *frame;
  253. x = 0x345678UL;
  254. frame = traceback->frames;
  255. while (--len >= 0) {
  256. y = (Py_uhash_t)PyObject_Hash(frame->filename);
  257. y ^= (Py_uhash_t)frame->lineno;
  258. frame++;
  259. x = (x ^ y) * mult;
  260. /* the cast might truncate len; that doesn't change hash stability */
  261. mult += (Py_uhash_t)(82520UL + len + len);
  262. }
  263. x ^= traceback->total_nframe;
  264. x += 97531UL;
  265. return x;
  266. }
  267. static void
  268. traceback_get_frames(traceback_t *traceback)
  269. {
  270. PyThreadState *tstate = PyGILState_GetThisThreadState();
  271. if (tstate == NULL) {
  272. #ifdef TRACE_DEBUG
  273. tracemalloc_error("failed to get the current thread state");
  274. #endif
  275. return;
  276. }
  277. _PyInterpreterFrame *pyframe = _PyThreadState_GetFrame(tstate);
  278. while (pyframe) {
  279. if (traceback->nframe < tracemalloc_config.max_nframe) {
  280. tracemalloc_get_frame(pyframe, &traceback->frames[traceback->nframe]);
  281. assert(traceback->frames[traceback->nframe].filename != NULL);
  282. traceback->nframe++;
  283. }
  284. if (traceback->total_nframe < UINT16_MAX) {
  285. traceback->total_nframe++;
  286. }
  287. pyframe = _PyFrame_GetFirstComplete(pyframe->previous);
  288. }
  289. }
  290. static traceback_t *
  291. traceback_new(void)
  292. {
  293. traceback_t *traceback;
  294. _Py_hashtable_entry_t *entry;
  295. assert(PyGILState_Check());
  296. /* get frames */
  297. traceback = tracemalloc_traceback;
  298. traceback->nframe = 0;
  299. traceback->total_nframe = 0;
  300. traceback_get_frames(traceback);
  301. if (traceback->nframe == 0)
  302. return &tracemalloc_empty_traceback;
  303. traceback->hash = traceback_hash(traceback);
  304. /* intern the traceback */
  305. entry = _Py_hashtable_get_entry(tracemalloc_tracebacks, traceback);
  306. if (entry != NULL) {
  307. traceback = (traceback_t *)entry->key;
  308. }
  309. else {
  310. traceback_t *copy;
  311. size_t traceback_size;
  312. traceback_size = TRACEBACK_SIZE(traceback->nframe);
  313. copy = raw_malloc(traceback_size);
  314. if (copy == NULL) {
  315. #ifdef TRACE_DEBUG
  316. tracemalloc_error("failed to intern the traceback: malloc failed");
  317. #endif
  318. return NULL;
  319. }
  320. memcpy(copy, traceback, traceback_size);
  321. if (_Py_hashtable_set(tracemalloc_tracebacks, copy, NULL) < 0) {
  322. raw_free(copy);
  323. #ifdef TRACE_DEBUG
  324. tracemalloc_error("failed to intern the traceback: putdata failed");
  325. #endif
  326. return NULL;
  327. }
  328. traceback = copy;
  329. }
  330. return traceback;
  331. }
  332. static _Py_hashtable_t*
  333. tracemalloc_create_traces_table(void)
  334. {
  335. return hashtable_new(_Py_hashtable_hash_ptr,
  336. _Py_hashtable_compare_direct,
  337. NULL, raw_free);
  338. }
  339. static _Py_hashtable_t*
  340. tracemalloc_create_domains_table(void)
  341. {
  342. return hashtable_new(hashtable_hash_uint,
  343. _Py_hashtable_compare_direct,
  344. NULL,
  345. (_Py_hashtable_destroy_func)_Py_hashtable_destroy);
  346. }
  347. static _Py_hashtable_t*
  348. tracemalloc_get_traces_table(unsigned int domain)
  349. {
  350. if (domain == DEFAULT_DOMAIN) {
  351. return tracemalloc_traces;
  352. }
  353. else {
  354. return _Py_hashtable_get(tracemalloc_domains, TO_PTR(domain));
  355. }
  356. }
  357. static void
  358. tracemalloc_remove_trace(unsigned int domain, uintptr_t ptr)
  359. {
  360. assert(tracemalloc_config.tracing);
  361. _Py_hashtable_t *traces = tracemalloc_get_traces_table(domain);
  362. if (!traces) {
  363. return;
  364. }
  365. trace_t *trace = _Py_hashtable_steal(traces, TO_PTR(ptr));
  366. if (!trace) {
  367. return;
  368. }
  369. assert(tracemalloc_traced_memory >= trace->size);
  370. tracemalloc_traced_memory -= trace->size;
  371. raw_free(trace);
  372. }
  373. #define REMOVE_TRACE(ptr) \
  374. tracemalloc_remove_trace(DEFAULT_DOMAIN, (uintptr_t)(ptr))
  375. static int
  376. tracemalloc_add_trace(unsigned int domain, uintptr_t ptr,
  377. size_t size)
  378. {
  379. assert(tracemalloc_config.tracing);
  380. traceback_t *traceback = traceback_new();
  381. if (traceback == NULL) {
  382. return -1;
  383. }
  384. _Py_hashtable_t *traces = tracemalloc_get_traces_table(domain);
  385. if (traces == NULL) {
  386. traces = tracemalloc_create_traces_table();
  387. if (traces == NULL) {
  388. return -1;
  389. }
  390. if (_Py_hashtable_set(tracemalloc_domains, TO_PTR(domain), traces) < 0) {
  391. _Py_hashtable_destroy(traces);
  392. return -1;
  393. }
  394. }
  395. trace_t *trace = _Py_hashtable_get(traces, TO_PTR(ptr));
  396. if (trace != NULL) {
  397. /* the memory block is already tracked */
  398. assert(tracemalloc_traced_memory >= trace->size);
  399. tracemalloc_traced_memory -= trace->size;
  400. trace->size = size;
  401. trace->traceback = traceback;
  402. }
  403. else {
  404. trace = raw_malloc(sizeof(trace_t));
  405. if (trace == NULL) {
  406. return -1;
  407. }
  408. trace->size = size;
  409. trace->traceback = traceback;
  410. int res = _Py_hashtable_set(traces, TO_PTR(ptr), trace);
  411. if (res != 0) {
  412. raw_free(trace);
  413. return res;
  414. }
  415. }
  416. assert(tracemalloc_traced_memory <= SIZE_MAX - size);
  417. tracemalloc_traced_memory += size;
  418. if (tracemalloc_traced_memory > tracemalloc_peak_traced_memory) {
  419. tracemalloc_peak_traced_memory = tracemalloc_traced_memory;
  420. }
  421. return 0;
  422. }
  423. #define ADD_TRACE(ptr, size) \
  424. tracemalloc_add_trace(DEFAULT_DOMAIN, (uintptr_t)(ptr), size)
  425. static void*
  426. tracemalloc_alloc(int use_calloc, void *ctx, size_t nelem, size_t elsize)
  427. {
  428. PyMemAllocatorEx *alloc = (PyMemAllocatorEx *)ctx;
  429. void *ptr;
  430. assert(elsize == 0 || nelem <= SIZE_MAX / elsize);
  431. if (use_calloc)
  432. ptr = alloc->calloc(alloc->ctx, nelem, elsize);
  433. else
  434. ptr = alloc->malloc(alloc->ctx, nelem * elsize);
  435. if (ptr == NULL)
  436. return NULL;
  437. TABLES_LOCK();
  438. if (ADD_TRACE(ptr, nelem * elsize) < 0) {
  439. /* Failed to allocate a trace for the new memory block */
  440. TABLES_UNLOCK();
  441. alloc->free(alloc->ctx, ptr);
  442. return NULL;
  443. }
  444. TABLES_UNLOCK();
  445. return ptr;
  446. }
  447. static void*
  448. tracemalloc_realloc(void *ctx, void *ptr, size_t new_size)
  449. {
  450. PyMemAllocatorEx *alloc = (PyMemAllocatorEx *)ctx;
  451. void *ptr2;
  452. ptr2 = alloc->realloc(alloc->ctx, ptr, new_size);
  453. if (ptr2 == NULL)
  454. return NULL;
  455. if (ptr != NULL) {
  456. /* an existing memory block has been resized */
  457. TABLES_LOCK();
  458. /* tracemalloc_add_trace() updates the trace if there is already
  459. a trace at address ptr2 */
  460. if (ptr2 != ptr) {
  461. REMOVE_TRACE(ptr);
  462. }
  463. if (ADD_TRACE(ptr2, new_size) < 0) {
  464. /* Memory allocation failed. The error cannot be reported to
  465. the caller, because realloc() may already have shrunk the
  466. memory block and so removed bytes.
  467. This case is very unlikely: a hash entry has just been
  468. released, so the hash table should have at least one free entry.
  469. The GIL and the table lock ensures that only one thread is
  470. allocating memory. */
  471. Py_FatalError("tracemalloc_realloc() failed to allocate a trace");
  472. }
  473. TABLES_UNLOCK();
  474. }
  475. else {
  476. /* new allocation */
  477. TABLES_LOCK();
  478. if (ADD_TRACE(ptr2, new_size) < 0) {
  479. /* Failed to allocate a trace for the new memory block */
  480. TABLES_UNLOCK();
  481. alloc->free(alloc->ctx, ptr2);
  482. return NULL;
  483. }
  484. TABLES_UNLOCK();
  485. }
  486. return ptr2;
  487. }
  488. static void
  489. tracemalloc_free(void *ctx, void *ptr)
  490. {
  491. PyMemAllocatorEx *alloc = (PyMemAllocatorEx *)ctx;
  492. if (ptr == NULL)
  493. return;
  494. /* GIL cannot be locked in PyMem_RawFree() because it would introduce
  495. a deadlock in _PyThreadState_DeleteCurrent(). */
  496. alloc->free(alloc->ctx, ptr);
  497. TABLES_LOCK();
  498. REMOVE_TRACE(ptr);
  499. TABLES_UNLOCK();
  500. }
  501. static void*
  502. tracemalloc_alloc_gil(int use_calloc, void *ctx, size_t nelem, size_t elsize)
  503. {
  504. void *ptr;
  505. if (get_reentrant()) {
  506. PyMemAllocatorEx *alloc = (PyMemAllocatorEx *)ctx;
  507. if (use_calloc)
  508. return alloc->calloc(alloc->ctx, nelem, elsize);
  509. else
  510. return alloc->malloc(alloc->ctx, nelem * elsize);
  511. }
  512. /* Ignore reentrant call. PyObjet_Malloc() calls PyMem_Malloc() for
  513. allocations larger than 512 bytes, don't trace the same memory
  514. allocation twice. */
  515. set_reentrant(1);
  516. ptr = tracemalloc_alloc(use_calloc, ctx, nelem, elsize);
  517. set_reentrant(0);
  518. return ptr;
  519. }
  520. static void*
  521. tracemalloc_malloc_gil(void *ctx, size_t size)
  522. {
  523. return tracemalloc_alloc_gil(0, ctx, 1, size);
  524. }
  525. static void*
  526. tracemalloc_calloc_gil(void *ctx, size_t nelem, size_t elsize)
  527. {
  528. return tracemalloc_alloc_gil(1, ctx, nelem, elsize);
  529. }
  530. static void*
  531. tracemalloc_realloc_gil(void *ctx, void *ptr, size_t new_size)
  532. {
  533. void *ptr2;
  534. if (get_reentrant()) {
  535. /* Reentrant call to PyMem_Realloc() and PyMem_RawRealloc().
  536. Example: PyMem_RawRealloc() is called internally by pymalloc
  537. (_PyObject_Malloc() and _PyObject_Realloc()) to allocate a new
  538. arena (new_arena()). */
  539. PyMemAllocatorEx *alloc = (PyMemAllocatorEx *)ctx;
  540. ptr2 = alloc->realloc(alloc->ctx, ptr, new_size);
  541. if (ptr2 != NULL && ptr != NULL) {
  542. TABLES_LOCK();
  543. REMOVE_TRACE(ptr);
  544. TABLES_UNLOCK();
  545. }
  546. return ptr2;
  547. }
  548. /* Ignore reentrant call. PyObjet_Realloc() calls PyMem_Realloc() for
  549. allocations larger than 512 bytes. Don't trace the same memory
  550. allocation twice. */
  551. set_reentrant(1);
  552. ptr2 = tracemalloc_realloc(ctx, ptr, new_size);
  553. set_reentrant(0);
  554. return ptr2;
  555. }
  556. #ifdef TRACE_RAW_MALLOC
  557. static void*
  558. tracemalloc_raw_alloc(int use_calloc, void *ctx, size_t nelem, size_t elsize)
  559. {
  560. PyGILState_STATE gil_state;
  561. void *ptr;
  562. if (get_reentrant()) {
  563. PyMemAllocatorEx *alloc = (PyMemAllocatorEx *)ctx;
  564. if (use_calloc)
  565. return alloc->calloc(alloc->ctx, nelem, elsize);
  566. else
  567. return alloc->malloc(alloc->ctx, nelem * elsize);
  568. }
  569. /* Ignore reentrant call. PyGILState_Ensure() may call PyMem_RawMalloc()
  570. indirectly which would call PyGILState_Ensure() if reentrant are not
  571. disabled. */
  572. set_reentrant(1);
  573. gil_state = PyGILState_Ensure();
  574. ptr = tracemalloc_alloc(use_calloc, ctx, nelem, elsize);
  575. PyGILState_Release(gil_state);
  576. set_reentrant(0);
  577. return ptr;
  578. }
  579. static void*
  580. tracemalloc_raw_malloc(void *ctx, size_t size)
  581. {
  582. return tracemalloc_raw_alloc(0, ctx, 1, size);
  583. }
  584. static void*
  585. tracemalloc_raw_calloc(void *ctx, size_t nelem, size_t elsize)
  586. {
  587. return tracemalloc_raw_alloc(1, ctx, nelem, elsize);
  588. }
  589. static void*
  590. tracemalloc_raw_realloc(void *ctx, void *ptr, size_t new_size)
  591. {
  592. PyGILState_STATE gil_state;
  593. void *ptr2;
  594. if (get_reentrant()) {
  595. /* Reentrant call to PyMem_RawRealloc(). */
  596. PyMemAllocatorEx *alloc = (PyMemAllocatorEx *)ctx;
  597. ptr2 = alloc->realloc(alloc->ctx, ptr, new_size);
  598. if (ptr2 != NULL && ptr != NULL) {
  599. TABLES_LOCK();
  600. REMOVE_TRACE(ptr);
  601. TABLES_UNLOCK();
  602. }
  603. return ptr2;
  604. }
  605. /* Ignore reentrant call. PyGILState_Ensure() may call PyMem_RawMalloc()
  606. indirectly which would call PyGILState_Ensure() if reentrant calls are
  607. not disabled. */
  608. set_reentrant(1);
  609. gil_state = PyGILState_Ensure();
  610. ptr2 = tracemalloc_realloc(ctx, ptr, new_size);
  611. PyGILState_Release(gil_state);
  612. set_reentrant(0);
  613. return ptr2;
  614. }
  615. #endif /* TRACE_RAW_MALLOC */
  616. static void
  617. tracemalloc_clear_filename(void *value)
  618. {
  619. PyObject *filename = (PyObject *)value;
  620. Py_DECREF(filename);
  621. }
  622. /* reentrant flag must be set to call this function and GIL must be held */
  623. static void
  624. tracemalloc_clear_traces(void)
  625. {
  626. /* The GIL protects variables against concurrent access */
  627. assert(PyGILState_Check());
  628. TABLES_LOCK();
  629. _Py_hashtable_clear(tracemalloc_traces);
  630. _Py_hashtable_clear(tracemalloc_domains);
  631. tracemalloc_traced_memory = 0;
  632. tracemalloc_peak_traced_memory = 0;
  633. TABLES_UNLOCK();
  634. _Py_hashtable_clear(tracemalloc_tracebacks);
  635. _Py_hashtable_clear(tracemalloc_filenames);
  636. }
  637. int
  638. _PyTraceMalloc_Init(void)
  639. {
  640. if (tracemalloc_config.initialized == TRACEMALLOC_FINALIZED) {
  641. PyErr_SetString(PyExc_RuntimeError,
  642. "the tracemalloc module has been unloaded");
  643. return -1;
  644. }
  645. if (tracemalloc_config.initialized == TRACEMALLOC_INITIALIZED)
  646. return 0;
  647. PyMem_GetAllocator(PYMEM_DOMAIN_RAW, &allocators.raw);
  648. #ifdef REENTRANT_THREADLOCAL
  649. if (PyThread_tss_create(&tracemalloc_reentrant_key) != 0) {
  650. #ifdef MS_WINDOWS
  651. PyErr_SetFromWindowsErr(0);
  652. #else
  653. PyErr_SetFromErrno(PyExc_OSError);
  654. #endif
  655. return -1;
  656. }
  657. #endif
  658. #if defined(TRACE_RAW_MALLOC)
  659. if (tables_lock == NULL) {
  660. tables_lock = PyThread_allocate_lock();
  661. if (tables_lock == NULL) {
  662. PyErr_SetString(PyExc_RuntimeError, "cannot allocate lock");
  663. return -1;
  664. }
  665. }
  666. #endif
  667. tracemalloc_filenames = hashtable_new(hashtable_hash_pyobject,
  668. hashtable_compare_unicode,
  669. tracemalloc_clear_filename, NULL);
  670. tracemalloc_tracebacks = hashtable_new(hashtable_hash_traceback,
  671. hashtable_compare_traceback,
  672. raw_free, NULL);
  673. tracemalloc_traces = tracemalloc_create_traces_table();
  674. tracemalloc_domains = tracemalloc_create_domains_table();
  675. if (tracemalloc_filenames == NULL || tracemalloc_tracebacks == NULL
  676. || tracemalloc_traces == NULL || tracemalloc_domains == NULL) {
  677. PyErr_NoMemory();
  678. return -1;
  679. }
  680. tracemalloc_empty_traceback.nframe = 1;
  681. tracemalloc_empty_traceback.total_nframe = 1;
  682. /* borrowed reference */
  683. tracemalloc_empty_traceback.frames[0].filename = &_Py_STR(anon_unknown);
  684. tracemalloc_empty_traceback.frames[0].lineno = 0;
  685. tracemalloc_empty_traceback.hash = traceback_hash(&tracemalloc_empty_traceback);
  686. tracemalloc_config.initialized = TRACEMALLOC_INITIALIZED;
  687. return 0;
  688. }
  689. static void
  690. tracemalloc_deinit(void)
  691. {
  692. if (tracemalloc_config.initialized != TRACEMALLOC_INITIALIZED)
  693. return;
  694. tracemalloc_config.initialized = TRACEMALLOC_FINALIZED;
  695. _PyTraceMalloc_Stop();
  696. /* destroy hash tables */
  697. _Py_hashtable_destroy(tracemalloc_domains);
  698. _Py_hashtable_destroy(tracemalloc_traces);
  699. _Py_hashtable_destroy(tracemalloc_tracebacks);
  700. _Py_hashtable_destroy(tracemalloc_filenames);
  701. #if defined(TRACE_RAW_MALLOC)
  702. if (tables_lock != NULL) {
  703. PyThread_free_lock(tables_lock);
  704. tables_lock = NULL;
  705. }
  706. #endif
  707. #ifdef REENTRANT_THREADLOCAL
  708. PyThread_tss_delete(&tracemalloc_reentrant_key);
  709. #endif
  710. }
  711. int
  712. _PyTraceMalloc_Start(int max_nframe)
  713. {
  714. PyMemAllocatorEx alloc;
  715. size_t size;
  716. if (max_nframe < 1 || (unsigned long) max_nframe > MAX_NFRAME) {
  717. PyErr_Format(PyExc_ValueError,
  718. "the number of frames must be in range [1; %lu]",
  719. MAX_NFRAME);
  720. return -1;
  721. }
  722. if (_PyTraceMalloc_Init() < 0) {
  723. return -1;
  724. }
  725. if (tracemalloc_config.tracing) {
  726. /* hook already installed: do nothing */
  727. return 0;
  728. }
  729. tracemalloc_config.max_nframe = max_nframe;
  730. /* allocate a buffer to store a new traceback */
  731. size = TRACEBACK_SIZE(max_nframe);
  732. assert(tracemalloc_traceback == NULL);
  733. tracemalloc_traceback = raw_malloc(size);
  734. if (tracemalloc_traceback == NULL) {
  735. PyErr_NoMemory();
  736. return -1;
  737. }
  738. #ifdef TRACE_RAW_MALLOC
  739. alloc.malloc = tracemalloc_raw_malloc;
  740. alloc.calloc = tracemalloc_raw_calloc;
  741. alloc.realloc = tracemalloc_raw_realloc;
  742. alloc.free = tracemalloc_free;
  743. alloc.ctx = &allocators.raw;
  744. PyMem_GetAllocator(PYMEM_DOMAIN_RAW, &allocators.raw);
  745. PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &alloc);
  746. #endif
  747. alloc.malloc = tracemalloc_malloc_gil;
  748. alloc.calloc = tracemalloc_calloc_gil;
  749. alloc.realloc = tracemalloc_realloc_gil;
  750. alloc.free = tracemalloc_free;
  751. alloc.ctx = &allocators.mem;
  752. PyMem_GetAllocator(PYMEM_DOMAIN_MEM, &allocators.mem);
  753. PyMem_SetAllocator(PYMEM_DOMAIN_MEM, &alloc);
  754. alloc.ctx = &allocators.obj;
  755. PyMem_GetAllocator(PYMEM_DOMAIN_OBJ, &allocators.obj);
  756. PyMem_SetAllocator(PYMEM_DOMAIN_OBJ, &alloc);
  757. /* everything is ready: start tracing Python memory allocations */
  758. tracemalloc_config.tracing = 1;
  759. return 0;
  760. }
  761. void
  762. _PyTraceMalloc_Stop(void)
  763. {
  764. if (!tracemalloc_config.tracing)
  765. return;
  766. /* stop tracing Python memory allocations */
  767. tracemalloc_config.tracing = 0;
  768. /* unregister the hook on memory allocators */
  769. #ifdef TRACE_RAW_MALLOC
  770. PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &allocators.raw);
  771. #endif
  772. PyMem_SetAllocator(PYMEM_DOMAIN_MEM, &allocators.mem);
  773. PyMem_SetAllocator(PYMEM_DOMAIN_OBJ, &allocators.obj);
  774. tracemalloc_clear_traces();
  775. /* release memory */
  776. raw_free(tracemalloc_traceback);
  777. tracemalloc_traceback = NULL;
  778. }
  779. static PyObject*
  780. frame_to_pyobject(frame_t *frame)
  781. {
  782. PyObject *frame_obj, *lineno_obj;
  783. frame_obj = PyTuple_New(2);
  784. if (frame_obj == NULL)
  785. return NULL;
  786. PyTuple_SET_ITEM(frame_obj, 0, Py_NewRef(frame->filename));
  787. lineno_obj = PyLong_FromUnsignedLong(frame->lineno);
  788. if (lineno_obj == NULL) {
  789. Py_DECREF(frame_obj);
  790. return NULL;
  791. }
  792. PyTuple_SET_ITEM(frame_obj, 1, lineno_obj);
  793. return frame_obj;
  794. }
  795. static PyObject*
  796. traceback_to_pyobject(traceback_t *traceback, _Py_hashtable_t *intern_table)
  797. {
  798. PyObject *frames;
  799. if (intern_table != NULL) {
  800. frames = _Py_hashtable_get(intern_table, (const void *)traceback);
  801. if (frames) {
  802. return Py_NewRef(frames);
  803. }
  804. }
  805. frames = PyTuple_New(traceback->nframe);
  806. if (frames == NULL)
  807. return NULL;
  808. for (int i=0; i < traceback->nframe; i++) {
  809. PyObject *frame = frame_to_pyobject(&traceback->frames[i]);
  810. if (frame == NULL) {
  811. Py_DECREF(frames);
  812. return NULL;
  813. }
  814. PyTuple_SET_ITEM(frames, i, frame);
  815. }
  816. if (intern_table != NULL) {
  817. if (_Py_hashtable_set(intern_table, traceback, frames) < 0) {
  818. Py_DECREF(frames);
  819. PyErr_NoMemory();
  820. return NULL;
  821. }
  822. /* intern_table keeps a new reference to frames */
  823. Py_INCREF(frames);
  824. }
  825. return frames;
  826. }
  827. static PyObject*
  828. trace_to_pyobject(unsigned int domain, const trace_t *trace,
  829. _Py_hashtable_t *intern_tracebacks)
  830. {
  831. PyObject *trace_obj = NULL;
  832. PyObject *obj;
  833. trace_obj = PyTuple_New(4);
  834. if (trace_obj == NULL)
  835. return NULL;
  836. obj = PyLong_FromSize_t(domain);
  837. if (obj == NULL) {
  838. Py_DECREF(trace_obj);
  839. return NULL;
  840. }
  841. PyTuple_SET_ITEM(trace_obj, 0, obj);
  842. obj = PyLong_FromSize_t(trace->size);
  843. if (obj == NULL) {
  844. Py_DECREF(trace_obj);
  845. return NULL;
  846. }
  847. PyTuple_SET_ITEM(trace_obj, 1, obj);
  848. obj = traceback_to_pyobject(trace->traceback, intern_tracebacks);
  849. if (obj == NULL) {
  850. Py_DECREF(trace_obj);
  851. return NULL;
  852. }
  853. PyTuple_SET_ITEM(trace_obj, 2, obj);
  854. obj = PyLong_FromUnsignedLong(trace->traceback->total_nframe);
  855. if (obj == NULL) {
  856. Py_DECREF(trace_obj);
  857. return NULL;
  858. }
  859. PyTuple_SET_ITEM(trace_obj, 3, obj);
  860. return trace_obj;
  861. }
  862. typedef struct {
  863. _Py_hashtable_t *traces;
  864. _Py_hashtable_t *domains;
  865. _Py_hashtable_t *tracebacks;
  866. PyObject *list;
  867. unsigned int domain;
  868. } get_traces_t;
  869. static int
  870. tracemalloc_copy_trace(_Py_hashtable_t *traces,
  871. const void *key, const void *value,
  872. void *user_data)
  873. {
  874. _Py_hashtable_t *traces2 = (_Py_hashtable_t *)user_data;
  875. trace_t *trace = (trace_t *)value;
  876. trace_t *trace2 = raw_malloc(sizeof(trace_t));
  877. if (trace2 == NULL) {
  878. return -1;
  879. }
  880. *trace2 = *trace;
  881. if (_Py_hashtable_set(traces2, key, trace2) < 0) {
  882. raw_free(trace2);
  883. return -1;
  884. }
  885. return 0;
  886. }
  887. static _Py_hashtable_t*
  888. tracemalloc_copy_traces(_Py_hashtable_t *traces)
  889. {
  890. _Py_hashtable_t *traces2 = tracemalloc_create_traces_table();
  891. if (traces2 == NULL) {
  892. return NULL;
  893. }
  894. int err = _Py_hashtable_foreach(traces,
  895. tracemalloc_copy_trace,
  896. traces2);
  897. if (err) {
  898. _Py_hashtable_destroy(traces2);
  899. return NULL;
  900. }
  901. return traces2;
  902. }
  903. static int
  904. tracemalloc_copy_domain(_Py_hashtable_t *domains,
  905. const void *key, const void *value,
  906. void *user_data)
  907. {
  908. _Py_hashtable_t *domains2 = (_Py_hashtable_t *)user_data;
  909. unsigned int domain = (unsigned int)FROM_PTR(key);
  910. _Py_hashtable_t *traces = (_Py_hashtable_t *)value;
  911. _Py_hashtable_t *traces2 = tracemalloc_copy_traces(traces);
  912. if (traces2 == NULL) {
  913. return -1;
  914. }
  915. if (_Py_hashtable_set(domains2, TO_PTR(domain), traces2) < 0) {
  916. _Py_hashtable_destroy(traces2);
  917. return -1;
  918. }
  919. return 0;
  920. }
  921. static _Py_hashtable_t*
  922. tracemalloc_copy_domains(_Py_hashtable_t *domains)
  923. {
  924. _Py_hashtable_t *domains2 = tracemalloc_create_domains_table();
  925. if (domains2 == NULL) {
  926. return NULL;
  927. }
  928. int err = _Py_hashtable_foreach(domains,
  929. tracemalloc_copy_domain,
  930. domains2);
  931. if (err) {
  932. _Py_hashtable_destroy(domains2);
  933. return NULL;
  934. }
  935. return domains2;
  936. }
  937. static int
  938. tracemalloc_get_traces_fill(_Py_hashtable_t *traces,
  939. const void *key, const void *value,
  940. void *user_data)
  941. {
  942. get_traces_t *get_traces = user_data;
  943. const trace_t *trace = (const trace_t *)value;
  944. PyObject *tuple = trace_to_pyobject(get_traces->domain, trace,
  945. get_traces->tracebacks);
  946. if (tuple == NULL) {
  947. return 1;
  948. }
  949. int res = PyList_Append(get_traces->list, tuple);
  950. Py_DECREF(tuple);
  951. if (res < 0) {
  952. return 1;
  953. }
  954. return 0;
  955. }
  956. static int
  957. tracemalloc_get_traces_domain(_Py_hashtable_t *domains,
  958. const void *key, const void *value,
  959. void *user_data)
  960. {
  961. get_traces_t *get_traces = user_data;
  962. unsigned int domain = (unsigned int)FROM_PTR(key);
  963. _Py_hashtable_t *traces = (_Py_hashtable_t *)value;
  964. get_traces->domain = domain;
  965. return _Py_hashtable_foreach(traces,
  966. tracemalloc_get_traces_fill,
  967. get_traces);
  968. }
  969. static void
  970. tracemalloc_pyobject_decref(void *value)
  971. {
  972. PyObject *obj = (PyObject *)value;
  973. Py_DECREF(obj);
  974. }
  975. static traceback_t*
  976. tracemalloc_get_traceback(unsigned int domain, uintptr_t ptr)
  977. {
  978. if (!tracemalloc_config.tracing)
  979. return NULL;
  980. trace_t *trace;
  981. TABLES_LOCK();
  982. _Py_hashtable_t *traces = tracemalloc_get_traces_table(domain);
  983. if (traces) {
  984. trace = _Py_hashtable_get(traces, TO_PTR(ptr));
  985. }
  986. else {
  987. trace = NULL;
  988. }
  989. TABLES_UNLOCK();
  990. if (!trace) {
  991. return NULL;
  992. }
  993. return trace->traceback;
  994. }
  995. #define PUTS(fd, str) _Py_write_noraise(fd, str, (int)strlen(str))
  996. static void
  997. _PyMem_DumpFrame(int fd, frame_t * frame)
  998. {
  999. PUTS(fd, " File \"");
  1000. _Py_DumpASCII(fd, frame->filename);
  1001. PUTS(fd, "\", line ");
  1002. _Py_DumpDecimal(fd, frame->lineno);
  1003. PUTS(fd, "\n");
  1004. }
  1005. /* Dump the traceback where a memory block was allocated into file descriptor
  1006. fd. The function may block on TABLES_LOCK() but it is unlikely. */
  1007. void
  1008. _PyMem_DumpTraceback(int fd, const void *ptr)
  1009. {
  1010. traceback_t *traceback;
  1011. int i;
  1012. if (!tracemalloc_config.tracing) {
  1013. PUTS(fd, "Enable tracemalloc to get the memory block "
  1014. "allocation traceback\n\n");
  1015. return;
  1016. }
  1017. traceback = tracemalloc_get_traceback(DEFAULT_DOMAIN, (uintptr_t)ptr);
  1018. if (traceback == NULL)
  1019. return;
  1020. PUTS(fd, "Memory block allocated at (most recent call first):\n");
  1021. for (i=0; i < traceback->nframe; i++) {
  1022. _PyMem_DumpFrame(fd, &traceback->frames[i]);
  1023. }
  1024. PUTS(fd, "\n");
  1025. }
  1026. #undef PUTS
  1027. static int
  1028. tracemalloc_get_tracemalloc_memory_cb(_Py_hashtable_t *domains,
  1029. const void *key, const void *value,
  1030. void *user_data)
  1031. {
  1032. const _Py_hashtable_t *traces = value;
  1033. size_t *size = (size_t*)user_data;
  1034. *size += _Py_hashtable_size(traces);
  1035. return 0;
  1036. }
  1037. int
  1038. PyTraceMalloc_Track(unsigned int domain, uintptr_t ptr,
  1039. size_t size)
  1040. {
  1041. int res;
  1042. PyGILState_STATE gil_state;
  1043. if (!tracemalloc_config.tracing) {
  1044. /* tracemalloc is not tracing: do nothing */
  1045. return -2;
  1046. }
  1047. gil_state = PyGILState_Ensure();
  1048. TABLES_LOCK();
  1049. res = tracemalloc_add_trace(domain, ptr, size);
  1050. TABLES_UNLOCK();
  1051. PyGILState_Release(gil_state);
  1052. return res;
  1053. }
  1054. int
  1055. PyTraceMalloc_Untrack(unsigned int domain, uintptr_t ptr)
  1056. {
  1057. if (!tracemalloc_config.tracing) {
  1058. /* tracemalloc is not tracing: do nothing */
  1059. return -2;
  1060. }
  1061. TABLES_LOCK();
  1062. tracemalloc_remove_trace(domain, ptr);
  1063. TABLES_UNLOCK();
  1064. return 0;
  1065. }
  1066. void
  1067. _PyTraceMalloc_Fini(void)
  1068. {
  1069. assert(PyGILState_Check());
  1070. tracemalloc_deinit();
  1071. }
  1072. /* If the object memory block is already traced, update its trace
  1073. with the current Python traceback.
  1074. Do nothing if tracemalloc is not tracing memory allocations
  1075. or if the object memory block is not already traced. */
  1076. int
  1077. _PyTraceMalloc_NewReference(PyObject *op)
  1078. {
  1079. assert(PyGILState_Check());
  1080. if (!tracemalloc_config.tracing) {
  1081. /* tracemalloc is not tracing: do nothing */
  1082. return -1;
  1083. }
  1084. PyTypeObject *type = Py_TYPE(op);
  1085. const size_t presize = _PyType_PreHeaderSize(type);
  1086. uintptr_t ptr = (uintptr_t)((char *)op - presize);
  1087. int res = -1;
  1088. TABLES_LOCK();
  1089. trace_t *trace = _Py_hashtable_get(tracemalloc_traces, TO_PTR(ptr));
  1090. if (trace != NULL) {
  1091. /* update the traceback of the memory block */
  1092. traceback_t *traceback = traceback_new();
  1093. if (traceback != NULL) {
  1094. trace->traceback = traceback;
  1095. res = 0;
  1096. }
  1097. }
  1098. /* else: cannot track the object, its memory block size is unknown */
  1099. TABLES_UNLOCK();
  1100. return res;
  1101. }
  1102. PyObject*
  1103. _PyTraceMalloc_GetTraceback(unsigned int domain, uintptr_t ptr)
  1104. {
  1105. traceback_t *traceback;
  1106. traceback = tracemalloc_get_traceback(domain, ptr);
  1107. if (traceback == NULL)
  1108. Py_RETURN_NONE;
  1109. return traceback_to_pyobject(traceback, NULL);
  1110. }
  1111. int
  1112. _PyTraceMalloc_IsTracing(void)
  1113. {
  1114. return tracemalloc_config.tracing;
  1115. }
  1116. void
  1117. _PyTraceMalloc_ClearTraces(void)
  1118. {
  1119. if (!tracemalloc_config.tracing) {
  1120. return;
  1121. }
  1122. set_reentrant(1);
  1123. tracemalloc_clear_traces();
  1124. set_reentrant(0);
  1125. }
  1126. PyObject *
  1127. _PyTraceMalloc_GetTraces(void)
  1128. {
  1129. get_traces_t get_traces;
  1130. get_traces.domain = DEFAULT_DOMAIN;
  1131. get_traces.traces = NULL;
  1132. get_traces.domains = NULL;
  1133. get_traces.tracebacks = NULL;
  1134. get_traces.list = PyList_New(0);
  1135. if (get_traces.list == NULL)
  1136. goto error;
  1137. if (!tracemalloc_config.tracing)
  1138. return get_traces.list;
  1139. /* the traceback hash table is used temporarily to intern traceback tuple
  1140. of (filename, lineno) tuples */
  1141. get_traces.tracebacks = hashtable_new(_Py_hashtable_hash_ptr,
  1142. _Py_hashtable_compare_direct,
  1143. NULL, tracemalloc_pyobject_decref);
  1144. if (get_traces.tracebacks == NULL) {
  1145. goto no_memory;
  1146. }
  1147. // Copy all traces so tracemalloc_get_traces_fill() doesn't have to disable
  1148. // temporarily tracemalloc which would impact other threads and so would
  1149. // miss allocations while get_traces() is called.
  1150. TABLES_LOCK();
  1151. get_traces.traces = tracemalloc_copy_traces(tracemalloc_traces);
  1152. TABLES_UNLOCK();
  1153. if (get_traces.traces == NULL) {
  1154. goto no_memory;
  1155. }
  1156. TABLES_LOCK();
  1157. get_traces.domains = tracemalloc_copy_domains(tracemalloc_domains);
  1158. TABLES_UNLOCK();
  1159. if (get_traces.domains == NULL) {
  1160. goto no_memory;
  1161. }
  1162. // Convert traces to a list of tuples
  1163. set_reentrant(1);
  1164. int err = _Py_hashtable_foreach(get_traces.traces,
  1165. tracemalloc_get_traces_fill,
  1166. &get_traces);
  1167. if (!err) {
  1168. err = _Py_hashtable_foreach(get_traces.domains,
  1169. tracemalloc_get_traces_domain,
  1170. &get_traces);
  1171. }
  1172. set_reentrant(0);
  1173. if (err) {
  1174. goto error;
  1175. }
  1176. goto finally;
  1177. no_memory:
  1178. PyErr_NoMemory();
  1179. error:
  1180. Py_CLEAR(get_traces.list);
  1181. finally:
  1182. if (get_traces.tracebacks != NULL) {
  1183. _Py_hashtable_destroy(get_traces.tracebacks);
  1184. }
  1185. if (get_traces.traces != NULL) {
  1186. _Py_hashtable_destroy(get_traces.traces);
  1187. }
  1188. if (get_traces.domains != NULL) {
  1189. _Py_hashtable_destroy(get_traces.domains);
  1190. }
  1191. return get_traces.list;
  1192. }
  1193. PyObject *
  1194. _PyTraceMalloc_GetObjectTraceback(PyObject *obj)
  1195. /*[clinic end generated code: output=41ee0553a658b0aa input=29495f1b21c53212]*/
  1196. {
  1197. PyTypeObject *type;
  1198. traceback_t *traceback;
  1199. type = Py_TYPE(obj);
  1200. const size_t presize = _PyType_PreHeaderSize(type);
  1201. uintptr_t ptr = (uintptr_t)((char *)obj - presize);
  1202. traceback = tracemalloc_get_traceback(DEFAULT_DOMAIN, ptr);
  1203. if (traceback == NULL) {
  1204. Py_RETURN_NONE;
  1205. }
  1206. return traceback_to_pyobject(traceback, NULL);
  1207. }
  1208. int _PyTraceMalloc_GetTracebackLimit(void) {
  1209. return tracemalloc_config.max_nframe;
  1210. }
  1211. size_t
  1212. _PyTraceMalloc_GetMemory(void) {
  1213. size_t size;
  1214. size = _Py_hashtable_size(tracemalloc_tracebacks);
  1215. size += _Py_hashtable_size(tracemalloc_filenames);
  1216. TABLES_LOCK();
  1217. size += _Py_hashtable_size(tracemalloc_traces);
  1218. _Py_hashtable_foreach(tracemalloc_domains,
  1219. tracemalloc_get_tracemalloc_memory_cb, &size);
  1220. TABLES_UNLOCK();
  1221. return size;
  1222. }
  1223. PyObject *
  1224. _PyTraceMalloc_GetTracedMemory(void)
  1225. {
  1226. Py_ssize_t size, peak_size;
  1227. if (!tracemalloc_config.tracing)
  1228. return Py_BuildValue("ii", 0, 0);
  1229. TABLES_LOCK();
  1230. size = tracemalloc_traced_memory;
  1231. peak_size = tracemalloc_peak_traced_memory;
  1232. TABLES_UNLOCK();
  1233. return Py_BuildValue("nn", size, peak_size);
  1234. }
  1235. void
  1236. _PyTraceMalloc_ResetPeak(void)
  1237. {
  1238. if (!tracemalloc_config.tracing) {
  1239. return;
  1240. }
  1241. TABLES_LOCK();
  1242. tracemalloc_peak_traced_memory = tracemalloc_traced_memory;
  1243. TABLES_UNLOCK();
  1244. }