GV

GeezerVison

The World Wide Web, restored to 800 pixels of glory.

Home|About|Gaming cabinet|Archives|How it works|Starter sites

On this site

  • Sign in
  • ActionsCI/CD and automation
  • CodespacesCloud development environments
  • All Features
  • Documentation
  • Training
  • Certifications
  • Build with Copilot
  • Customize Copilot
  • Integrations
  • Trending repos
  • GitHub Sponsors
  • Developer articles
  • Enterprises

This view

  • Original page
  • New address

GeezerVison is showing github.com — Missing critical section for `PyDict_Next` in `_pickle.c` · Issue #150157 · python/cpython

Missing critical section for PyDict_Next in _pickle.c #150157

New issue
Copy link
New issue
Copy link
Closed
#150158
Closed
Missing critical section for PyDict_Next in _pickle.c#150157
#150158
Copy link
Labels
extension-modulesC modules in the Modules dirC modules in the Modules dirtopic-free-threadingtype-bugAn unexpected behavior, bug, or errorAn unexpected behavior, bug, or error

Description

@KowalskiThomas
KowalskiThomas
opened on May 20, 2026
Issue body actions

Bug report

Bug description:

whichmodule (Modules/_pickle.c) iterates over sys.modules using PyDict_Next and immediately Py_INCREFs the borrowed references it returns, with no synchronisation. In a free-threaded build another thread can remove an entry from sys.modules between the PyDict_Next call and the subsequent Py_INCREFs. PySys_GetAttr gives a strong reference to the dict itself, so the dict won't be freed, but the borrowed key/value pointers returned by PyDict_Next are not protected. The path is triggered when pickling a class whose __module__ is None (e.g. numpy ufuncs).

import pickle, sys, threading, types

class NoModule:
    pass

NoModule.__module__ = None  # forces whichmodule to scan sys.modules

def _pickle_worker():
    for _ in range(200_000):
        try: pickle.dumps(NoModule)
        except Exception: pass

def _mutate_worker():
    for i in range(200_000):
        name = f"__tmp_{i % 200}"
        sys.modules[name] = types.ModuleType(name)
        sys.modules.pop(f"__tmp_{(i - 50) % 200}", None)

threads = [threading.Thread(target=_pickle_worker) for _ in range(4)]
threads += [threading.Thread(target=_mutate_worker)]
for t in threads: t.start()
for t in threads: t.join()

gives

$ ./python.exe ../repro.py
zsh: segmentation fault  ./python.exe ./repro.py

Proposed fix

Wrap the PyDict_Next loop in Py_BEGIN_CRITICAL_SECTION(modules) / Py_END_CRITICAL_SECTION, restructuring early returns as breaks so the section is always exited cleanly (same pattern used in #145446).

CPython versions tested on:

CPython main branch

Operating systems tested on:

macOS

Linked PRs

  • gh-150157: fix: critical section for PyDict_Next in _pickle.c #150158
  • [3.14] gh-150157: Fix critical section for PyDict_Next() in _pickle.c (GH-150158) #150710
  • [3.15] gh-150157: Fix critical section for PyDict_Next() in _pickle.c (GH-150158) #150711
  • [3.13] gh-150157: add critical section for PyDict_Next in _pickle.c #150951

Activity

  1. KowalskiThomas
    added
    type-bugAn unexpected behavior, bug, or errorAn unexpected behavior, bug, or error
    on May 20, 2026
  2. aisk
    added
    extension-modulesC modules in the Modules dirC modules in the Modules dir
    topic-free-threading
    on May 20, 2026
  3. aisk
    added this to Pickle and copy issues 🥒on May 20, 2026
  4. serhiy-storchaka
    closed this as completedin #150158on Jun 1, 2026
  5. serhiy-storchaka
    added a commit that references this issue on Jun 1, 2026

    gh-150157: Fix critical section for PyDict_Next() in _pickle.c (GH-15…

    c5516e7
  6. github-project-automation
    moved this to Done in Pickle and copy issues 🥒on Jun 1, 2026
  7. serhiy-storchaka
    added 2 commits that reference this issue on Jun 1, 2026

    [3.14] gh-150157: Fix critical section for PyDict_Next() in _pickle.c (…

    c15f066

    [3.15] gh-150157: Fix critical section for PyDict_Next() in _pickle.c (…

    b65c282
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

    extension-modulesC modules in the Modules dirC modules in the Modules dirtopic-free-threadingtype-bugAn unexpected behavior, bug, or errorAn unexpected behavior, bug, or error

    Projects

    • Pickle and copy issues 🥒
      Status
      Done
      Show more project fields

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions

    You are visitor 01402503 — GeezerVison does not store the pages you look up.
    Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required.