Skip to content

Commit 65893c6

Browse files
authored
gh-116738: Make syslog module thread-safe (#136760)
Make the setlogmask() function in the syslog module thread-safe. These changes are relevant for scenarios where the GIL is disabled or when using subinterpreters.
1 parent 5f9e38f commit 65893c6

File tree

3 files changed

+53
-1
lines changed

3 files changed

+53
-1
lines changed
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
import unittest
2+
import threading
3+
4+
from test.support import import_helper, threading_helper
5+
from test.support.threading_helper import run_concurrently
6+
7+
syslog = import_helper.import_module("syslog")
8+
9+
NTHREADS = 32
10+
11+
# Similar to Lib/test/test_syslog.py, this test's purpose is to verify that
12+
# the code neither crashes nor leaks.
13+
14+
15+
@threading_helper.requires_working_threading()
16+
class TestSyslog(unittest.TestCase):
17+
def test_racing_syslog(self):
18+
def worker():
19+
"""
20+
The syslog module provides the following functions:
21+
openlog(), syslog(), closelog(), and setlogmask().
22+
"""
23+
thread_id = threading.get_ident()
24+
syslog.openlog(f"thread-id: {thread_id}")
25+
try:
26+
for _ in range(5):
27+
syslog.syslog("logline")
28+
syslog.setlogmask(syslog.LOG_MASK(syslog.LOG_INFO))
29+
syslog.syslog(syslog.LOG_INFO, "logline LOG_INFO")
30+
syslog.setlogmask(syslog.LOG_MASK(syslog.LOG_ERR))
31+
syslog.syslog(syslog.LOG_ERR, "logline LOG_ERR")
32+
syslog.setlogmask(syslog.LOG_UPTO(syslog.LOG_DEBUG))
33+
finally:
34+
syslog.closelog()
35+
36+
# Run the worker concurrently to exercise all these syslog functions
37+
run_concurrently(
38+
worker_func=worker,
39+
nthreads=NTHREADS,
40+
)
41+
42+
43+
if __name__ == "__main__":
44+
unittest.main()
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Make functions in :mod:`syslog` thread-safe on the :term:`free threaded
2+
<free threading>` build.

Modules/syslogmodule.c

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -298,7 +298,13 @@ syslog_setlogmask_impl(PyObject *module, long maskpri)
298298
return -1;
299299
}
300300

301-
return setlogmask(maskpri);
301+
static PyMutex setlogmask_mutex = {0};
302+
PyMutex_Lock(&setlogmask_mutex);
303+
// Linux man page (3): setlogmask() is MT-Unsafe race:LogMask.
304+
long previous_mask = setlogmask(maskpri);
305+
PyMutex_Unlock(&setlogmask_mutex);
306+
307+
return previous_mask;
302308
}
303309

304310
/*[clinic input]

0 commit comments

Comments
 (0)