@@ -168,7 +168,7 @@ should_audit(PyInterpreterState *interp)
168
168
if (!interp ) {
169
169
return 0 ;
170
170
}
171
- return (interp -> runtime -> audit_hook_head
171
+ return (interp -> runtime -> audit_hooks . head
172
172
|| interp -> audit_hooks
173
173
|| PyDTrace_AUDIT_ENABLED ());
174
174
}
@@ -224,8 +224,11 @@ sys_audit_tstate(PyThreadState *ts, const char *event,
224
224
goto exit ;
225
225
}
226
226
227
- /* Call global hooks */
228
- _Py_AuditHookEntry * e = is -> runtime -> audit_hook_head ;
227
+ /* Call global hooks
228
+ *
229
+ * We don't worry about any races on hooks getting added,
230
+ * since that would not leave is in an inconsistent state. */
231
+ _Py_AuditHookEntry * e = is -> runtime -> audit_hooks .head ;
229
232
for (; e ; e = e -> next ) {
230
233
if (e -> hookCFunction (event , eventArgs , e -> userData ) < 0 ) {
231
234
goto exit ;
@@ -353,15 +356,35 @@ _PySys_ClearAuditHooks(PyThreadState *ts)
353
356
_PySys_Audit (ts , "cpython._PySys_ClearAuditHooks" , NULL );
354
357
_PyErr_Clear (ts );
355
358
356
- _Py_AuditHookEntry * e = runtime -> audit_hook_head , * n ;
357
- runtime -> audit_hook_head = NULL ;
359
+ /* We don't worry about the very unlikely race right here,
360
+ * since it's entirely benign. Nothing else removes entries
361
+ * from the list and adding an entry right now would not cause
362
+ * any trouble. */
363
+ _Py_AuditHookEntry * e = runtime -> audit_hooks .head , * n ;
364
+ runtime -> audit_hooks .head = NULL ;
358
365
while (e ) {
359
366
n = e -> next ;
360
367
PyMem_RawFree (e );
361
368
e = n ;
362
369
}
363
370
}
364
371
372
+ static void
373
+ add_audit_hook_entry_unlocked (_PyRuntimeState * runtime ,
374
+ _Py_AuditHookEntry * entry )
375
+ {
376
+ if (runtime -> audit_hooks .head == NULL ) {
377
+ runtime -> audit_hooks .head = entry ;
378
+ }
379
+ else {
380
+ _Py_AuditHookEntry * last = runtime -> audit_hooks .head ;
381
+ while (last -> next ) {
382
+ last = last -> next ;
383
+ }
384
+ last -> next = entry ;
385
+ }
386
+ }
387
+
365
388
int
366
389
PySys_AddAuditHook (Py_AuditHookFunction hook , void * userData )
367
390
{
@@ -389,29 +412,28 @@ PySys_AddAuditHook(Py_AuditHookFunction hook, void *userData)
389
412
}
390
413
}
391
414
392
- _Py_AuditHookEntry * e = runtime -> audit_hook_head ;
393
- if (!e ) {
394
- e = (_Py_AuditHookEntry * )PyMem_RawMalloc (sizeof (_Py_AuditHookEntry ));
395
- runtime -> audit_hook_head = e ;
396
- } else {
397
- while (e -> next ) {
398
- e = e -> next ;
399
- }
400
- e = e -> next = (_Py_AuditHookEntry * )PyMem_RawMalloc (
415
+ _Py_AuditHookEntry * e = (_Py_AuditHookEntry * )PyMem_RawMalloc (
401
416
sizeof (_Py_AuditHookEntry ));
402
- }
403
-
404
417
if (!e ) {
405
418
if (tstate != NULL ) {
406
419
_PyErr_NoMemory (tstate );
407
420
}
408
421
return -1 ;
409
422
}
410
-
411
423
e -> next = NULL ;
412
424
e -> hookCFunction = (Py_AuditHookFunction )hook ;
413
425
e -> userData = userData ;
414
426
427
+ if (runtime -> audit_hooks .mutex == NULL ) {
428
+ /* The runtime must not be initailized yet. */
429
+ add_audit_hook_entry_unlocked (runtime , e );
430
+ }
431
+ else {
432
+ PyThread_acquire_lock (runtime -> audit_hooks .mutex , WAIT_LOCK );
433
+ add_audit_hook_entry_unlocked (runtime , e );
434
+ PyThread_release_lock (runtime -> audit_hooks .mutex );
435
+ }
436
+
415
437
return 0 ;
416
438
}
417
439
0 commit comments