1 /*
2 * Python interface to the garbage collector.
3 *
4 * See Python/gc.c for the implementation of the garbage collector.
5 */
6
7 #include "Python.h"
8 #include "pycore_gc.h"
9 #include "pycore_object.h" // _PyObject_IS_GC()
10 #include "pycore_pystate.h" // _PyInterpreterState_GET()
11
12 typedef struct _gc_runtime_state GCState;
13
14 static GCState *
get_gc_state(void)15 get_gc_state(void)
16 {
17 PyInterpreterState *interp = _PyInterpreterState_GET();
18 return &interp->gc;
19 }
20
21 /*[clinic input]
22 module gc
23 [clinic start generated code]*/
24 /*[clinic end generated code: output=da39a3ee5e6b4b0d input=b5c9690ecc842d79]*/
25 #include "clinic/gcmodule.c.h"
26
27 /*[clinic input]
28 gc.enable
29
30 Enable automatic garbage collection.
31 [clinic start generated code]*/
32
33 static PyObject *
gc_enable_impl(PyObject * module)34 gc_enable_impl(PyObject *module)
35 /*[clinic end generated code: output=45a427e9dce9155c input=81ac4940ca579707]*/
36 {
37 PyGC_Enable();
38 Py_RETURN_NONE;
39 }
40
41 /*[clinic input]
42 gc.disable
43
44 Disable automatic garbage collection.
45 [clinic start generated code]*/
46
47 static PyObject *
gc_disable_impl(PyObject * module)48 gc_disable_impl(PyObject *module)
49 /*[clinic end generated code: output=97d1030f7aa9d279 input=8c2e5a14e800d83b]*/
50 {
51 PyGC_Disable();
52 Py_RETURN_NONE;
53 }
54
55 /*[clinic input]
56 gc.isenabled -> bool
57
58 Returns true if automatic garbage collection is enabled.
59 [clinic start generated code]*/
60
61 static int
gc_isenabled_impl(PyObject * module)62 gc_isenabled_impl(PyObject *module)
63 /*[clinic end generated code: output=1874298331c49130 input=30005e0422373b31]*/
64 {
65 return PyGC_IsEnabled();
66 }
67
68 /*[clinic input]
69 gc.collect -> Py_ssize_t
70
71 generation: int(c_default="NUM_GENERATIONS - 1") = 2
72
73 Run the garbage collector.
74
75 With no arguments, run a full collection. The optional argument
76 may be an integer specifying which generation to collect. A ValueError
77 is raised if the generation number is invalid.
78
79 The number of unreachable objects is returned.
80 [clinic start generated code]*/
81
82 static Py_ssize_t
gc_collect_impl(PyObject * module,int generation)83 gc_collect_impl(PyObject *module, int generation)
84 /*[clinic end generated code: output=b697e633043233c7 input=40720128b682d879]*/
85 {
86 PyThreadState *tstate = _PyThreadState_GET();
87
88 if (generation < 0 || generation >= NUM_GENERATIONS) {
89 _PyErr_SetString(tstate, PyExc_ValueError, "invalid generation");
90 return -1;
91 }
92
93 return _PyGC_Collect(tstate, generation, _Py_GC_REASON_MANUAL);
94 }
95
96 /*[clinic input]
97 gc.set_debug
98
99 flags: int
100 An integer that can have the following bits turned on:
101 DEBUG_STATS - Print statistics during collection.
102 DEBUG_COLLECTABLE - Print collectable objects found.
103 DEBUG_UNCOLLECTABLE - Print unreachable but uncollectable objects
104 found.
105 DEBUG_SAVEALL - Save objects to gc.garbage rather than freeing them.
106 DEBUG_LEAK - Debug leaking programs (everything but STATS).
107 /
108
109 Set the garbage collection debugging flags.
110
111 Debugging information is written to sys.stderr.
112 [clinic start generated code]*/
113
114 static PyObject *
gc_set_debug_impl(PyObject * module,int flags)115 gc_set_debug_impl(PyObject *module, int flags)
116 /*[clinic end generated code: output=7c8366575486b228 input=5e5ce15e84fbed15]*/
117 {
118 GCState *gcstate = get_gc_state();
119 gcstate->debug = flags;
120 Py_RETURN_NONE;
121 }
122
123 /*[clinic input]
124 gc.get_debug -> int
125
126 Get the garbage collection debugging flags.
127 [clinic start generated code]*/
128
129 static int
gc_get_debug_impl(PyObject * module)130 gc_get_debug_impl(PyObject *module)
131 /*[clinic end generated code: output=91242f3506cd1e50 input=91a101e1c3b98366]*/
132 {
133 GCState *gcstate = get_gc_state();
134 return gcstate->debug;
135 }
136
137 /*[clinic input]
138 gc.set_threshold
139
140 threshold0: int
141 [
142 threshold1: int
143 [
144 threshold2: int
145 ]
146 ]
147 /
148
149 Set the collection thresholds (the collection frequency).
150
151 Setting 'threshold0' to zero disables collection.
152 [clinic start generated code]*/
153
154 static PyObject *
gc_set_threshold_impl(PyObject * module,int threshold0,int group_right_1,int threshold1,int group_right_2,int threshold2)155 gc_set_threshold_impl(PyObject *module, int threshold0, int group_right_1,
156 int threshold1, int group_right_2, int threshold2)
157 /*[clinic end generated code: output=2e3c7c7dd59060f3 input=0d9612db50984eec]*/
158 {
159 GCState *gcstate = get_gc_state();
160
161 gcstate->generations[0].threshold = threshold0;
162 if (group_right_1) {
163 gcstate->generations[1].threshold = threshold1;
164 }
165 if (group_right_2) {
166 gcstate->generations[2].threshold = threshold2;
167
168 /* generations higher than 2 get the same threshold */
169 for (int i = 3; i < NUM_GENERATIONS; i++) {
170 gcstate->generations[i].threshold = gcstate->generations[2].threshold;
171 }
172 }
173 Py_RETURN_NONE;
174 }
175
176 /*[clinic input]
177 gc.get_threshold
178
179 Return the current collection thresholds.
180 [clinic start generated code]*/
181
182 static PyObject *
gc_get_threshold_impl(PyObject * module)183 gc_get_threshold_impl(PyObject *module)
184 /*[clinic end generated code: output=7902bc9f41ecbbd8 input=286d79918034d6e6]*/
185 {
186 GCState *gcstate = get_gc_state();
187 return Py_BuildValue("(iii)",
188 gcstate->generations[0].threshold,
189 gcstate->generations[1].threshold,
190 gcstate->generations[2].threshold);
191 }
192
193 /*[clinic input]
194 gc.get_count
195
196 Return a three-tuple of the current collection counts.
197 [clinic start generated code]*/
198
199 static PyObject *
gc_get_count_impl(PyObject * module)200 gc_get_count_impl(PyObject *module)
201 /*[clinic end generated code: output=354012e67b16398f input=a392794a08251751]*/
202 {
203 GCState *gcstate = get_gc_state();
204
205 #ifdef Py_GIL_DISABLED
206 _PyThreadStateImpl *tstate = (_PyThreadStateImpl *)_PyThreadState_GET();
207 struct _gc_thread_state *gc = &tstate->gc;
208
209 // Flush the local allocation count to the global count
210 _Py_atomic_add_int(&gcstate->generations[0].count, (int)gc->alloc_count);
211 gc->alloc_count = 0;
212 #endif
213
214 return Py_BuildValue("(iii)",
215 gcstate->generations[0].count,
216 gcstate->generations[1].count,
217 gcstate->generations[2].count);
218 }
219
220 /*[clinic input]
221 gc.get_referrers
222
223 *objs as args: object
224
225 Return the list of objects that directly refer to any of 'objs'.
226 [clinic start generated code]*/
227
228 static PyObject *
gc_get_referrers_impl(PyObject * module,PyObject * args)229 gc_get_referrers_impl(PyObject *module, PyObject *args)
230 /*[clinic end generated code: output=296a09587f6a86b5 input=bae96961b14a0922]*/
231 {
232 if (PySys_Audit("gc.get_referrers", "(O)", args) < 0) {
233 return NULL;
234 }
235
236 PyInterpreterState *interp = _PyInterpreterState_GET();
237 return _PyGC_GetReferrers(interp, args);
238 }
239
240 /* Append obj to list; return true if error (out of memory), false if OK. */
241 static int
referentsvisit(PyObject * obj,void * arg)242 referentsvisit(PyObject *obj, void *arg)
243 {
244 PyObject *list = arg;
245 return PyList_Append(list, obj) < 0;
246 }
247
248 static int
append_referrents(PyObject * result,PyObject * args)249 append_referrents(PyObject *result, PyObject *args)
250 {
251 for (Py_ssize_t i = 0; i < PyTuple_GET_SIZE(args); i++) {
252 PyObject *obj = PyTuple_GET_ITEM(args, i);
253 if (!_PyObject_IS_GC(obj)) {
254 continue;
255 }
256
257 traverseproc traverse = Py_TYPE(obj)->tp_traverse;
258 if (!traverse) {
259 continue;
260 }
261 if (traverse(obj, referentsvisit, result)) {
262 return -1;
263 }
264 }
265 return 0;
266 }
267
268 /*[clinic input]
269 gc.get_referents
270
271 *objs as args: object
272
273 Return the list of objects that are directly referred to by 'objs'.
274 [clinic start generated code]*/
275
276 static PyObject *
gc_get_referents_impl(PyObject * module,PyObject * args)277 gc_get_referents_impl(PyObject *module, PyObject *args)
278 /*[clinic end generated code: output=d47dc02cefd06fe8 input=b3ceab0c34038cbf]*/
279 {
280 if (PySys_Audit("gc.get_referents", "(O)", args) < 0) {
281 return NULL;
282 }
283 PyInterpreterState *interp = _PyInterpreterState_GET();
284 PyObject *result = PyList_New(0);
285
286 if (result == NULL)
287 return NULL;
288
289 // NOTE: stop the world is a no-op in default build
290 _PyEval_StopTheWorld(interp);
291 int err = append_referrents(result, args);
292 _PyEval_StartTheWorld(interp);
293
294 if (err < 0) {
295 Py_CLEAR(result);
296 }
297
298 return result;
299 }
300
301 /*[clinic input]
302 gc.get_objects
303 generation: Py_ssize_t(accept={int, NoneType}, c_default="-1") = None
304 Generation to extract the objects from.
305
306 Return a list of objects tracked by the collector (excluding the list returned).
307
308 If generation is not None, return only the objects tracked by the collector
309 that are in that generation.
310 [clinic start generated code]*/
311
312 static PyObject *
gc_get_objects_impl(PyObject * module,Py_ssize_t generation)313 gc_get_objects_impl(PyObject *module, Py_ssize_t generation)
314 /*[clinic end generated code: output=48b35fea4ba6cb0e input=ef7da9df9806754c]*/
315 {
316 if (PySys_Audit("gc.get_objects", "n", generation) < 0) {
317 return NULL;
318 }
319
320 if (generation >= NUM_GENERATIONS) {
321 return PyErr_Format(PyExc_ValueError,
322 "generation parameter must be less than the number of "
323 "available generations (%i)",
324 NUM_GENERATIONS);
325 }
326
327 if (generation < -1) {
328 PyErr_SetString(PyExc_ValueError,
329 "generation parameter cannot be negative");
330 return NULL;
331 }
332
333 PyInterpreterState *interp = _PyInterpreterState_GET();
334 return _PyGC_GetObjects(interp, (int)generation);
335 }
336
337 /*[clinic input]
338 gc.get_stats
339
340 Return a list of dictionaries containing per-generation statistics.
341 [clinic start generated code]*/
342
343 static PyObject *
gc_get_stats_impl(PyObject * module)344 gc_get_stats_impl(PyObject *module)
345 /*[clinic end generated code: output=a8ab1d8a5d26f3ab input=1ef4ed9d17b1a470]*/
346 {
347 int i;
348 struct gc_generation_stats stats[NUM_GENERATIONS], *st;
349
350 /* To get consistent values despite allocations while constructing
351 the result list, we use a snapshot of the running stats. */
352 GCState *gcstate = get_gc_state();
353 for (i = 0; i < NUM_GENERATIONS; i++) {
354 stats[i] = gcstate->generation_stats[i];
355 }
356
357 PyObject *result = PyList_New(0);
358 if (result == NULL)
359 return NULL;
360
361 for (i = 0; i < NUM_GENERATIONS; i++) {
362 PyObject *dict;
363 st = &stats[i];
364 dict = Py_BuildValue("{snsnsn}",
365 "collections", st->collections,
366 "collected", st->collected,
367 "uncollectable", st->uncollectable
368 );
369 if (dict == NULL)
370 goto error;
371 if (PyList_Append(result, dict)) {
372 Py_DECREF(dict);
373 goto error;
374 }
375 Py_DECREF(dict);
376 }
377 return result;
378
379 error:
380 Py_XDECREF(result);
381 return NULL;
382 }
383
384
385 /*[clinic input]
386 gc.is_tracked -> bool
387
388 obj: object
389 /
390
391 Returns true if the object is tracked by the garbage collector.
392
393 Simple atomic objects will return false.
394 [clinic start generated code]*/
395
396 static int
gc_is_tracked_impl(PyObject * module,PyObject * obj)397 gc_is_tracked_impl(PyObject *module, PyObject *obj)
398 /*[clinic end generated code: output=91c8d086b7f47a33 input=423b98ec680c3126]*/
399 {
400 return PyObject_GC_IsTracked(obj);
401 }
402
403 /*[clinic input]
404 gc.is_finalized -> bool
405
406 obj: object
407 /
408
409 Returns true if the object has been already finalized by the GC.
410 [clinic start generated code]*/
411
412 static int
gc_is_finalized_impl(PyObject * module,PyObject * obj)413 gc_is_finalized_impl(PyObject *module, PyObject *obj)
414 /*[clinic end generated code: output=401ff5d6fc660429 input=ca4d111c8f8c4e3a]*/
415 {
416 return PyObject_GC_IsFinalized(obj);
417 }
418
419 /*[clinic input]
420 gc.freeze
421
422 Freeze all current tracked objects and ignore them for future collections.
423
424 This can be used before a POSIX fork() call to make the gc copy-on-write friendly.
425 Note: collection before a POSIX fork() call may free pages for future allocation
426 which can cause copy-on-write.
427 [clinic start generated code]*/
428
429 static PyObject *
gc_freeze_impl(PyObject * module)430 gc_freeze_impl(PyObject *module)
431 /*[clinic end generated code: output=502159d9cdc4c139 input=b602b16ac5febbe5]*/
432 {
433 PyInterpreterState *interp = _PyInterpreterState_GET();
434 _PyGC_Freeze(interp);
435 Py_RETURN_NONE;
436 }
437
438 /*[clinic input]
439 gc.unfreeze
440
441 Unfreeze all objects in the permanent generation.
442
443 Put all objects in the permanent generation back into oldest generation.
444 [clinic start generated code]*/
445
446 static PyObject *
gc_unfreeze_impl(PyObject * module)447 gc_unfreeze_impl(PyObject *module)
448 /*[clinic end generated code: output=1c15f2043b25e169 input=2dd52b170f4cef6c]*/
449 {
450 PyInterpreterState *interp = _PyInterpreterState_GET();
451 _PyGC_Unfreeze(interp);
452 Py_RETURN_NONE;
453 }
454
455 /*[clinic input]
456 gc.get_freeze_count -> Py_ssize_t
457
458 Return the number of objects in the permanent generation.
459 [clinic start generated code]*/
460
461 static Py_ssize_t
gc_get_freeze_count_impl(PyObject * module)462 gc_get_freeze_count_impl(PyObject *module)
463 /*[clinic end generated code: output=61cbd9f43aa032e1 input=45ffbc65cfe2a6ed]*/
464 {
465 PyInterpreterState *interp = _PyInterpreterState_GET();
466 return _PyGC_GetFreezeCount(interp);
467 }
468
469
470 PyDoc_STRVAR(gc__doc__,
471 "This module provides access to the garbage collector for reference cycles.\n"
472 "\n"
473 "enable() -- Enable automatic garbage collection.\n"
474 "disable() -- Disable automatic garbage collection.\n"
475 "isenabled() -- Returns true if automatic collection is enabled.\n"
476 "collect() -- Do a full collection right now.\n"
477 "get_count() -- Return the current collection counts.\n"
478 "get_stats() -- Return list of dictionaries containing per-generation stats.\n"
479 "set_debug() -- Set debugging flags.\n"
480 "get_debug() -- Get debugging flags.\n"
481 "set_threshold() -- Set the collection thresholds.\n"
482 "get_threshold() -- Return the current the collection thresholds.\n"
483 "get_objects() -- Return a list of all objects tracked by the collector.\n"
484 "is_tracked() -- Returns true if a given object is tracked.\n"
485 "is_finalized() -- Returns true if a given object has been already finalized.\n"
486 "get_referrers() -- Return the list of objects that refer to an object.\n"
487 "get_referents() -- Return the list of objects that an object refers to.\n"
488 "freeze() -- Freeze all tracked objects and ignore them for future collections.\n"
489 "unfreeze() -- Unfreeze all objects in the permanent generation.\n"
490 "get_freeze_count() -- Return the number of objects in the permanent generation.\n");
491
492 static PyMethodDef GcMethods[] = {
493 GC_ENABLE_METHODDEF
494 GC_DISABLE_METHODDEF
495 GC_ISENABLED_METHODDEF
496 GC_SET_DEBUG_METHODDEF
497 GC_GET_DEBUG_METHODDEF
498 GC_GET_COUNT_METHODDEF
499 GC_SET_THRESHOLD_METHODDEF
500 GC_GET_THRESHOLD_METHODDEF
501 GC_COLLECT_METHODDEF
502 GC_GET_OBJECTS_METHODDEF
503 GC_GET_STATS_METHODDEF
504 GC_IS_TRACKED_METHODDEF
505 GC_IS_FINALIZED_METHODDEF
506 GC_GET_REFERRERS_METHODDEF
507 GC_GET_REFERENTS_METHODDEF
508 GC_FREEZE_METHODDEF
509 GC_UNFREEZE_METHODDEF
510 GC_GET_FREEZE_COUNT_METHODDEF
511 {NULL, NULL} /* Sentinel */
512 };
513
514 static int
gcmodule_exec(PyObject * module)515 gcmodule_exec(PyObject *module)
516 {
517 GCState *gcstate = get_gc_state();
518
519 /* garbage and callbacks are initialized by _PyGC_Init() early in
520 * interpreter lifecycle. */
521 assert(gcstate->garbage != NULL);
522 if (PyModule_AddObjectRef(module, "garbage", gcstate->garbage) < 0) {
523 return -1;
524 }
525 assert(gcstate->callbacks != NULL);
526 if (PyModule_AddObjectRef(module, "callbacks", gcstate->callbacks) < 0) {
527 return -1;
528 }
529
530 #define ADD_INT(NAME) if (PyModule_AddIntConstant(module, #NAME, _PyGC_ ## NAME) < 0) { return -1; }
531 ADD_INT(DEBUG_STATS);
532 ADD_INT(DEBUG_COLLECTABLE);
533 ADD_INT(DEBUG_UNCOLLECTABLE);
534 ADD_INT(DEBUG_SAVEALL);
535 ADD_INT(DEBUG_LEAK);
536 #undef ADD_INT
537 return 0;
538 }
539
540 static PyModuleDef_Slot gcmodule_slots[] = {
541 {Py_mod_exec, gcmodule_exec},
542 {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED},
543 {Py_mod_gil, Py_MOD_GIL_NOT_USED},
544 {0, NULL}
545 };
546
547 static struct PyModuleDef gcmodule = {
548 PyModuleDef_HEAD_INIT,
549 .m_name = "gc",
550 .m_doc = gc__doc__,
551 .m_size = 0, // per interpreter state, see: get_gc_state()
552 .m_methods = GcMethods,
553 .m_slots = gcmodule_slots
554 };
555
556 PyMODINIT_FUNC
PyInit_gc(void)557 PyInit_gc(void)
558 {
559 return PyModuleDef_Init(&gcmodule);
560 }
561