bpo-41162: Clear audit hooks later during finalization (GH-21222)

This commit is contained in:
Konge 2020-07-04 05:06:46 +08:00 committed by GitHub
parent d160e0f8e2
commit daa0fe03a5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 16 additions and 45 deletions

View File

@ -44,28 +44,6 @@ class TestHook:
raise self.exc_type("saw event " + event) raise self.exc_type("saw event " + event)
class TestFinalizeHook:
"""Used in the test_finalize_hooks function to ensure that hooks
are correctly cleaned up, that they are notified about the cleanup,
and are unable to prevent it.
"""
def __init__(self):
print("Created", id(self), file=sys.stdout, flush=True)
def __call__(self, event, args):
# Avoid recursion when we call id() below
if event == "builtins.id":
return
print(event, id(self), file=sys.stdout, flush=True)
if event == "cpython._PySys_ClearAuditHooks":
raise RuntimeError("Should be ignored")
elif event == "cpython.PyInterpreterState_Clear":
raise RuntimeError("Should be ignored")
# Simple helpers, since we are not in unittest here # Simple helpers, since we are not in unittest here
def assertEqual(x, y): def assertEqual(x, y):
if x != y: if x != y:
@ -128,10 +106,6 @@ def test_block_add_hook_baseexception():
pass pass
def test_finalize_hooks():
sys.addaudithook(TestFinalizeHook())
def test_pickle(): def test_pickle():
import pickle import pickle

View File

@ -51,22 +51,6 @@ class AuditTest(unittest.TestCase):
def test_block_add_hook_baseexception(self): def test_block_add_hook_baseexception(self):
self.do_test("test_block_add_hook_baseexception") self.do_test("test_block_add_hook_baseexception")
def test_finalize_hooks(self):
returncode, events, stderr = self.run_python("test_finalize_hooks")
if stderr:
print(stderr, file=sys.stderr)
if returncode:
self.fail(stderr)
firstId = events[0][2]
self.assertSequenceEqual(
[
("Created", " ", firstId),
("cpython._PySys_ClearAuditHooks", " ", firstId),
],
events,
)
def test_pickle(self): def test_pickle(self):
support.import_module("pickle") support.import_module("pickle")

View File

@ -0,0 +1 @@
Audit hooks are now cleared later during finalization to avoid missing events.

View File

@ -1112,8 +1112,11 @@ static int test_open_code_hook(void)
return result; return result;
} }
static int _audit_hook_clear_count = 0;
static int _audit_hook(const char *event, PyObject *args, void *userdata) static int _audit_hook(const char *event, PyObject *args, void *userdata)
{ {
assert(args && PyTuple_CheckExact(args));
if (strcmp(event, "_testembed.raise") == 0) { if (strcmp(event, "_testembed.raise") == 0) {
PyErr_SetString(PyExc_RuntimeError, "Intentional error"); PyErr_SetString(PyExc_RuntimeError, "Intentional error");
return -1; return -1;
@ -1122,6 +1125,8 @@ static int _audit_hook(const char *event, PyObject *args, void *userdata)
return -1; return -1;
} }
return 0; return 0;
} else if (strcmp(event, "cpython._PySys_ClearAuditHooks") == 0) {
_audit_hook_clear_count += 1;
} }
return 0; return 0;
} }
@ -1167,6 +1172,9 @@ static int test_audit(void)
{ {
int result = _test_audit(42); int result = _test_audit(42);
Py_Finalize(); Py_Finalize();
if (_audit_hook_clear_count != 1) {
return 0x1000 | _audit_hook_clear_count;
}
return result; return result;
} }

View File

@ -1291,6 +1291,13 @@ finalize_interp_clear(PyThreadState *tstate)
_PyGC_CollectNoFail(); _PyGC_CollectNoFail();
} }
/* Clear all loghooks */
/* Both _PySys_Audit function and users still need PyObject, such as tuple.
Call _PySys_ClearAuditHooks when PyObject available. */
if (is_main_interp) {
_PySys_ClearAuditHooks(tstate);
}
_PyGC_Fini(tstate); _PyGC_Fini(tstate);
if (is_main_interp) { if (is_main_interp) {
@ -1405,9 +1412,6 @@ Py_FinalizeEx(void)
*/ */
_PyGC_CollectIfEnabled(); _PyGC_CollectIfEnabled();
/* Clear all loghooks */
_PySys_ClearAuditHooks(tstate);
/* Destroy all modules */ /* Destroy all modules */
_PyImport_Cleanup(tstate); _PyImport_Cleanup(tstate);