Skip to content

Commit 38a30c5

Browse files
espressoleelazerg
andcommitted
gh-159864: Fix syslog.openlog() crash with concurrent sys.argv changes
syslog_get_argv() took sys.argv[0] with PyList_GetItem() and increfed it only afterwards, so on the free-threaded build a concurrent replacement of sys.argv[0] could free it in between. Use PyList_GetItemRef() instead. Co-authored-by: Lazizbek Ergashev <20501725+lazerg@users.noreply.github.com>
1 parent 4b33a9d commit 38a30c5

3 files changed

Lines changed: 26 additions & 2 deletions

File tree

‎Lib/test/test_free_threading/test_syslog.py‎

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
1+
import sys
12
import unittest
23
import threading
34

5+
from test import support
46
from test.support import import_helper, threading_helper
57
from test.support.threading_helper import run_concurrently
68

@@ -39,6 +41,27 @@ def worker():
3941
nthreads=NTHREADS,
4042
)
4143

44+
def test_racing_openlog_argv(self):
45+
# gh-159864: openlog() without an ident reads sys.argv[0] while
46+
# another thread replaces it.
47+
argv = ["prog"]
48+
49+
def opener():
50+
for _ in range(1000):
51+
syslog.openlog()
52+
53+
def writer():
54+
for i in range(1000):
55+
argv[0] = f"prog-{i}"
56+
57+
with support.swap_attr(sys, "argv", argv):
58+
try:
59+
run_concurrently(
60+
worker_func=[opener] * (NTHREADS - 1) + [writer],
61+
)
62+
finally:
63+
syslog.closelog()
64+
4265

4366
if __name__ == "__main__":
4467
unittest.main()
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Fix a crash in :func:`syslog.openlog` under the free-threaded build when
2+
:data:`sys.argv` is modified concurrently.

‎Modules/syslogmodule.c‎

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -106,8 +106,7 @@ syslog_get_argv(void)
106106
return NULL;
107107
}
108108

109-
scriptobj = PyList_GetItem(argv, 0);
110-
Py_XINCREF(scriptobj);
109+
scriptobj = PyList_GetItemRef(argv, 0);
111110
Py_DECREF(argv);
112111
if (scriptobj == NULL) {
113112
PyErr_Clear();

0 commit comments

Comments
 (0)