Skip to content

syslog cross-interpreter refcount race on static S_ident_o #158929

Description

@error-3317

Crash report

PoC

import threading, syslog
import concurrent.interpreters as ci

ROUNDS = 400000
syslog.openlog("seed", syslog.LOG_PERROR)

SUB = f"""
import syslog
for i in range({ROUNDS}):
    try:
        syslog.syslog('m')
    except Exception:
        pass
"""

interp = ci.create()
t = threading.Thread(target=lambda: interp.exec(SUB))
t.start()
for i in range(ROUNDS):
    syslog.openlog("ident-%d" % i)
t.join()
print("no crash")

Output

$ python3 -X faulthandler main.py
free(): invalid pointer
Fatal Python error: Aborted

Current thread 0x00007f82271046c0 [Thread-1 (<lamb] (most recent call first):
  File "<script>", line 5 in <module>

Current thread's C stack trace (most recent call first):
  Binary file "/home/user/.local/share/uv/python/cpython-3.15-linux-x86_64-gnu/bin/python3.15", at _Py_DumpStack+0x30 [0x4f0b80]
  Binary file "/home/user/.local/share/uv/python/cpython-3.15-linux-x86_64-gnu/bin/python3.15" [0x59968b]
  Binary file "/home/user/.local/share/uv/python/cpython-3.15-linux-x86_64-gnu/bin/python3.15" [0x5995de]
  Binary file "/lib/x86_64-linux-gnu/libc.so.6", at +0x3c050 [0x7f8227a65050]
  Binary file "/lib/x86_64-linux-gnu/libc.so.6", at +0x8aeec [0x7f8227ab3eec]
  Binary file "/lib/x86_64-linux-gnu/libc.so.6", at gsignal+0x12 [0x7f8227a64fb2]
  Binary file "/lib/x86_64-linux-gnu/libc.so.6", at abort+0xd3 [0x7f8227a4f472]
  Binary file "/lib/x86_64-linux-gnu/libc.so.6", at +0x7f42f [0x7f8227aa842f]
  Binary file "/lib/x86_64-linux-gnu/libc.so.6", at +0x9486a [0x7f8227abd86a]
  Binary file "/lib/x86_64-linux-gnu/libc.so.6", at +0x965f4 [0x7f8227abf5f4]
  Binary file "/lib/x86_64-linux-gnu/libc.so.6", at __libc_free+0x6f [0x7f8227ac1f5f]
  Binary file "/home/user/.local/share/uv/python/cpython-3.15-linux-x86_64-gnu/bin/python3.15" [0x1a01dce]
  Binary file "/home/user/.local/share/uv/python/cpython-3.15-linux-x86_64-gnu/bin/python3.15" [0x1a01c8a]
  Binary file "/home/user/.local/share/uv/python/cpython-3.15-linux-x86_64-gnu/bin/python3.15", at _Py_Dealloc+0x51 [0x1a01b59]
  Binary file "/home/user/.local/share/uv/python/cpython-3.15-linux-x86_64-gnu/bin/python3.15" [0x54ef72]
  Binary file "/home/user/.local/share/uv/python/cpython-3.15-linux-x86_64-gnu/bin/python3.15" [0x54ed51]
  Binary file "/home/user/.local/share/uv/python/cpython-3.15-linux-x86_64-gnu/bin/python3.15" [0x1a67fc4]
  Binary file "/home/user/.local/share/uv/python/cpython-3.15-linux-x86_64-gnu/bin/python3.15" [0x1a0b93e]
  Binary file "/home/user/.local/share/uv/python/cpython-3.15-linux-x86_64-gnu/bin/python3.15" [0x1a72484]
  Binary file "/home/user/.local/share/uv/python/cpython-3.15-linux-x86_64-gnu/bin/python3.15", at PyEval_EvalCode+0xa6 [0x1a72182]
  Binary file "/home/user/.local/share/uv/python/cpython-3.15-linux-x86_64-gnu/bin/python3.15" [0x51b289]
  Binary file "/home/user/.local/share/uv/python/cpython-3.15-linux-x86_64-gnu/bin/python3.15" [0x1e9a943]
  Binary file "/home/user/.local/share/uv/python/cpython-3.15-linux-x86_64-gnu/bin/python3.15" [0x51b592]
  Binary file "/home/user/.local/share/uv/python/cpython-3.15-linux-x86_64-gnu/bin/python3.15" [0x51a959]
  Binary file "/home/user/.local/share/uv/python/cpython-3.15-linux-x86_64-gnu/bin/python3.15", at PyObject_Vectorcall+0x4c [0x1a1c3a4]
  Binary file "/home/user/.local/share/uv/python/cpython-3.15-linux-x86_64-gnu/bin/python3.15", at _Py_VectorCallInstrumentation_StackRefSteal+0xca [0x1b23ade]
  Binary file "/home/user/.local/share/uv/python/cpython-3.15-linux-x86_64-gnu/bin/python3.15" [0x1a406c2]
  Binary file "/home/user/.local/share/uv/python/cpython-3.15-linux-x86_64-gnu/bin/python3.15", at _PyFunction_Vectorcall+0x337 [0x1a11337]
  Binary file "/home/user/.local/share/uv/python/cpython-3.15-linux-x86_64-gnu/bin/python3.15" [0x1a10dd9]
  Binary file "/home/user/.local/share/uv/python/cpython-3.15-linux-x86_64-gnu/bin/python3.15" [0x1bf19be]
  Binary file "/home/user/.local/share/uv/python/cpython-3.15-linux-x86_64-gnu/bin/python3.15" [0x1a2d33f]
  Binary file "/home/user/.local/share/uv/python/cpython-3.15-linux-x86_64-gnu/bin/python3.15", at _PyFunction_Vectorcall+0x337 [0x1a11337]
  <truncated rest of calls>

Root Cause

Modules/syslogmodule.c:71 (file-static PyObject* shared by all interpreters), :193 (Py_XSETREF in openlog, main-only since 3.12), :241/:250 (Py_XNewRef/Py_XDECREF plain RMWs from syslog(), allowed from subinterpreters)
The module declares Py_MOD_PER_INTERPRETER_GIL_SUPPORTED, exactly the configuration that breaks it, yet shares one non-atomic refcounted ident object across interpreters. The clinic @critical_section wraps the per-interpreter module object, which excludes nothing across interpreters.

Versions Affected

Python 3.14+
(technical range 3.12+: per-interpreter GIL, PEP 684)

CPython versions tested on:

3.15

Operating systems tested on:

Linux

Output from running 'python -VV' on the command line:

Python 3.15.0rc3 (main, Oct 3 2026, 01:07:55) [Clang 22.1.3 ]

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions