@@ -171,7 +171,7 @@ _PySys_ClearAttrString(PyInterpreterState *interp,
171171
172172
173173static int
174- should_audit (PyInterpreterState * interp )
174+ should_audit_interp (PyInterpreterState * interp )
175175{
176176 /* interp must not be NULL, but test it just in case for extra safety */
177177 assert (interp != NULL );
@@ -185,10 +185,8 @@ should_audit(PyInterpreterState *interp)
185185
186186
187187static int
188- sys_audit_tuple (PyThreadState * ts , const char * event , PyObject * eventArgs )
188+ should_audit_tstate (PyThreadState * ts )
189189{
190- assert (PyTuple_Check (eventArgs ));
191-
192190 if (!ts ) {
193191 /* Audit hooks cannot be called with a NULL thread state */
194192 return 0 ;
@@ -198,18 +196,33 @@ sys_audit_tuple(PyThreadState *ts, const char *event, PyObject *eventArgs)
198196 the current Python thread state. */
199197 assert (ts == _PyThreadState_GET ());
200198
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+
201220 if (event == NULL ) {
202221 _PyErr_SetString (ts , PyExc_ValueError ,
203222 "event argument must not be NULL" );
204223 return -1 ;
205224 }
206225
207- /* Early exit when no hooks are registered */
208- PyInterpreterState * is = ts -> interp ;
209- if (!should_audit (is )) {
210- return 0 ;
211- }
212-
213226 PyObject * eventName = NULL ;
214227 PyObject * hooks = NULL ;
215228 PyObject * hook = NULL ;
@@ -224,6 +237,7 @@ sys_audit_tuple(PyThreadState *ts, const char *event, PyObject *eventArgs)
224237 *
225238 * We don't worry about any races on hooks getting added,
226239 * since that would not leave is in an inconsistent state. */
240+ PyInterpreterState * is = ts -> interp ;
227241 _Py_AuditHookEntry * e = is -> runtime -> audit_hooks .head ;
228242 for (; e ; e = e -> next ) {
229243 if (e -> hookCFunction (event , eventArgs , e -> userData ) < 0 ) {
332346_PySys_Audit (PyThreadState * tstate , const char * event ,
333347 const char * format , ...)
334348{
349+ // tstate can be NULL
350+ if (!should_audit_tstate (tstate )) {
351+ return 0 ;
352+ }
353+
335354 va_list vargs ;
336355 va_start (vargs , format );
337356 int res = sys_audit_vargs (tstate , event , format , vargs );
343362PySys_Audit (const char * event , const char * format , ...)
344363{
345364 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+
346370 va_list vargs ;
347371 va_start (vargs , format );
348372 int res = sys_audit_vargs (tstate , event , format , vargs );
354378PySys_AuditTuple (const char * event , PyObject * args )
355379{
356380 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+ }
358385
386+ int delete_args = 0 ;
359387 if (args == NULL ) {
360388 delete_args = 1 ;
361389 args = PyTuple_New (0 );
@@ -548,7 +576,7 @@ sys_audit(PyObject *self, PyObject *const *args, Py_ssize_t argc)
548576 return NULL ;
549577 }
550578
551- if (!should_audit (tstate -> interp )) {
579+ if (!should_audit_interp (tstate -> interp )) {
552580 Py_RETURN_NONE ;
553581 }
554582
0 commit comments