Skip to content

Commit b9e288c

Browse files
zoobazkonge
andauthored
bpo-41162: Clear audit hooks later during finalization (pythonGH-21222)
Co-authored-by: Konge <[email protected]>
1 parent c1d9165 commit b9e288c

File tree

5 files changed

+16
-49
lines changed

5 files changed

+16
-49
lines changed

Lib/test/audit-tests.py

Lines changed: 0 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -44,28 +44,6 @@ def __call__(self, event, args):
4444
raise self.exc_type("saw event " + event)
4545

4646

47-
class TestFinalizeHook:
48-
"""Used in the test_finalize_hooks function to ensure that hooks
49-
are correctly cleaned up, that they are notified about the cleanup,
50-
and are unable to prevent it.
51-
"""
52-
53-
def __init__(self):
54-
print("Created", id(self), file=sys.stdout, flush=True)
55-
56-
def __call__(self, event, args):
57-
# Avoid recursion when we call id() below
58-
if event == "builtins.id":
59-
return
60-
61-
print(event, id(self), file=sys.stdout, flush=True)
62-
63-
if event == "cpython._PySys_ClearAuditHooks":
64-
raise RuntimeError("Should be ignored")
65-
elif event == "cpython.PyInterpreterState_Clear":
66-
raise RuntimeError("Should be ignored")
67-
68-
6947
# Simple helpers, since we are not in unittest here
7048
def assertEqual(x, y):
7149
if x != y:
@@ -128,10 +106,6 @@ def test_block_add_hook_baseexception():
128106
pass
129107

130108

131-
def test_finalize_hooks():
132-
sys.addaudithook(TestFinalizeHook())
133-
134-
135109
def test_pickle():
136110
import pickle
137111

Lib/test/test_audit.py

Lines changed: 0 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -51,22 +51,6 @@ def test_block_add_hook(self):
5151
def test_block_add_hook_baseexception(self):
5252
self.do_test("test_block_add_hook_baseexception")
5353

54-
def test_finalize_hooks(self):
55-
returncode, events, stderr = self.run_python("test_finalize_hooks")
56-
if stderr:
57-
print(stderr, file=sys.stderr)
58-
if returncode:
59-
self.fail(stderr)
60-
61-
firstId = events[0][2]
62-
self.assertSequenceEqual(
63-
[
64-
("Created", " ", firstId),
65-
("cpython._PySys_ClearAuditHooks", " ", firstId),
66-
],
67-
events,
68-
)
69-
7054
def test_pickle(self):
7155
support.import_module("pickle")
7256

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Audit hooks are now cleared later during finalization to avoid missing events.

Programs/_testembed.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1106,8 +1106,11 @@ static int test_open_code_hook(void)
11061106
return result;
11071107
}
11081108

1109+
static int _audit_hook_clear_count = 0;
1110+
11091111
static int _audit_hook(const char *event, PyObject *args, void *userdata)
11101112
{
1113+
assert(args && PyTuple_CheckExact(args));
11111114
if (strcmp(event, "_testembed.raise") == 0) {
11121115
PyErr_SetString(PyExc_RuntimeError, "Intentional error");
11131116
return -1;
@@ -1116,6 +1119,8 @@ static int _audit_hook(const char *event, PyObject *args, void *userdata)
11161119
return -1;
11171120
}
11181121
return 0;
1122+
} else if (strcmp(event, "cpython._PySys_ClearAuditHooks") == 0) {
1123+
_audit_hook_clear_count += 1;
11191124
}
11201125
return 0;
11211126
}
@@ -1161,6 +1166,9 @@ static int test_audit(void)
11611166
{
11621167
int result = _test_audit(42);
11631168
Py_Finalize();
1169+
if (_audit_hook_clear_count != 1) {
1170+
return 0x1000 | _audit_hook_clear_count;
1171+
}
11641172
return result;
11651173
}
11661174

Python/pylifecycle.c

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1229,13 +1229,6 @@ Py_FinalizeEx(void)
12291229
/* nothing */;
12301230
#endif
12311231

1232-
/* Clear all loghooks */
1233-
/* We want minimal exposure of this function, so define the extern
1234-
* here. The linker should discover the correct function without
1235-
* exporting a symbol. */
1236-
extern void _PySys_ClearAuditHooks(void);
1237-
_PySys_ClearAuditHooks();
1238-
12391232
/* Destroy all modules */
12401233
PyImport_Cleanup();
12411234

@@ -1306,6 +1299,13 @@ Py_FinalizeEx(void)
13061299
/* Clear interpreter state and all thread states. */
13071300
PyInterpreterState_Clear(interp);
13081301

1302+
/* Clear all loghooks */
1303+
/* We want minimal exposure of this function, so define the extern
1304+
* here. The linker should discover the correct function without
1305+
* exporting a symbol. */
1306+
extern void _PySys_ClearAuditHooks(void);
1307+
_PySys_ClearAuditHooks();
1308+
13091309
/* Now we decref the exception classes. After this point nothing
13101310
can raise an exception. That's okay, because each Fini() method
13111311
below has been checked to make sure no exceptions are ever

0 commit comments

Comments
 (0)