Skip to content

Crash on 3.14.6 free threading #513

Description

@ddorian

I hit this when trying free-threading with playwright in microsoft/playwright-python#3123.

This happens also with gil=on.

Is this valid? Can I try to make a pull request?

uv run --no-project --python 3.14.6t repro_min.py
python 3.14.6  gil_enabled=False
Fatal Python error: PyMutex_Unlock: unlocking mutex that is not locked
Python runtime state: initialized

Stack (most recent call first):
  File "/home/guru/Desktop/repro_min.py", line 39 in g2_body

Extension modules: greenlet._greenlet (total: 1)

script:

# /// script
# requires-python = "==3.14.6"
# dependencies = ["greenlet==3.5.2"]
# ///
# Run on free-threaded CPython:  uv run --no-project --python 3.14t repro_min.py
#
# greenlet never saves/restores CPython's per-thread critical-section pointer
# (tstate->critical_section) across a stack switch. Two greenlets that each
# switch *while holding a list.sort() critical section* interleave non-nested,
# corrupting the chain; the next blocking open() then aborts in
# _PyCriticalSection_SuspendAll with "PyMutex_Unlock: unlocking mutex that is
# not locked".
import sys

import greenlet

print(f"python {sys.version.split()[0]}  gil_enabled={sys._is_gil_enabled()}", flush=True)

main = greenlet.getcurrent()


def k1(x):
    g2.switch()  # into G2 while holding G1's sort critical section
    return x


def k2(x):
    g1.switch()  # back into G1 while holding G2's sort critical section
    return x


def g1_body():
    sorted([0], key=k1)
    g2.switch()


def g2_body():
    sorted([0], key=k2)
    open("/etc/hostname").read()  # SuspendAll over a stale, unlocked mutex -> fatal


g1 = greenlet.greenlet(g1_body)
g2 = greenlet.greenlet(g2_body)
g1.switch()
print("DONE no crash")

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions