Skip to content

Commit 0843b8d

Browse files
espressoleelazerg
authored andcommitted
[3.14] gh-159864: Fix syslog.openlog() crash with concurrent sys.argv changes (GH-159884)
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. (cherry picked from commit e5e0748) Co-authored-by: Junhyung Lee <70549809+espressolee@users.noreply.github.com> Co-authored-by: Lazizbek Ergashev <20501725+lazerg@users.noreply.github.com>
1 parent d3e976f commit 0843b8d

3 files changed

Lines changed: 26 additions & 2 deletions

File tree

‎Lib/test/test_syslog.py‎

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,29 @@ def test_openlog_noargs(self):
5252
syslog.openlog()
5353
syslog.syslog('test message from python test_syslog')
5454

55+
@threading_helper.requires_working_threading()
56+
def test_racing_openlog_argv(self):
57+
# gh-159864: openlog() without an ident reads sys.argv[0] while
58+
# another thread replaces it.
59+
argv = ["prog"]
60+
nthreads = 32
61+
62+
def opener():
63+
for _ in range(1000):
64+
syslog.openlog()
65+
66+
def writer():
67+
for i in range(1000):
68+
argv[0] = f"prog-{i}"
69+
70+
with support.swap_attr(sys, "argv", argv):
71+
try:
72+
threading_helper.run_concurrently(
73+
worker_func=[opener] * (nthreads - 1) + [writer],
74+
)
75+
finally:
76+
syslog.closelog()
77+
5578
@threading_helper.requires_working_threading()
5679
def test_syslog_threaded(self):
5780
start = threading.Event()
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
@@ -107,8 +107,7 @@ syslog_get_argv(void)
107107
return NULL;
108108
}
109109

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

0 commit comments

Comments
 (0)