https://github.com/python/cpython/commit/65893c6f9c69562526d24fe8265119feeea54cbf
commit: 65893c6f9c69562526d24fe8265119feeea54cbf
branch: main
author: Alper <[email protected]>
committer: mpage <[email protected]>
date: 2025-07-21T09:24:42-07:00
summary:
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.
files:
A Lib/test/test_free_threading/test_syslog.py
A
Misc/NEWS.d/next/Core_and_Builtins/2025-07-18-08-43-35.gh-issue-116738.i0HWtP.rst
M Modules/syslogmodule.c
diff --git a/Lib/test/test_free_threading/test_syslog.py
b/Lib/test/test_free_threading/test_syslog.py
new file mode 100644
index 00000000000000..b374a98b96e6de
--- /dev/null
+++ b/Lib/test/test_free_threading/test_syslog.py
@@ -0,0 +1,44 @@
+import unittest
+import threading
+
+from test.support import import_helper, threading_helper
+from test.support.threading_helper import run_concurrently
+
+syslog = import_helper.import_module("syslog")
+
+NTHREADS = 32
+
+# Similar to Lib/test/test_syslog.py, this test's purpose is to verify that
+# the code neither crashes nor leaks.
+
+
+@threading_helper.requires_working_threading()
+class TestSyslog(unittest.TestCase):
+ def test_racing_syslog(self):
+ def worker():
+ """
+ The syslog module provides the following functions:
+ openlog(), syslog(), closelog(), and setlogmask().
+ """
+ thread_id = threading.get_ident()
+ syslog.openlog(f"thread-id: {thread_id}")
+ try:
+ for _ in range(5):
+ syslog.syslog("logline")
+ syslog.setlogmask(syslog.LOG_MASK(syslog.LOG_INFO))
+ syslog.syslog(syslog.LOG_INFO, "logline LOG_INFO")
+ syslog.setlogmask(syslog.LOG_MASK(syslog.LOG_ERR))
+ syslog.syslog(syslog.LOG_ERR, "logline LOG_ERR")
+ syslog.setlogmask(syslog.LOG_UPTO(syslog.LOG_DEBUG))
+ finally:
+ syslog.closelog()
+
+ # Run the worker concurrently to exercise all these syslog functions
+ run_concurrently(
+ worker_func=worker,
+ nthreads=NTHREADS,
+ )
+
+
+if __name__ == "__main__":
+ unittest.main()
diff --git
a/Misc/NEWS.d/next/Core_and_Builtins/2025-07-18-08-43-35.gh-issue-116738.i0HWtP.rst
b/Misc/NEWS.d/next/Core_and_Builtins/2025-07-18-08-43-35.gh-issue-116738.i0HWtP.rst
new file mode 100644
index 00000000000000..77dca4074b742f
--- /dev/null
+++
b/Misc/NEWS.d/next/Core_and_Builtins/2025-07-18-08-43-35.gh-issue-116738.i0HWtP.rst
@@ -0,0 +1,2 @@
+Make functions in :mod:`syslog` thread-safe on the :term:`free threaded
+<free threading>` build.
diff --git a/Modules/syslogmodule.c b/Modules/syslogmodule.c
index ab20fff1509dfe..5d7fd20c4e0999 100644
--- a/Modules/syslogmodule.c
+++ b/Modules/syslogmodule.c
@@ -298,7 +298,13 @@ syslog_setlogmask_impl(PyObject *module, long maskpri)
return -1;
}
- return setlogmask(maskpri);
+ static PyMutex setlogmask_mutex = {0};
+ PyMutex_Lock(&setlogmask_mutex);
+ // Linux man page (3): setlogmask() is MT-Unsafe race:LogMask.
+ long previous_mask = setlogmask(maskpri);
+ PyMutex_Unlock(&setlogmask_mutex);
+
+ return previous_mask;
}
/*[clinic input]
_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3//lists/python-checkins.python.org
Member address: [email protected]