bpo-43439: Add audit hooks for gc functions (GH-24794)

This commit is contained in:
Pablo Galindo 2021-03-10 00:53:57 +00:00 committed by GitHub
parent 62a03cd490
commit b4f9089d4a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 56 additions and 0 deletions

View file

@ -72,6 +72,8 @@ The :mod:`gc` module provides the following functions:
.. versionchanged:: 3.8 .. versionchanged:: 3.8
New *generation* parameter. New *generation* parameter.
.. audit-event:: gc.get_objects generation gc.get_objects
.. function:: get_stats() .. function:: get_stats()
Return a list of three per-generation dictionaries containing collection Return a list of three per-generation dictionaries containing collection
@ -141,6 +143,8 @@ The :mod:`gc` module provides the following functions:
invalid state. Avoid using :func:`get_referrers` for any purpose other than invalid state. Avoid using :func:`get_referrers` for any purpose other than
debugging. debugging.
.. audit-event:: gc.get_referrers objs gc.get_referrers
.. function:: get_referents(*objs) .. function:: get_referents(*objs)
@ -152,6 +156,7 @@ The :mod:`gc` module provides the following functions:
be involved in a cycle. So, for example, if an integer is directly reachable be involved in a cycle. So, for example, if an integer is directly reachable
from an argument, that integer object may or may not appear in the result list. from an argument, that integer object may or may not appear in the result list.
.. audit-event:: gc.get_referents objs gc.get_referents
.. function:: is_tracked(obj) .. function:: is_tracked(obj)

View file

@ -673,9 +673,16 @@ When a module does not define ``__loader__``, fall back to ``__spec__.loader``.
encodings encodings
--------- ---------
:func:`encodings.normalize_encoding` now ignores non-ASCII characters. :func:`encodings.normalize_encoding` now ignores non-ASCII characters.
(Contributed by Hai Shi in :issue:`39337`.) (Contributed by Hai Shi in :issue:`39337`.)
gc
--
Added audit hooks for :func:`gc.get_objects`, :func:`gc.get_referrers` and
:func:`gc.get_referents`. (Contributed by Pablo Galindo in :issue:`43439`.)
glob glob
---- ----

View file

@ -323,6 +323,24 @@ def test_socket():
sock.close() sock.close()
def test_gc():
import gc
def hook(event, args):
if event.startswith("gc."):
print(event, *args)
sys.addaudithook(hook)
gc.get_objects(generation=1)
x = object()
y = [x]
gc.get_referrers(x)
gc.get_referents(y)
if __name__ == "__main__": if __name__ == "__main__":
from test.support import suppress_msvcrt_asserts from test.support import suppress_msvcrt_asserts

View file

@ -118,5 +118,18 @@ class AuditTest(unittest.TestCase):
self.assertEqual(events[2][0], "socket.bind") self.assertEqual(events[2][0], "socket.bind")
self.assertTrue(events[2][2].endswith("('127.0.0.1', 8080)")) self.assertTrue(events[2][2].endswith("('127.0.0.1', 8080)"))
def test_gc(self):
returncode, events, stderr = self.run_python("test_gc")
if returncode:
self.fail(stderr)
if support.verbose:
print(*events, sep='\n')
self.assertEqual(
[event[0] for event in events],
["gc.get_objects", "gc.get_referrers", "gc.get_referents"]
)
if __name__ == "__main__": if __name__ == "__main__":
unittest.main() unittest.main()

View file

@ -0,0 +1,2 @@
Add audit hooks for :func:`gc.get_objects`, :func:`gc.get_referrers` and
:func:`gc.get_referents`. Patch by Pablo Galindo.

View file

@ -1690,6 +1690,10 @@ Return the list of objects that directly refer to any of objs.");
static PyObject * static PyObject *
gc_get_referrers(PyObject *self, PyObject *args) gc_get_referrers(PyObject *self, PyObject *args)
{ {
if (PySys_Audit("gc.get_referrers", "O", args) < 0) {
return NULL;
}
PyObject *result = PyList_New(0); PyObject *result = PyList_New(0);
if (!result) { if (!result) {
return NULL; return NULL;
@ -1720,6 +1724,9 @@ static PyObject *
gc_get_referents(PyObject *self, PyObject *args) gc_get_referents(PyObject *self, PyObject *args)
{ {
Py_ssize_t i; Py_ssize_t i;
if (PySys_Audit("gc.get_referents", "O", args) < 0) {
return NULL;
}
PyObject *result = PyList_New(0); PyObject *result = PyList_New(0);
if (result == NULL) if (result == NULL)
@ -1762,6 +1769,10 @@ gc_get_objects_impl(PyObject *module, Py_ssize_t generation)
PyObject* result; PyObject* result;
GCState *gcstate = &tstate->interp->gc; GCState *gcstate = &tstate->interp->gc;
if (PySys_Audit("gc.get_objects", "n", generation) < 0) {
return NULL;
}
result = PyList_New(0); result = PyList_New(0);
if (result == NULL) { if (result == NULL) {
return NULL; return NULL;