@@ -61,10 +61,18 @@ module syslog
61
61
62
62
#include "clinic/syslogmodule.c.h"
63
63
64
- /* only one instance, only one syslog, so globals should be ok */
65
- static PyObject * S_ident_o = NULL ; /* identifier, held by openlog() */
66
- static char S_log_open = 0 ;
64
+ typedef struct {
65
+ PyObject * S_ident_o ; /* identifier, held by openlog() */
66
+ char S_log_open ;
67
+ } _syslog_state ;
67
68
69
+ static inline _syslog_state *
70
+ get_syslog_state (PyObject * module )
71
+ {
72
+ void * state = PyModule_GetState (module );
73
+ assert (state != NULL );
74
+ return (_syslog_state * )state ;
75
+ }
68
76
69
77
static PyObject *
70
78
syslog_get_argv (void )
@@ -162,8 +170,9 @@ syslog_openlog_impl(PyObject *module, PyObject *ident, long logopt,
162
170
}
163
171
164
172
openlog (ident_str , logopt , facility );
165
- S_log_open = 1 ;
166
- Py_XSETREF (S_ident_o , ident );
173
+ _syslog_state * state = get_syslog_state (module );
174
+ state -> S_log_open = 1 ;
175
+ Py_XSETREF (state -> S_ident_o , ident );
167
176
168
177
Py_RETURN_NONE ;
169
178
}
@@ -193,8 +202,9 @@ syslog_syslog_impl(PyObject *module, int group_left_1, int priority,
193
202
return NULL ;
194
203
}
195
204
205
+ _syslog_state * state = get_syslog_state (module );
196
206
/* if log is not opened, open it now */
197
- if (!S_log_open ) {
207
+ if (!state -> S_log_open ) {
198
208
PyObject * openlog_ret = syslog_openlog_impl (module , NULL , 0 , LOG_USER );
199
209
if (openlog_ret == NULL ) {
200
210
return NULL ;
@@ -205,7 +215,7 @@ syslog_syslog_impl(PyObject *module, int group_left_1, int priority,
205
215
/* Incref ident, because it can be decrefed if syslog.openlog() is
206
216
* called when the GIL is released.
207
217
*/
208
- PyObject * ident = S_ident_o ;
218
+ PyObject * ident = state -> S_ident_o ;
209
219
Py_XINCREF (ident );
210
220
#ifdef __APPLE__
211
221
// gh-98178: On macOS, libc syslog() is not thread-safe
@@ -233,10 +243,12 @@ syslog_closelog_impl(PyObject *module)
233
243
if (PySys_Audit ("syslog.closelog" , NULL ) < 0 ) {
234
244
return NULL ;
235
245
}
236
- if (S_log_open ) {
246
+
247
+ _syslog_state * state = get_syslog_state (module );
248
+ if (state -> S_log_open ) {
237
249
closelog ();
238
- Py_CLEAR (S_ident_o );
239
- S_log_open = 0 ;
250
+ Py_CLEAR (state -> S_ident_o );
251
+ state -> S_log_open = 0 ;
240
252
}
241
253
Py_RETURN_NONE ;
242
254
}
@@ -315,6 +327,11 @@ syslog_exec(PyObject *module)
315
327
return -1; \
316
328
} \
317
329
} while (0)
330
+
331
+ _syslog_state * state = get_syslog_state (module );
332
+ state -> S_ident_o = NULL ;
333
+ state -> S_log_open = 0 ;
334
+
318
335
/* Priorities */
319
336
ADD_INT_MACRO (module , LOG_EMERG );
320
337
ADD_INT_MACRO (module , LOG_ALERT );
@@ -380,6 +397,29 @@ syslog_exec(PyObject *module)
380
397
return 0 ;
381
398
}
382
399
400
+ static int
401
+ _syslog_traverse (PyObject * module , visitproc visit , void * arg )
402
+ {
403
+ _syslog_state * state = get_syslog_state (module );
404
+ Py_VISIT (state -> S_ident_o );
405
+ return 0 ;
406
+ }
407
+
408
+ static int
409
+ _syslog_clear (PyObject * module )
410
+ {
411
+ _syslog_state * state = get_syslog_state (module );
412
+ Py_CLEAR (state -> S_ident_o );
413
+ state -> S_log_open = 0 ;
414
+ return 0 ;
415
+ }
416
+
417
+ static void
418
+ _syslog_free (void * module )
419
+ {
420
+ _syslog_clear ((PyObject * )module );
421
+ }
422
+
383
423
static PyModuleDef_Slot syslog_slots [] = {
384
424
{Py_mod_exec , syslog_exec },
385
425
{0 , NULL }
@@ -390,9 +430,12 @@ static PyModuleDef_Slot syslog_slots[] = {
390
430
static struct PyModuleDef syslogmodule = {
391
431
PyModuleDef_HEAD_INIT ,
392
432
.m_name = "syslog" ,
393
- .m_size = 0 ,
433
+ .m_size = sizeof ( _syslog_state ) ,
394
434
.m_methods = syslog_methods ,
395
435
.m_slots = syslog_slots ,
436
+ .m_traverse = _syslog_traverse ,
437
+ .m_clear = _syslog_clear ,
438
+ .m_free = _syslog_free ,
396
439
};
397
440
398
441
PyMODINIT_FUNC
0 commit comments