• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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