@@ -171,7 +171,7 @@ _PySys_ClearAttrString(PyInterpreterState *interp,
171
171
172
172
173
173
static int
174
- should_audit (PyInterpreterState * interp )
174
+ should_audit_interp (PyInterpreterState * interp )
175
175
{
176
176
/* interp must not be NULL, but test it just in case for extra safety */
177
177
assert (interp != NULL );
@@ -185,10 +185,8 @@ should_audit(PyInterpreterState *interp)
185
185
186
186
187
187
static int
188
- sys_audit_tuple (PyThreadState * ts , const char * event , PyObject * eventArgs )
188
+ should_audit_tstate (PyThreadState * ts )
189
189
{
190
- assert (PyTuple_Check (eventArgs ));
191
-
192
190
if (!ts ) {
193
191
/* Audit hooks cannot be called with a NULL thread state */
194
192
return 0 ;
@@ -198,18 +196,33 @@ sys_audit_tuple(PyThreadState *ts, const char *event, PyObject *eventArgs)
198
196
the current Python thread state. */
199
197
assert (ts == _PyThreadState_GET ());
200
198
199
+ /* Early exit when no hooks are registered */
200
+ PyInterpreterState * is = ts -> interp ;
201
+ if (!should_audit_interp (is )) {
202
+ return 0 ;
203
+ }
204
+ return 1 ;
205
+ }
206
+
207
+
208
+ static int
209
+ sys_audit_tuple (PyThreadState * ts , const char * event , PyObject * eventArgs )
210
+ {
211
+ // The caller check should_audit_tstate() or should_audit_interp() as soon
212
+ // as possible to avoid any performance overhead if no hook was added.
213
+ assert (should_audit_tstate (ts ));
214
+
215
+ // The caller must check via should_audit_tstate() that tstate is not NULL
216
+ assert (ts != NULL );
217
+
218
+ assert (PyTuple_Check (eventArgs ));
219
+
201
220
if (event == NULL ) {
202
221
_PyErr_SetString (ts , PyExc_ValueError ,
203
222
"event argument must not be NULL" );
204
223
return -1 ;
205
224
}
206
225
207
- /* Early exit when no hooks are registered */
208
- PyInterpreterState * is = ts -> interp ;
209
- if (!should_audit (is )) {
210
- return 0 ;
211
- }
212
-
213
226
PyObject * eventName = NULL ;
214
227
PyObject * hooks = NULL ;
215
228
PyObject * hook = NULL ;
@@ -224,6 +237,7 @@ sys_audit_tuple(PyThreadState *ts, const char *event, PyObject *eventArgs)
224
237
*
225
238
* We don't worry about any races on hooks getting added,
226
239
* since that would not leave is in an inconsistent state. */
240
+ PyInterpreterState * is = ts -> interp ;
227
241
_Py_AuditHookEntry * e = is -> runtime -> audit_hooks .head ;
228
242
for (; e ; e = e -> next ) {
229
243
if (e -> hookCFunction (event , eventArgs , e -> userData ) < 0 ) {
332
346
_PySys_Audit (PyThreadState * tstate , const char * event ,
333
347
const char * format , ...)
334
348
{
349
+ // tstate can be NULL
350
+ if (!should_audit_tstate (tstate )) {
351
+ return 0 ;
352
+ }
353
+
335
354
va_list vargs ;
336
355
va_start (vargs , format );
337
356
int res = sys_audit_vargs (tstate , event , format , vargs );
343
362
PySys_Audit (const char * event , const char * format , ...)
344
363
{
345
364
PyThreadState * tstate = _PyThreadState_GET ();
365
+ // tstate can be NULL if the function is called before Py_Initialize()
366
+ if (!should_audit_tstate (tstate )) {
367
+ return 0 ;
368
+ }
369
+
346
370
va_list vargs ;
347
371
va_start (vargs , format );
348
372
int res = sys_audit_vargs (tstate , event , format , vargs );
354
378
PySys_AuditTuple (const char * event , PyObject * args )
355
379
{
356
380
PyThreadState * tstate = _PyThreadState_GET ();
357
- int delete_args = 0 ;
381
+ // tstate can be NULL if the function is called before Py_Initialize()
382
+ if (!should_audit_tstate (tstate )) {
383
+ return 0 ;
384
+ }
358
385
386
+ int delete_args = 0 ;
359
387
if (args == NULL ) {
360
388
delete_args = 1 ;
361
389
args = PyTuple_New (0 );
@@ -548,7 +576,7 @@ sys_audit(PyObject *self, PyObject *const *args, Py_ssize_t argc)
548
576
return NULL ;
549
577
}
550
578
551
- if (!should_audit (tstate -> interp )) {
579
+ if (!should_audit_interp (tstate -> interp )) {
552
580
Py_RETURN_NONE ;
553
581
}
554
582
0 commit comments