You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1811 lines
44 KiB

  1. #include "Python.h"
  2. #include "hashtable.h"
  3. #include "frameobject.h"
  4. #include "pythread.h"
  5. #include "osdefs.h"
  6. #include "clinic/_tracemalloc.c.h"
  7. /*[clinic input]
  8. module _tracemalloc
  9. [clinic start generated code]*/
  10. /*[clinic end generated code: output=da39a3ee5e6b4b0d input=708a98302fc46e5f]*/
  11. /* Trace memory blocks allocated by PyMem_RawMalloc() */
  12. #define TRACE_RAW_MALLOC
  13. /* Forward declaration */
  14. static void tracemalloc_stop(void);
  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. /* Protected by the GIL */
  21. static struct {
  22. PyMemAllocatorEx mem;
  23. PyMemAllocatorEx raw;
  24. PyMemAllocatorEx obj;
  25. } allocators;
  26. static 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. /* Is tracemalloc tracing memory allocations?
  35. Variable protected by the GIL */
  36. int tracing;
  37. /* limit of the number of frames in a traceback, 1 by default.
  38. Variable protected by the GIL. */
  39. int max_nframe;
  40. /* use domain in trace key?
  41. Variable protected by the GIL. */
  42. int use_domain;
  43. } tracemalloc_config = {TRACEMALLOC_NOT_INITIALIZED, 0, 1, 0};
  44. #if defined(TRACE_RAW_MALLOC)
  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(). */
  48. static 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. #define DEFAULT_DOMAIN 0
  57. /* Pack the frame_t structure to reduce the memory footprint. */
  58. typedef struct
  59. #ifdef __GNUC__
  60. __attribute__((packed))
  61. #endif
  62. {
  63. uintptr_t ptr;
  64. unsigned int domain;
  65. } pointer_t;
  66. /* Pack the frame_t structure to reduce the memory footprint on 64-bit
  67. architectures: 12 bytes instead of 16. */
  68. typedef struct
  69. #ifdef __GNUC__
  70. __attribute__((packed))
  71. #elif defined(_MSC_VER)
  72. #pragma pack(push, 4)
  73. #endif
  74. {
  75. /* filename cannot be NULL: "<unknown>" is used if the Python frame
  76. filename is NULL */
  77. PyObject *filename;
  78. unsigned int lineno;
  79. } frame_t;
  80. #ifdef _MSC_VER
  81. #pragma pack(pop)
  82. #endif
  83. typedef struct {
  84. Py_uhash_t hash;
  85. int nframe;
  86. frame_t frames[1];
  87. } traceback_t;
  88. #define TRACEBACK_SIZE(NFRAME) \
  89. (sizeof(traceback_t) + sizeof(frame_t) * (NFRAME - 1))
  90. #define MAX_NFRAME \
  91. ((INT_MAX - (int)sizeof(traceback_t)) / (int)sizeof(frame_t) + 1)
  92. static PyObject *unknown_filename = NULL;
  93. static traceback_t tracemalloc_empty_traceback;
  94. /* Trace of a memory block */
  95. typedef struct {
  96. /* Size of the memory block in bytes */
  97. size_t size;
  98. /* Traceback where the memory block was allocated */
  99. traceback_t *traceback;
  100. } trace_t;
  101. /* Size in bytes of currently traced memory.
  102. Protected by TABLES_LOCK(). */
  103. static size_t tracemalloc_traced_memory = 0;
  104. /* Peak size in bytes of traced memory.
  105. Protected by TABLES_LOCK(). */
  106. static size_t tracemalloc_peak_traced_memory = 0;
  107. /* Hash table used as a set to intern filenames:
  108. PyObject* => PyObject*.
  109. Protected by the GIL */
  110. static _Py_hashtable_t *tracemalloc_filenames = NULL;
  111. /* Buffer to store a new traceback in traceback_new().
  112. Protected by the GIL. */
  113. static traceback_t *tracemalloc_traceback = NULL;
  114. /* Hash table used as a set to intern tracebacks:
  115. traceback_t* => traceback_t*
  116. Protected by the GIL */
  117. static _Py_hashtable_t *tracemalloc_tracebacks = NULL;
  118. /* pointer (void*) => trace (trace_t).
  119. Protected by TABLES_LOCK(). */
  120. static _Py_hashtable_t *tracemalloc_traces = NULL;
  121. #ifdef TRACE_DEBUG
  122. static void
  123. tracemalloc_error(const char *format, ...)
  124. {
  125. va_list ap;
  126. fprintf(stderr, "tracemalloc: ");
  127. va_start(ap, format);
  128. vfprintf(stderr, format, ap);
  129. va_end(ap);
  130. fprintf(stderr, "\n");
  131. fflush(stderr);
  132. }
  133. #endif
  134. #if defined(TRACE_RAW_MALLOC)
  135. #define REENTRANT_THREADLOCAL
  136. /* If your OS does not provide native thread local storage, you can implement
  137. it manually using a lock. Functions of thread.c cannot be used because
  138. they use PyMem_RawMalloc() which leads to a reentrant call. */
  139. #if !(defined(_POSIX_THREADS) || defined(NT_THREADS))
  140. # error "need native thread local storage (TLS)"
  141. #endif
  142. static int tracemalloc_reentrant_key = -1;
  143. /* Any non-NULL pointer can be used */
  144. #define REENTRANT Py_True
  145. static int
  146. get_reentrant(void)
  147. {
  148. void *ptr;
  149. assert(tracemalloc_reentrant_key != -1);
  150. ptr = PyThread_get_key_value(tracemalloc_reentrant_key);
  151. if (ptr != NULL) {
  152. assert(ptr == REENTRANT);
  153. return 1;
  154. }
  155. else
  156. return 0;
  157. }
  158. static void
  159. set_reentrant(int reentrant)
  160. {
  161. assert(reentrant == 0 || reentrant == 1);
  162. assert(tracemalloc_reentrant_key != -1);
  163. if (reentrant) {
  164. assert(!get_reentrant());
  165. PyThread_set_key_value(tracemalloc_reentrant_key, REENTRANT);
  166. }
  167. else {
  168. assert(get_reentrant());
  169. PyThread_set_key_value(tracemalloc_reentrant_key, NULL);
  170. }
  171. }
  172. #else
  173. /* TRACE_RAW_MALLOC not defined: variable protected by the GIL */
  174. static int tracemalloc_reentrant = 0;
  175. static int
  176. get_reentrant(void)
  177. {
  178. return tracemalloc_reentrant;
  179. }
  180. static void
  181. set_reentrant(int reentrant)
  182. {
  183. assert(reentrant != tracemalloc_reentrant);
  184. tracemalloc_reentrant = reentrant;
  185. }
  186. #endif
  187. static Py_uhash_t
  188. hashtable_hash_pyobject(_Py_hashtable_t *ht, const void *pkey)
  189. {
  190. PyObject *obj;
  191. _Py_HASHTABLE_READ_KEY(ht, pkey, obj);
  192. return PyObject_Hash(obj);
  193. }
  194. static int
  195. hashtable_compare_unicode(_Py_hashtable_t *ht, const void *pkey,
  196. const _Py_hashtable_entry_t *entry)
  197. {
  198. PyObject *key1, *key2;
  199. _Py_HASHTABLE_READ_KEY(ht, pkey, key1);
  200. _Py_HASHTABLE_ENTRY_READ_KEY(ht, entry, key2);
  201. if (key1 != NULL && key2 != NULL)
  202. return (PyUnicode_Compare(key1, key2) == 0);
  203. else
  204. return key1 == key2;
  205. }
  206. static Py_uhash_t
  207. hashtable_hash_pointer_t(_Py_hashtable_t *ht, const void *pkey)
  208. {
  209. pointer_t ptr;
  210. Py_uhash_t hash;
  211. _Py_HASHTABLE_READ_KEY(ht, pkey, ptr);
  212. hash = (Py_uhash_t)_Py_HashPointer((void*)ptr.ptr);
  213. hash ^= ptr.domain;
  214. return hash;
  215. }
  216. static int
  217. hashtable_compare_pointer_t(_Py_hashtable_t *ht, const void *pkey,
  218. const _Py_hashtable_entry_t *entry)
  219. {
  220. pointer_t ptr1, ptr2;
  221. _Py_HASHTABLE_READ_KEY(ht, pkey, ptr1);
  222. _Py_HASHTABLE_ENTRY_READ_KEY(ht, entry, ptr2);
  223. /* compare pointer before domain, because pointer is more likely to be
  224. different */
  225. return (ptr1.ptr == ptr2.ptr && ptr1.domain == ptr2.domain);
  226. }
  227. static _Py_hashtable_t *
  228. hashtable_new(size_t key_size, size_t data_size,
  229. _Py_hashtable_hash_func hash_func,
  230. _Py_hashtable_compare_func compare_func)
  231. {
  232. _Py_hashtable_allocator_t hashtable_alloc = {malloc, free};
  233. return _Py_hashtable_new_full(key_size, data_size, 0,
  234. hash_func, compare_func,
  235. &hashtable_alloc);
  236. }
  237. static void*
  238. raw_malloc(size_t size)
  239. {
  240. return allocators.raw.malloc(allocators.raw.ctx, size);
  241. }
  242. static void
  243. raw_free(void *ptr)
  244. {
  245. allocators.raw.free(allocators.raw.ctx, ptr);
  246. }
  247. static Py_uhash_t
  248. hashtable_hash_traceback(_Py_hashtable_t *ht, const void *pkey)
  249. {
  250. traceback_t *traceback;
  251. _Py_HASHTABLE_READ_KEY(ht, pkey, traceback);
  252. return traceback->hash;
  253. }
  254. static int
  255. hashtable_compare_traceback(_Py_hashtable_t *ht, const void *pkey,
  256. const _Py_hashtable_entry_t *entry)
  257. {
  258. traceback_t *traceback1, *traceback2;
  259. const frame_t *frame1, *frame2;
  260. int i;
  261. _Py_HASHTABLE_READ_KEY(ht, pkey, traceback1);
  262. _Py_HASHTABLE_ENTRY_READ_KEY(ht, entry, traceback2);
  263. if (traceback1->nframe != traceback2->nframe)
  264. return 0;
  265. for (i=0; i < traceback1->nframe; i++) {
  266. frame1 = &traceback1->frames[i];
  267. frame2 = &traceback2->frames[i];
  268. if (frame1->lineno != frame2->lineno)
  269. return 0;
  270. if (frame1->filename != frame2->filename) {
  271. assert(PyUnicode_Compare(frame1->filename, frame2->filename) != 0);
  272. return 0;
  273. }
  274. }
  275. return 1;
  276. }
  277. static void
  278. tracemalloc_get_frame(PyFrameObject *pyframe, frame_t *frame)
  279. {
  280. PyCodeObject *code;
  281. PyObject *filename;
  282. _Py_hashtable_entry_t *entry;
  283. int lineno;
  284. frame->filename = unknown_filename;
  285. lineno = PyFrame_GetLineNumber(pyframe);
  286. if (lineno < 0)
  287. lineno = 0;
  288. frame->lineno = (unsigned int)lineno;
  289. code = pyframe->f_code;
  290. if (code == NULL) {
  291. #ifdef TRACE_DEBUG
  292. tracemalloc_error("failed to get the code object of the frame");
  293. #endif
  294. return;
  295. }
  296. if (code->co_filename == NULL) {
  297. #ifdef TRACE_DEBUG
  298. tracemalloc_error("failed to get the filename of the code object");
  299. #endif
  300. return;
  301. }
  302. filename = code->co_filename;
  303. assert(filename != NULL);
  304. if (filename == NULL)
  305. return;
  306. if (!PyUnicode_Check(filename)) {
  307. #ifdef TRACE_DEBUG
  308. tracemalloc_error("filename is not a unicode string");
  309. #endif
  310. return;
  311. }
  312. if (!PyUnicode_IS_READY(filename)) {
  313. /* Don't make a Unicode string ready to avoid reentrant calls
  314. to tracemalloc_malloc() or tracemalloc_realloc() */
  315. #ifdef TRACE_DEBUG
  316. tracemalloc_error("filename is not a ready unicode string");
  317. #endif
  318. return;
  319. }
  320. /* intern the filename */
  321. entry = _Py_HASHTABLE_GET_ENTRY(tracemalloc_filenames, filename);
  322. if (entry != NULL) {
  323. _Py_HASHTABLE_ENTRY_READ_KEY(tracemalloc_filenames, entry, filename);
  324. }
  325. else {
  326. /* tracemalloc_filenames is responsible to keep a reference
  327. to the filename */
  328. Py_INCREF(filename);
  329. if (_Py_HASHTABLE_SET_NODATA(tracemalloc_filenames, filename) < 0) {
  330. Py_DECREF(filename);
  331. #ifdef TRACE_DEBUG
  332. tracemalloc_error("failed to intern the filename");
  333. #endif
  334. return;
  335. }
  336. }
  337. /* the tracemalloc_filenames table keeps a reference to the filename */
  338. frame->filename = filename;
  339. }
  340. static Py_uhash_t
  341. traceback_hash(traceback_t *traceback)
  342. {
  343. /* code based on tuplehash() of Objects/tupleobject.c */
  344. Py_uhash_t x, y; /* Unsigned for defined overflow behavior. */
  345. int len = traceback->nframe;
  346. Py_uhash_t mult = _PyHASH_MULTIPLIER;
  347. frame_t *frame;
  348. x = 0x345678UL;
  349. frame = traceback->frames;
  350. while (--len >= 0) {
  351. y = (Py_uhash_t)PyObject_Hash(frame->filename);
  352. y ^= (Py_uhash_t)frame->lineno;
  353. frame++;
  354. x = (x ^ y) * mult;
  355. /* the cast might truncate len; that doesn't change hash stability */
  356. mult += (Py_uhash_t)(82520UL + len + len);
  357. }
  358. x += 97531UL;
  359. return x;
  360. }
  361. static void
  362. traceback_get_frames(traceback_t *traceback)
  363. {
  364. PyThreadState *tstate;
  365. PyFrameObject *pyframe;
  366. tstate = PyGILState_GetThisThreadState();
  367. if (tstate == NULL) {
  368. #ifdef TRACE_DEBUG
  369. tracemalloc_error("failed to get the current thread state");
  370. #endif
  371. return;
  372. }
  373. for (pyframe = tstate->frame; pyframe != NULL; pyframe = pyframe->f_back) {
  374. tracemalloc_get_frame(pyframe, &traceback->frames[traceback->nframe]);
  375. assert(traceback->frames[traceback->nframe].filename != NULL);
  376. traceback->nframe++;
  377. if (traceback->nframe == tracemalloc_config.max_nframe)
  378. break;
  379. }
  380. }
  381. static traceback_t *
  382. traceback_new(void)
  383. {
  384. traceback_t *traceback;
  385. _Py_hashtable_entry_t *entry;
  386. assert(PyGILState_Check());
  387. /* get frames */
  388. traceback = tracemalloc_traceback;
  389. traceback->nframe = 0;
  390. traceback_get_frames(traceback);
  391. if (traceback->nframe == 0)
  392. return &tracemalloc_empty_traceback;
  393. traceback->hash = traceback_hash(traceback);
  394. /* intern the traceback */
  395. entry = _Py_HASHTABLE_GET_ENTRY(tracemalloc_tracebacks, traceback);
  396. if (entry != NULL) {
  397. _Py_HASHTABLE_ENTRY_READ_KEY(tracemalloc_tracebacks, entry, traceback);
  398. }
  399. else {
  400. traceback_t *copy;
  401. size_t traceback_size;
  402. traceback_size = TRACEBACK_SIZE(traceback->nframe);
  403. copy = raw_malloc(traceback_size);
  404. if (copy == NULL) {
  405. #ifdef TRACE_DEBUG
  406. tracemalloc_error("failed to intern the traceback: malloc failed");
  407. #endif
  408. return NULL;
  409. }
  410. memcpy(copy, traceback, traceback_size);
  411. if (_Py_HASHTABLE_SET_NODATA(tracemalloc_tracebacks, copy) < 0) {
  412. raw_free(copy);
  413. #ifdef TRACE_DEBUG
  414. tracemalloc_error("failed to intern the traceback: putdata failed");
  415. #endif
  416. return NULL;
  417. }
  418. traceback = copy;
  419. }
  420. return traceback;
  421. }
  422. static int
  423. tracemalloc_use_domain_cb(_Py_hashtable_t *old_traces,
  424. _Py_hashtable_entry_t *entry, void *user_data)
  425. {
  426. uintptr_t ptr;
  427. pointer_t key;
  428. _Py_hashtable_t *new_traces = (_Py_hashtable_t *)user_data;
  429. const void *pdata = _Py_HASHTABLE_ENTRY_PDATA(old_traces, entry);
  430. _Py_HASHTABLE_ENTRY_READ_KEY(old_traces, entry, ptr);
  431. key.ptr = ptr;
  432. key.domain = DEFAULT_DOMAIN;
  433. return _Py_hashtable_set(new_traces,
  434. sizeof(key), &key,
  435. old_traces->data_size, pdata);
  436. }
  437. /* Convert tracemalloc_traces from compact key (uintptr_t) to pointer_t key.
  438. * Return 0 on success, -1 on error. */
  439. static int
  440. tracemalloc_use_domain(void)
  441. {
  442. _Py_hashtable_t *new_traces = NULL;
  443. assert(!tracemalloc_config.use_domain);
  444. new_traces = hashtable_new(sizeof(pointer_t),
  445. sizeof(trace_t),
  446. hashtable_hash_pointer_t,
  447. hashtable_compare_pointer_t);
  448. if (new_traces == NULL) {
  449. return -1;
  450. }
  451. if (_Py_hashtable_foreach(tracemalloc_traces, tracemalloc_use_domain_cb,
  452. new_traces) < 0)
  453. {
  454. _Py_hashtable_destroy(new_traces);
  455. return -1;
  456. }
  457. _Py_hashtable_destroy(tracemalloc_traces);
  458. tracemalloc_traces = new_traces;
  459. tracemalloc_config.use_domain = 1;
  460. return 0;
  461. }
  462. static void
  463. tracemalloc_remove_trace(unsigned int domain, uintptr_t ptr)
  464. {
  465. trace_t trace;
  466. int removed;
  467. assert(tracemalloc_config.tracing);
  468. if (tracemalloc_config.use_domain) {
  469. pointer_t key = {ptr, domain};
  470. removed = _Py_HASHTABLE_POP(tracemalloc_traces, key, trace);
  471. }
  472. else {
  473. removed = _Py_HASHTABLE_POP(tracemalloc_traces, ptr, trace);
  474. }
  475. if (!removed) {
  476. return;
  477. }
  478. assert(tracemalloc_traced_memory >= trace.size);
  479. tracemalloc_traced_memory -= trace.size;
  480. }
  481. #define REMOVE_TRACE(ptr) \
  482. tracemalloc_remove_trace(DEFAULT_DOMAIN, (uintptr_t)(ptr))
  483. static int
  484. tracemalloc_add_trace(unsigned int domain, uintptr_t ptr,
  485. size_t size)
  486. {
  487. pointer_t key = {ptr, domain};
  488. traceback_t *traceback;
  489. trace_t trace;
  490. _Py_hashtable_entry_t* entry;
  491. int res;
  492. assert(tracemalloc_config.tracing);
  493. traceback = traceback_new();
  494. if (traceback == NULL) {
  495. return -1;
  496. }
  497. if (!tracemalloc_config.use_domain && domain != DEFAULT_DOMAIN) {
  498. /* first trace using a non-zero domain whereas traces use compact
  499. (uintptr_t) keys: switch to pointer_t keys. */
  500. if (tracemalloc_use_domain() < 0) {
  501. return -1;
  502. }
  503. }
  504. if (tracemalloc_config.use_domain) {
  505. entry = _Py_HASHTABLE_GET_ENTRY(tracemalloc_traces, key);
  506. }
  507. else {
  508. entry = _Py_HASHTABLE_GET_ENTRY(tracemalloc_traces, ptr);
  509. }
  510. if (entry != NULL) {
  511. /* the memory block is already tracked */
  512. _Py_HASHTABLE_ENTRY_READ_DATA(tracemalloc_traces, entry, trace);
  513. assert(tracemalloc_traced_memory >= trace.size);
  514. tracemalloc_traced_memory -= trace.size;
  515. trace.size = size;
  516. trace.traceback = traceback;
  517. _Py_HASHTABLE_ENTRY_WRITE_DATA(tracemalloc_traces, entry, trace);
  518. }
  519. else {
  520. trace.size = size;
  521. trace.traceback = traceback;
  522. if (tracemalloc_config.use_domain) {
  523. res = _Py_HASHTABLE_SET(tracemalloc_traces, key, trace);
  524. }
  525. else {
  526. res = _Py_HASHTABLE_SET(tracemalloc_traces, ptr, trace);
  527. }
  528. if (res != 0) {
  529. return res;
  530. }
  531. }
  532. assert(tracemalloc_traced_memory <= SIZE_MAX - size);
  533. tracemalloc_traced_memory += size;
  534. if (tracemalloc_traced_memory > tracemalloc_peak_traced_memory)
  535. tracemalloc_peak_traced_memory = tracemalloc_traced_memory;
  536. return 0;
  537. }
  538. #define ADD_TRACE(ptr, size) \
  539. tracemalloc_add_trace(DEFAULT_DOMAIN, (uintptr_t)(ptr), size)
  540. static void*
  541. tracemalloc_alloc(int use_calloc, void *ctx, size_t nelem, size_t elsize)
  542. {
  543. PyMemAllocatorEx *alloc = (PyMemAllocatorEx *)ctx;
  544. void *ptr;
  545. assert(elsize == 0 || nelem <= SIZE_MAX / elsize);
  546. if (use_calloc)
  547. ptr = alloc->calloc(alloc->ctx, nelem, elsize);
  548. else
  549. ptr = alloc->malloc(alloc->ctx, nelem * elsize);
  550. if (ptr == NULL)
  551. return NULL;
  552. TABLES_LOCK();
  553. if (ADD_TRACE(ptr, nelem * elsize) < 0) {
  554. /* Failed to allocate a trace for the new memory block */
  555. TABLES_UNLOCK();
  556. alloc->free(alloc->ctx, ptr);
  557. return NULL;
  558. }
  559. TABLES_UNLOCK();
  560. return ptr;
  561. }
  562. static void*
  563. tracemalloc_realloc(void *ctx, void *ptr, size_t new_size)
  564. {
  565. PyMemAllocatorEx *alloc = (PyMemAllocatorEx *)ctx;
  566. void *ptr2;
  567. ptr2 = alloc->realloc(alloc->ctx, ptr, new_size);
  568. if (ptr2 == NULL)
  569. return NULL;
  570. if (ptr != NULL) {
  571. /* an existing memory block has been resized */
  572. TABLES_LOCK();
  573. /* tracemalloc_add_trace() updates the trace if there is already
  574. a trace at address (domain, ptr2) */
  575. if (ptr2 != ptr) {
  576. REMOVE_TRACE(ptr);
  577. }
  578. if (ADD_TRACE(ptr2, new_size) < 0) {
  579. /* Memory allocation failed. The error cannot be reported to
  580. the caller, because realloc() may already have shrunk the
  581. memory block and so removed bytes.
  582. This case is very unlikely: a hash entry has just been
  583. released, so the hash table should have at least one free entry.
  584. The GIL and the table lock ensures that only one thread is
  585. allocating memory. */
  586. Py_UNREACHABLE();
  587. }
  588. TABLES_UNLOCK();
  589. }
  590. else {
  591. /* new allocation */
  592. TABLES_LOCK();
  593. if (ADD_TRACE(ptr2, new_size) < 0) {
  594. /* Failed to allocate a trace for the new memory block */
  595. TABLES_UNLOCK();
  596. alloc->free(alloc->ctx, ptr2);
  597. return NULL;
  598. }
  599. TABLES_UNLOCK();
  600. }
  601. return ptr2;
  602. }
  603. static void
  604. tracemalloc_free(void *ctx, void *ptr)
  605. {
  606. PyMemAllocatorEx *alloc = (PyMemAllocatorEx *)ctx;
  607. if (ptr == NULL)
  608. return;
  609. /* GIL cannot be locked in PyMem_RawFree() because it would introduce
  610. a deadlock in PyThreadState_DeleteCurrent(). */
  611. alloc->free(alloc->ctx, ptr);
  612. TABLES_LOCK();
  613. REMOVE_TRACE(ptr);
  614. TABLES_UNLOCK();
  615. }
  616. static void*
  617. tracemalloc_alloc_gil(int use_calloc, void *ctx, size_t nelem, size_t elsize)
  618. {
  619. void *ptr;
  620. if (get_reentrant()) {
  621. PyMemAllocatorEx *alloc = (PyMemAllocatorEx *)ctx;
  622. if (use_calloc)
  623. return alloc->calloc(alloc->ctx, nelem, elsize);
  624. else
  625. return alloc->malloc(alloc->ctx, nelem * elsize);
  626. }
  627. /* Ignore reentrant call. PyObjet_Malloc() calls PyMem_Malloc() for
  628. allocations larger than 512 bytes, don't trace the same memory
  629. allocation twice. */
  630. set_reentrant(1);
  631. ptr = tracemalloc_alloc(use_calloc, ctx, nelem, elsize);
  632. set_reentrant(0);
  633. return ptr;
  634. }
  635. static void*
  636. tracemalloc_malloc_gil(void *ctx, size_t size)
  637. {
  638. return tracemalloc_alloc_gil(0, ctx, 1, size);
  639. }
  640. static void*
  641. tracemalloc_calloc_gil(void *ctx, size_t nelem, size_t elsize)
  642. {
  643. return tracemalloc_alloc_gil(1, ctx, nelem, elsize);
  644. }
  645. static void*
  646. tracemalloc_realloc_gil(void *ctx, void *ptr, size_t new_size)
  647. {
  648. void *ptr2;
  649. if (get_reentrant()) {
  650. /* Reentrant call to PyMem_Realloc() and PyMem_RawRealloc().
  651. Example: PyMem_RawRealloc() is called internally by pymalloc
  652. (_PyObject_Malloc() and _PyObject_Realloc()) to allocate a new
  653. arena (new_arena()). */
  654. PyMemAllocatorEx *alloc = (PyMemAllocatorEx *)ctx;
  655. ptr2 = alloc->realloc(alloc->ctx, ptr, new_size);
  656. if (ptr2 != NULL && ptr != NULL) {
  657. TABLES_LOCK();
  658. REMOVE_TRACE(ptr);
  659. TABLES_UNLOCK();
  660. }
  661. return ptr2;
  662. }
  663. /* Ignore reentrant call. PyObjet_Realloc() calls PyMem_Realloc() for
  664. allocations larger than 512 bytes. Don't trace the same memory
  665. allocation twice. */
  666. set_reentrant(1);
  667. ptr2 = tracemalloc_realloc(ctx, ptr, new_size);
  668. set_reentrant(0);
  669. return ptr2;
  670. }
  671. #ifdef TRACE_RAW_MALLOC
  672. static void*
  673. tracemalloc_raw_alloc(int use_calloc, void *ctx, size_t nelem, size_t elsize)
  674. {
  675. PyGILState_STATE gil_state;
  676. void *ptr;
  677. if (get_reentrant()) {
  678. PyMemAllocatorEx *alloc = (PyMemAllocatorEx *)ctx;
  679. if (use_calloc)
  680. return alloc->calloc(alloc->ctx, nelem, elsize);
  681. else
  682. return alloc->malloc(alloc->ctx, nelem * elsize);
  683. }
  684. /* Ignore reentrant call. PyGILState_Ensure() may call PyMem_RawMalloc()
  685. indirectly which would call PyGILState_Ensure() if reentrant are not
  686. disabled. */
  687. set_reentrant(1);
  688. gil_state = PyGILState_Ensure();
  689. ptr = tracemalloc_alloc(use_calloc, ctx, nelem, elsize);
  690. PyGILState_Release(gil_state);
  691. set_reentrant(0);
  692. return ptr;
  693. }
  694. static void*
  695. tracemalloc_raw_malloc(void *ctx, size_t size)
  696. {
  697. return tracemalloc_raw_alloc(0, ctx, 1, size);
  698. }
  699. static void*
  700. tracemalloc_raw_calloc(void *ctx, size_t nelem, size_t elsize)
  701. {
  702. return tracemalloc_raw_alloc(1, ctx, nelem, elsize);
  703. }
  704. static void*
  705. tracemalloc_raw_realloc(void *ctx, void *ptr, size_t new_size)
  706. {
  707. PyGILState_STATE gil_state;
  708. void *ptr2;
  709. if (get_reentrant()) {
  710. /* Reentrant call to PyMem_RawRealloc(). */
  711. PyMemAllocatorEx *alloc = (PyMemAllocatorEx *)ctx;
  712. ptr2 = alloc->realloc(alloc->ctx, ptr, new_size);
  713. if (ptr2 != NULL && ptr != NULL) {
  714. TABLES_LOCK();
  715. REMOVE_TRACE(ptr);
  716. TABLES_UNLOCK();
  717. }
  718. return ptr2;
  719. }
  720. /* Ignore reentrant call. PyGILState_Ensure() may call PyMem_RawMalloc()
  721. indirectly which would call PyGILState_Ensure() if reentrant calls are
  722. not disabled. */
  723. set_reentrant(1);
  724. gil_state = PyGILState_Ensure();
  725. ptr2 = tracemalloc_realloc(ctx, ptr, new_size);
  726. PyGILState_Release(gil_state);
  727. set_reentrant(0);
  728. return ptr2;
  729. }
  730. #endif /* TRACE_RAW_MALLOC */
  731. static int
  732. tracemalloc_clear_filename(_Py_hashtable_t *ht, _Py_hashtable_entry_t *entry,
  733. void *user_data)
  734. {
  735. PyObject *filename;
  736. _Py_HASHTABLE_ENTRY_READ_KEY(ht, entry, filename);
  737. Py_DECREF(filename);
  738. return 0;
  739. }
  740. static int
  741. traceback_free_traceback(_Py_hashtable_t *ht, _Py_hashtable_entry_t *entry,
  742. void *user_data)
  743. {
  744. traceback_t *traceback;
  745. _Py_HASHTABLE_ENTRY_READ_KEY(ht, entry, traceback);
  746. raw_free(traceback);
  747. return 0;
  748. }
  749. /* reentrant flag must be set to call this function and GIL must be held */
  750. static void
  751. tracemalloc_clear_traces(void)
  752. {
  753. /* The GIL protects variables againt concurrent access */
  754. assert(PyGILState_Check());
  755. TABLES_LOCK();
  756. _Py_hashtable_clear(tracemalloc_traces);
  757. tracemalloc_traced_memory = 0;
  758. tracemalloc_peak_traced_memory = 0;
  759. TABLES_UNLOCK();
  760. _Py_hashtable_foreach(tracemalloc_tracebacks, traceback_free_traceback, NULL);
  761. _Py_hashtable_clear(tracemalloc_tracebacks);
  762. _Py_hashtable_foreach(tracemalloc_filenames, tracemalloc_clear_filename, NULL);
  763. _Py_hashtable_clear(tracemalloc_filenames);
  764. }
  765. static int
  766. tracemalloc_init(void)
  767. {
  768. if (tracemalloc_config.initialized == TRACEMALLOC_FINALIZED) {
  769. PyErr_SetString(PyExc_RuntimeError,
  770. "the tracemalloc module has been unloaded");
  771. return -1;
  772. }
  773. if (tracemalloc_config.initialized == TRACEMALLOC_INITIALIZED)
  774. return 0;
  775. PyMem_GetAllocator(PYMEM_DOMAIN_RAW, &allocators.raw);
  776. #ifdef REENTRANT_THREADLOCAL
  777. tracemalloc_reentrant_key = PyThread_create_key();
  778. if (tracemalloc_reentrant_key == -1) {
  779. #ifdef MS_WINDOWS
  780. PyErr_SetFromWindowsErr(0);
  781. #else
  782. PyErr_SetFromErrno(PyExc_OSError);
  783. #endif
  784. return -1;
  785. }
  786. #endif
  787. #if defined(TRACE_RAW_MALLOC)
  788. if (tables_lock == NULL) {
  789. tables_lock = PyThread_allocate_lock();
  790. if (tables_lock == NULL) {
  791. PyErr_SetString(PyExc_RuntimeError, "cannot allocate lock");
  792. return -1;
  793. }
  794. }
  795. #endif
  796. tracemalloc_filenames = hashtable_new(sizeof(PyObject *), 0,
  797. hashtable_hash_pyobject,
  798. hashtable_compare_unicode);
  799. tracemalloc_tracebacks = hashtable_new(sizeof(traceback_t *), 0,
  800. hashtable_hash_traceback,
  801. hashtable_compare_traceback);
  802. if (tracemalloc_config.use_domain) {
  803. tracemalloc_traces = hashtable_new(sizeof(pointer_t),
  804. sizeof(trace_t),
  805. hashtable_hash_pointer_t,
  806. hashtable_compare_pointer_t);
  807. }
  808. else {
  809. tracemalloc_traces = hashtable_new(sizeof(uintptr_t),
  810. sizeof(trace_t),
  811. _Py_hashtable_hash_ptr,
  812. _Py_hashtable_compare_direct);
  813. }
  814. if (tracemalloc_filenames == NULL || tracemalloc_tracebacks == NULL
  815. || tracemalloc_traces == NULL) {
  816. PyErr_NoMemory();
  817. return -1;
  818. }
  819. unknown_filename = PyUnicode_FromString("<unknown>");
  820. if (unknown_filename == NULL)
  821. return -1;
  822. PyUnicode_InternInPlace(&unknown_filename);
  823. tracemalloc_empty_traceback.nframe = 1;
  824. /* borrowed reference */
  825. tracemalloc_empty_traceback.frames[0].filename = unknown_filename;
  826. tracemalloc_empty_traceback.frames[0].lineno = 0;
  827. tracemalloc_empty_traceback.hash = traceback_hash(&tracemalloc_empty_traceback);
  828. tracemalloc_config.initialized = TRACEMALLOC_INITIALIZED;
  829. return 0;
  830. }
  831. static void
  832. tracemalloc_deinit(void)
  833. {
  834. if (tracemalloc_config.initialized != TRACEMALLOC_INITIALIZED)
  835. return;
  836. tracemalloc_config.initialized = TRACEMALLOC_FINALIZED;
  837. tracemalloc_stop();
  838. /* destroy hash tables */
  839. _Py_hashtable_destroy(tracemalloc_tracebacks);
  840. _Py_hashtable_destroy(tracemalloc_filenames);
  841. _Py_hashtable_destroy(tracemalloc_traces);
  842. #if defined(TRACE_RAW_MALLOC)
  843. if (tables_lock != NULL) {
  844. PyThread_free_lock(tables_lock);
  845. tables_lock = NULL;
  846. }
  847. #endif
  848. #ifdef REENTRANT_THREADLOCAL
  849. PyThread_delete_key(tracemalloc_reentrant_key);
  850. tracemalloc_reentrant_key = -1;
  851. #endif
  852. Py_XDECREF(unknown_filename);
  853. }
  854. static int
  855. tracemalloc_start(int max_nframe)
  856. {
  857. PyMemAllocatorEx alloc;
  858. size_t size;
  859. if (tracemalloc_init() < 0)
  860. return -1;
  861. if (tracemalloc_config.tracing) {
  862. /* hook already installed: do nothing */
  863. return 0;
  864. }
  865. assert(1 <= max_nframe && max_nframe <= MAX_NFRAME);
  866. tracemalloc_config.max_nframe = max_nframe;
  867. /* allocate a buffer to store a new traceback */
  868. size = TRACEBACK_SIZE(max_nframe);
  869. assert(tracemalloc_traceback == NULL);
  870. tracemalloc_traceback = raw_malloc(size);
  871. if (tracemalloc_traceback == NULL) {
  872. PyErr_NoMemory();
  873. return -1;
  874. }
  875. #ifdef TRACE_RAW_MALLOC
  876. alloc.malloc = tracemalloc_raw_malloc;
  877. alloc.calloc = tracemalloc_raw_calloc;
  878. alloc.realloc = tracemalloc_raw_realloc;
  879. alloc.free = tracemalloc_free;
  880. alloc.ctx = &allocators.raw;
  881. PyMem_GetAllocator(PYMEM_DOMAIN_RAW, &allocators.raw);
  882. PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &alloc);
  883. #endif
  884. alloc.malloc = tracemalloc_malloc_gil;
  885. alloc.calloc = tracemalloc_calloc_gil;
  886. alloc.realloc = tracemalloc_realloc_gil;
  887. alloc.free = tracemalloc_free;
  888. alloc.ctx = &allocators.mem;
  889. PyMem_GetAllocator(PYMEM_DOMAIN_MEM, &allocators.mem);
  890. PyMem_SetAllocator(PYMEM_DOMAIN_MEM, &alloc);
  891. alloc.ctx = &allocators.obj;
  892. PyMem_GetAllocator(PYMEM_DOMAIN_OBJ, &allocators.obj);
  893. PyMem_SetAllocator(PYMEM_DOMAIN_OBJ, &alloc);
  894. /* everything is ready: start tracing Python memory allocations */
  895. tracemalloc_config.tracing = 1;
  896. return 0;
  897. }
  898. static void
  899. tracemalloc_stop(void)
  900. {
  901. if (!tracemalloc_config.tracing)
  902. return;
  903. /* stop tracing Python memory allocations */
  904. tracemalloc_config.tracing = 0;
  905. /* unregister the hook on memory allocators */
  906. #ifdef TRACE_RAW_MALLOC
  907. PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &allocators.raw);
  908. #endif
  909. PyMem_SetAllocator(PYMEM_DOMAIN_MEM, &allocators.mem);
  910. PyMem_SetAllocator(PYMEM_DOMAIN_OBJ, &allocators.obj);
  911. tracemalloc_clear_traces();
  912. /* release memory */
  913. raw_free(tracemalloc_traceback);
  914. tracemalloc_traceback = NULL;
  915. }
  916. /*[clinic input]
  917. _tracemalloc.is_tracing
  918. Return True if the tracemalloc module is tracing Python memory allocations.
  919. [clinic start generated code]*/
  920. static PyObject *
  921. _tracemalloc_is_tracing_impl(PyObject *module)
  922. /*[clinic end generated code: output=2d763b42601cd3ef input=af104b0a00192f63]*/
  923. {
  924. return PyBool_FromLong(tracemalloc_config.tracing);
  925. }
  926. /*[clinic input]
  927. _tracemalloc.clear_traces
  928. Clear traces of memory blocks allocated by Python.
  929. [clinic start generated code]*/
  930. static PyObject *
  931. _tracemalloc_clear_traces_impl(PyObject *module)
  932. /*[clinic end generated code: output=a86080ee41b84197 input=0dab5b6c785183a5]*/
  933. {
  934. if (!tracemalloc_config.tracing)
  935. Py_RETURN_NONE;
  936. set_reentrant(1);
  937. tracemalloc_clear_traces();
  938. set_reentrant(0);
  939. Py_RETURN_NONE;
  940. }
  941. static PyObject*
  942. frame_to_pyobject(frame_t *frame)
  943. {
  944. PyObject *frame_obj, *lineno_obj;
  945. frame_obj = PyTuple_New(2);
  946. if (frame_obj == NULL)
  947. return NULL;
  948. Py_INCREF(frame->filename);
  949. PyTuple_SET_ITEM(frame_obj, 0, frame->filename);
  950. lineno_obj = PyLong_FromUnsignedLong(frame->lineno);
  951. if (lineno_obj == NULL) {
  952. Py_DECREF(frame_obj);
  953. return NULL;
  954. }
  955. PyTuple_SET_ITEM(frame_obj, 1, lineno_obj);
  956. return frame_obj;
  957. }
  958. static PyObject*
  959. traceback_to_pyobject(traceback_t *traceback, _Py_hashtable_t *intern_table)
  960. {
  961. int i;
  962. PyObject *frames, *frame;
  963. if (intern_table != NULL) {
  964. if (_Py_HASHTABLE_GET(intern_table, traceback, frames)) {
  965. Py_INCREF(frames);
  966. return frames;
  967. }
  968. }
  969. frames = PyTuple_New(traceback->nframe);
  970. if (frames == NULL)
  971. return NULL;
  972. for (i=0; i < traceback->nframe; i++) {
  973. frame = frame_to_pyobject(&traceback->frames[i]);
  974. if (frame == NULL) {
  975. Py_DECREF(frames);
  976. return NULL;
  977. }
  978. PyTuple_SET_ITEM(frames, i, frame);
  979. }
  980. if (intern_table != NULL) {
  981. if (_Py_HASHTABLE_SET(intern_table, traceback, frames) < 0) {
  982. Py_DECREF(frames);
  983. PyErr_NoMemory();
  984. return NULL;
  985. }
  986. /* intern_table keeps a new reference to frames */
  987. Py_INCREF(frames);
  988. }
  989. return frames;
  990. }
  991. static PyObject*
  992. trace_to_pyobject(unsigned int domain, trace_t *trace,
  993. _Py_hashtable_t *intern_tracebacks)
  994. {
  995. PyObject *trace_obj = NULL;
  996. PyObject *obj;
  997. trace_obj = PyTuple_New(3);
  998. if (trace_obj == NULL)
  999. return NULL;
  1000. obj = PyLong_FromSize_t(domain);
  1001. if (obj == NULL) {
  1002. Py_DECREF(trace_obj);
  1003. return NULL;
  1004. }
  1005. PyTuple_SET_ITEM(trace_obj, 0, obj);
  1006. obj = PyLong_FromSize_t(trace->size);
  1007. if (obj == NULL) {
  1008. Py_DECREF(trace_obj);
  1009. return NULL;
  1010. }
  1011. PyTuple_SET_ITEM(trace_obj, 1, obj);
  1012. obj = traceback_to_pyobject(trace->traceback, intern_tracebacks);
  1013. if (obj == NULL) {
  1014. Py_DECREF(trace_obj);
  1015. return NULL;
  1016. }
  1017. PyTuple_SET_ITEM(trace_obj, 2, obj);
  1018. return trace_obj;
  1019. }
  1020. typedef struct {
  1021. _Py_hashtable_t *traces;
  1022. _Py_hashtable_t *tracebacks;
  1023. PyObject *list;
  1024. } get_traces_t;
  1025. static int
  1026. tracemalloc_get_traces_fill(_Py_hashtable_t *traces, _Py_hashtable_entry_t *entry,
  1027. void *user_data)
  1028. {
  1029. get_traces_t *get_traces = user_data;
  1030. unsigned int domain;
  1031. trace_t trace;
  1032. PyObject *tracemalloc_obj;
  1033. int res;
  1034. if (tracemalloc_config.use_domain) {
  1035. pointer_t key;
  1036. _Py_HASHTABLE_ENTRY_READ_KEY(traces, entry, key);
  1037. domain = key.domain;
  1038. }
  1039. else {
  1040. domain = DEFAULT_DOMAIN;
  1041. }
  1042. _Py_HASHTABLE_ENTRY_READ_DATA(traces, entry, trace);
  1043. tracemalloc_obj = trace_to_pyobject(domain, &trace, get_traces->tracebacks);
  1044. if (tracemalloc_obj == NULL)
  1045. return 1;
  1046. res = PyList_Append(get_traces->list, tracemalloc_obj);
  1047. Py_DECREF(tracemalloc_obj);
  1048. if (res < 0)
  1049. return 1;
  1050. return 0;
  1051. }
  1052. static int
  1053. tracemalloc_pyobject_decref_cb(_Py_hashtable_t *tracebacks,
  1054. _Py_hashtable_entry_t *entry,
  1055. void *user_data)
  1056. {
  1057. PyObject *obj;
  1058. _Py_HASHTABLE_ENTRY_READ_DATA(tracebacks, entry, obj);
  1059. Py_DECREF(obj);
  1060. return 0;
  1061. }
  1062. /*[clinic input]
  1063. _tracemalloc._get_traces
  1064. Get traces of all memory blocks allocated by Python.
  1065. Return a list of (size: int, traceback: tuple) tuples.
  1066. traceback is a tuple of (filename: str, lineno: int) tuples.
  1067. Return an empty list if the tracemalloc module is disabled.
  1068. [clinic start generated code]*/
  1069. static PyObject *
  1070. _tracemalloc__get_traces_impl(PyObject *module)
  1071. /*[clinic end generated code: output=e9929876ced4b5cc input=6c7d2230b24255aa]*/
  1072. {
  1073. get_traces_t get_traces;
  1074. int err;
  1075. get_traces.traces = NULL;
  1076. get_traces.tracebacks = NULL;
  1077. get_traces.list = PyList_New(0);
  1078. if (get_traces.list == NULL)
  1079. goto error;
  1080. if (!tracemalloc_config.tracing)
  1081. return get_traces.list;
  1082. /* the traceback hash table is used temporarily to intern traceback tuple
  1083. of (filename, lineno) tuples */
  1084. get_traces.tracebacks = hashtable_new(sizeof(traceback_t *),
  1085. sizeof(PyObject *),
  1086. _Py_hashtable_hash_ptr,
  1087. _Py_hashtable_compare_direct);
  1088. if (get_traces.tracebacks == NULL) {
  1089. PyErr_NoMemory();
  1090. goto error;
  1091. }
  1092. TABLES_LOCK();
  1093. get_traces.traces = _Py_hashtable_copy(tracemalloc_traces);
  1094. TABLES_UNLOCK();
  1095. if (get_traces.traces == NULL) {
  1096. PyErr_NoMemory();
  1097. goto error;
  1098. }
  1099. set_reentrant(1);
  1100. err = _Py_hashtable_foreach(get_traces.traces,
  1101. tracemalloc_get_traces_fill, &get_traces);
  1102. set_reentrant(0);
  1103. if (err)
  1104. goto error;
  1105. goto finally;
  1106. error:
  1107. Py_CLEAR(get_traces.list);
  1108. finally:
  1109. if (get_traces.tracebacks != NULL) {
  1110. _Py_hashtable_foreach(get_traces.tracebacks,
  1111. tracemalloc_pyobject_decref_cb, NULL);
  1112. _Py_hashtable_destroy(get_traces.tracebacks);
  1113. }
  1114. if (get_traces.traces != NULL) {
  1115. _Py_hashtable_destroy(get_traces.traces);
  1116. }
  1117. return get_traces.list;
  1118. }
  1119. static traceback_t*
  1120. tracemalloc_get_traceback(unsigned int domain, uintptr_t ptr)
  1121. {
  1122. trace_t trace;
  1123. int found;
  1124. if (!tracemalloc_config.tracing)
  1125. return NULL;
  1126. TABLES_LOCK();
  1127. if (tracemalloc_config.use_domain) {
  1128. pointer_t key = {ptr, domain};
  1129. found = _Py_HASHTABLE_GET(tracemalloc_traces, key, trace);
  1130. }
  1131. else {
  1132. found = _Py_HASHTABLE_GET(tracemalloc_traces, ptr, trace);
  1133. }
  1134. TABLES_UNLOCK();
  1135. if (!found)
  1136. return NULL;
  1137. return trace.traceback;
  1138. }
  1139. /*[clinic input]
  1140. _tracemalloc._get_object_traceback
  1141. obj: object
  1142. /
  1143. Get the traceback where the Python object obj was allocated.
  1144. Return a tuple of (filename: str, lineno: int) tuples.
  1145. Return None if the tracemalloc module is disabled or did not
  1146. trace the allocation of the object.
  1147. [clinic start generated code]*/
  1148. static PyObject *
  1149. _tracemalloc__get_object_traceback(PyObject *module, PyObject *obj)
  1150. /*[clinic end generated code: output=41ee0553a658b0aa input=29495f1b21c53212]*/
  1151. {
  1152. PyTypeObject *type;
  1153. void *ptr;
  1154. traceback_t *traceback;
  1155. type = Py_TYPE(obj);
  1156. if (PyType_IS_GC(type))
  1157. ptr = (void *)((char *)obj - sizeof(PyGC_Head));
  1158. else
  1159. ptr = (void *)obj;
  1160. traceback = tracemalloc_get_traceback(DEFAULT_DOMAIN, (uintptr_t)ptr);
  1161. if (traceback == NULL)
  1162. Py_RETURN_NONE;
  1163. return traceback_to_pyobject(traceback, NULL);
  1164. }
  1165. #define PUTS(fd, str) _Py_write_noraise(fd, str, (int)strlen(str))
  1166. static void
  1167. _PyMem_DumpFrame(int fd, frame_t * frame)
  1168. {
  1169. PUTS(fd, " File \"");
  1170. _Py_DumpASCII(fd, frame->filename);
  1171. PUTS(fd, "\", line ");
  1172. _Py_DumpDecimal(fd, frame->lineno);
  1173. PUTS(fd, "\n");
  1174. }
  1175. /* Dump the traceback where a memory block was allocated into file descriptor
  1176. fd. The function may block on TABLES_LOCK() but it is unlikely. */
  1177. void
  1178. _PyMem_DumpTraceback(int fd, const void *ptr)
  1179. {
  1180. traceback_t *traceback;
  1181. int i;
  1182. traceback = tracemalloc_get_traceback(DEFAULT_DOMAIN, (uintptr_t)ptr);
  1183. if (traceback == NULL)
  1184. return;
  1185. PUTS(fd, "Memory block allocated at (most recent call first):\n");
  1186. for (i=0; i < traceback->nframe; i++) {
  1187. _PyMem_DumpFrame(fd, &traceback->frames[i]);
  1188. }
  1189. PUTS(fd, "\n");
  1190. }
  1191. #undef PUTS
  1192. /*[clinic input]
  1193. _tracemalloc.start
  1194. nframe: Py_ssize_t = 1
  1195. /
  1196. Start tracing Python memory allocations.
  1197. Also set the maximum number of frames stored in the traceback of a
  1198. trace to nframe.
  1199. [clinic start generated code]*/
  1200. static PyObject *
  1201. _tracemalloc_start_impl(PyObject *module, Py_ssize_t nframe)
  1202. /*[clinic end generated code: output=0f558d2079511553 input=997841629cc441cb]*/
  1203. {
  1204. int nframe_int;
  1205. if (nframe < 1 || nframe > MAX_NFRAME) {
  1206. PyErr_Format(PyExc_ValueError,
  1207. "the number of frames must be in range [1; %i]",
  1208. (int)MAX_NFRAME);
  1209. return NULL;
  1210. }
  1211. nframe_int = Py_SAFE_DOWNCAST(nframe, Py_ssize_t, int);
  1212. if (tracemalloc_start(nframe_int) < 0)
  1213. return NULL;
  1214. Py_RETURN_NONE;
  1215. }
  1216. /*[clinic input]
  1217. _tracemalloc.stop
  1218. Stop tracing Python memory allocations.
  1219. Also clear traces of memory blocks allocated by Python.
  1220. [clinic start generated code]*/
  1221. static PyObject *
  1222. _tracemalloc_stop_impl(PyObject *module)
  1223. /*[clinic end generated code: output=c3c42ae03e3955cd input=7478f075e51dae18]*/
  1224. {
  1225. tracemalloc_stop();
  1226. Py_RETURN_NONE;
  1227. }
  1228. /*[clinic input]
  1229. _tracemalloc.get_traceback_limit
  1230. Get the maximum number of frames stored in the traceback of a trace.
  1231. By default, a trace of an allocated memory block only stores
  1232. the most recent frame: the limit is 1.
  1233. [clinic start generated code]*/
  1234. static PyObject *
  1235. _tracemalloc_get_traceback_limit_impl(PyObject *module)
  1236. /*[clinic end generated code: output=d556d9306ba95567 input=da3cd977fc68ae3b]*/
  1237. {
  1238. return PyLong_FromLong(tracemalloc_config.max_nframe);
  1239. }
  1240. /*[clinic input]
  1241. _tracemalloc.get_tracemalloc_memory
  1242. Get the memory usage in bytes of the tracemalloc module.
  1243. This memory is used internally to trace memory allocations.
  1244. [clinic start generated code]*/
  1245. static PyObject *
  1246. _tracemalloc_get_tracemalloc_memory_impl(PyObject *module)
  1247. /*[clinic end generated code: output=e3f14e280a55f5aa input=5d919c0f4d5132ad]*/
  1248. {
  1249. size_t size;
  1250. size = _Py_hashtable_size(tracemalloc_tracebacks);
  1251. size += _Py_hashtable_size(tracemalloc_filenames);
  1252. TABLES_LOCK();
  1253. size += _Py_hashtable_size(tracemalloc_traces);
  1254. TABLES_UNLOCK();
  1255. return PyLong_FromSize_t(size);
  1256. }
  1257. /*[clinic input]
  1258. _tracemalloc.get_traced_memory
  1259. Get the current size and peak size of memory blocks traced by tracemalloc.
  1260. Returns a tuple: (current: int, peak: int).
  1261. [clinic start generated code]*/
  1262. static PyObject *
  1263. _tracemalloc_get_traced_memory_impl(PyObject *module)
  1264. /*[clinic end generated code: output=5b167189adb9e782 input=61ddb5478400ff66]*/
  1265. {
  1266. Py_ssize_t size, peak_size;
  1267. if (!tracemalloc_config.tracing)
  1268. return Py_BuildValue("ii", 0, 0);
  1269. TABLES_LOCK();
  1270. size = tracemalloc_traced_memory;
  1271. peak_size = tracemalloc_peak_traced_memory;
  1272. TABLES_UNLOCK();
  1273. return Py_BuildValue("nn", size, peak_size);
  1274. }
  1275. static PyMethodDef module_methods[] = {
  1276. _TRACEMALLOC_IS_TRACING_METHODDEF
  1277. _TRACEMALLOC_CLEAR_TRACES_METHODDEF
  1278. _TRACEMALLOC__GET_TRACES_METHODDEF
  1279. _TRACEMALLOC__GET_OBJECT_TRACEBACK_METHODDEF
  1280. _TRACEMALLOC_START_METHODDEF
  1281. _TRACEMALLOC_STOP_METHODDEF
  1282. _TRACEMALLOC_GET_TRACEBACK_LIMIT_METHODDEF
  1283. _TRACEMALLOC_GET_TRACEMALLOC_MEMORY_METHODDEF
  1284. _TRACEMALLOC_GET_TRACED_MEMORY_METHODDEF
  1285. /* sentinel */
  1286. {NULL, NULL}
  1287. };
  1288. PyDoc_STRVAR(module_doc,
  1289. "Debug module to trace memory blocks allocated by Python.");
  1290. static struct PyModuleDef module_def = {
  1291. PyModuleDef_HEAD_INIT,
  1292. "_tracemalloc",
  1293. module_doc,
  1294. 0, /* non-negative size to be able to unload the module */
  1295. module_methods,
  1296. NULL,
  1297. };
  1298. PyMODINIT_FUNC
  1299. PyInit__tracemalloc(void)
  1300. {
  1301. PyObject *m;
  1302. m = PyModule_Create(&module_def);
  1303. if (m == NULL)
  1304. return NULL;
  1305. if (tracemalloc_init() < 0)
  1306. return NULL;
  1307. return m;
  1308. }
  1309. static int
  1310. parse_sys_xoptions(PyObject *value)
  1311. {
  1312. PyObject *valuelong;
  1313. long nframe;
  1314. if (value == Py_True)
  1315. return 1;
  1316. assert(PyUnicode_Check(value));
  1317. if (PyUnicode_GetLength(value) == 0)
  1318. return -1;
  1319. valuelong = PyLong_FromUnicodeObject(value, 10);
  1320. if (valuelong == NULL)
  1321. return -1;
  1322. nframe = PyLong_AsLong(valuelong);
  1323. Py_DECREF(valuelong);
  1324. if (nframe == -1 && PyErr_Occurred())
  1325. return -1;
  1326. if (nframe < 1 || nframe > MAX_NFRAME)
  1327. return -1;
  1328. return Py_SAFE_DOWNCAST(nframe, long, int);
  1329. }
  1330. int
  1331. _PyTraceMalloc_Init(void)
  1332. {
  1333. char *p;
  1334. int nframe;
  1335. assert(PyGILState_Check());
  1336. if ((p = Py_GETENV("PYTHONTRACEMALLOC")) && *p != '\0') {
  1337. char *endptr = p;
  1338. long value;
  1339. errno = 0;
  1340. value = strtol(p, &endptr, 10);
  1341. if (*endptr != '\0'
  1342. || value < 1
  1343. || value > MAX_NFRAME
  1344. || errno == ERANGE)
  1345. {
  1346. Py_FatalError("PYTHONTRACEMALLOC: invalid number of frames");
  1347. return -1;
  1348. }
  1349. nframe = (int)value;
  1350. }
  1351. else {
  1352. PyObject *xoptions, *key, *value;
  1353. xoptions = PySys_GetXOptions();
  1354. if (xoptions == NULL)
  1355. return -1;
  1356. key = PyUnicode_FromString("tracemalloc");
  1357. if (key == NULL)
  1358. return -1;
  1359. value = PyDict_GetItemWithError(xoptions, key); /* borrowed */
  1360. Py_DECREF(key);
  1361. if (value == NULL) {
  1362. if (PyErr_Occurred())
  1363. return -1;
  1364. /* -X tracemalloc is not used */
  1365. return 0;
  1366. }
  1367. nframe = parse_sys_xoptions(value);
  1368. if (nframe < 0) {
  1369. Py_FatalError("-X tracemalloc=NFRAME: invalid number of frames");
  1370. }
  1371. }
  1372. return tracemalloc_start(nframe);
  1373. }
  1374. void
  1375. _PyTraceMalloc_Fini(void)
  1376. {
  1377. assert(PyGILState_Check());
  1378. tracemalloc_deinit();
  1379. }
  1380. int
  1381. PyTraceMalloc_Track(unsigned int domain, uintptr_t ptr,
  1382. size_t size)
  1383. {
  1384. int res;
  1385. PyGILState_STATE gil_state;
  1386. if (!tracemalloc_config.tracing) {
  1387. /* tracemalloc is not tracing: do nothing */
  1388. return -2;
  1389. }
  1390. gil_state = PyGILState_Ensure();
  1391. TABLES_LOCK();
  1392. res = tracemalloc_add_trace(domain, ptr, size);
  1393. TABLES_UNLOCK();
  1394. PyGILState_Release(gil_state);
  1395. return res;
  1396. }
  1397. int
  1398. PyTraceMalloc_Untrack(unsigned int domain, uintptr_t ptr)
  1399. {
  1400. if (!tracemalloc_config.tracing) {
  1401. /* tracemalloc is not tracing: do nothing */
  1402. return -2;
  1403. }
  1404. TABLES_LOCK();
  1405. tracemalloc_remove_trace(domain, ptr);
  1406. TABLES_UNLOCK();
  1407. return 0;
  1408. }
  1409. PyObject*
  1410. _PyTraceMalloc_GetTraceback(unsigned int domain, uintptr_t ptr)
  1411. {
  1412. traceback_t *traceback;
  1413. traceback = tracemalloc_get_traceback(domain, ptr);
  1414. if (traceback == NULL)
  1415. Py_RETURN_NONE;
  1416. return traceback_to_pyobject(traceback, NULL);
  1417. }