@@ -61,10 +61,19 @@ module syslog
6161
6262#include "clinic/syslogmodule.c.h"
6363
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 ;
67-
64+ typedef struct {
65+ /* only one instance, only one syslog, */
66+ PyObject * S_ident_o ; /* identifier, held by openlog() */
67+ char S_log_open ;
68+ } _syslog_state ;
69+
70+ static inline _syslog_state *
71+ get_syslog_state (PyObject * module )
72+ {
73+ void * state = PyModule_GetState (module );
74+ assert (state != NULL );
75+ return (_syslog_state * )state ;
76+ }
6877
6978static PyObject *
7079syslog_get_argv (void )
@@ -162,8 +171,9 @@ syslog_openlog_impl(PyObject *module, PyObject *ident, long logopt,
162171 }
163172
164173 openlog (ident_str , logopt , facility );
165- S_log_open = 1 ;
166- Py_XSETREF (S_ident_o , ident );
174+ _syslog_state * state = get_syslog_state (module );
175+ state -> S_log_open = 1 ;
176+ Py_XSETREF (state -> S_ident_o , ident );
167177
168178 Py_RETURN_NONE ;
169179}
@@ -193,8 +203,9 @@ syslog_syslog_impl(PyObject *module, int group_left_1, int priority,
193203 return NULL ;
194204 }
195205
206+ _syslog_state * state = get_syslog_state (module );
196207 /* if log is not opened, open it now */
197- if (!S_log_open ) {
208+ if (!state -> S_log_open ) {
198209 PyObject * openlog_ret = syslog_openlog_impl (module , NULL , 0 , LOG_USER );
199210 if (openlog_ret == NULL ) {
200211 return NULL ;
@@ -205,7 +216,7 @@ syslog_syslog_impl(PyObject *module, int group_left_1, int priority,
205216 /* Incref ident, because it can be decrefed if syslog.openlog() is
206217 * called when the GIL is released.
207218 */
208- PyObject * ident = S_ident_o ;
219+ PyObject * ident = state -> S_ident_o ;
209220 Py_XINCREF (ident );
210221#ifdef __APPLE__
211222 // gh-98178: On macOS, libc syslog() is not thread-safe
@@ -233,10 +244,12 @@ syslog_closelog_impl(PyObject *module)
233244 if (PySys_Audit ("syslog.closelog" , NULL ) < 0 ) {
234245 return NULL ;
235246 }
236- if (S_log_open ) {
247+
248+ _syslog_state * state = get_syslog_state (module );
249+ if (state -> S_log_open ) {
237250 closelog ();
238- Py_CLEAR (S_ident_o );
239- S_log_open = 0 ;
251+ Py_CLEAR (state -> S_ident_o );
252+ state -> S_log_open = 0 ;
240253 }
241254 Py_RETURN_NONE ;
242255}
@@ -315,6 +328,11 @@ syslog_exec(PyObject *module)
315328 return -1; \
316329 } \
317330 } while (0)
331+
332+ _syslog_state * state = get_syslog_state (module );
333+ state -> S_ident_o = NULL ;
334+ state -> S_log_open = 0 ;
335+
318336 /* Priorities */
319337 ADD_INT_MACRO (module , LOG_EMERG );
320338 ADD_INT_MACRO (module , LOG_ALERT );
@@ -380,6 +398,29 @@ syslog_exec(PyObject *module)
380398 return 0 ;
381399}
382400
401+ static int
402+ _syslog_traverse (PyObject * module , visitproc visit , void * arg )
403+ {
404+ _syslog_state * state = get_syslog_state (module );
405+ Py_VISIT (state -> S_ident_o );
406+ return 0 ;
407+ }
408+
409+ static int
410+ _syslog_clear (PyObject * module )
411+ {
412+ _syslog_state * state = get_syslog_state (module );
413+ Py_CLEAR (state -> S_ident_o );
414+ state -> S_log_open = 0 ;
415+ return 0 ;
416+ }
417+
418+ static void
419+ _syslog_free (void * module )
420+ {
421+ _syslog_clear ((PyObject * )module );
422+ }
423+
383424static PyModuleDef_Slot syslog_slots [] = {
384425 {Py_mod_exec , syslog_exec },
385426 {0 , NULL }
@@ -390,9 +431,12 @@ static PyModuleDef_Slot syslog_slots[] = {
390431static struct PyModuleDef syslogmodule = {
391432 PyModuleDef_HEAD_INIT ,
392433 .m_name = "syslog" ,
393- .m_size = 0 ,
434+ .m_size = sizeof ( _syslog_state ) ,
394435 .m_methods = syslog_methods ,
395436 .m_slots = syslog_slots ,
437+ .m_traverse = _syslog_traverse ,
438+ .m_clear = _syslog_clear ,
439+ .m_free = _syslog_free ,
396440};
397441
398442PyMODINIT_FUNC
0 commit comments