Skip to content

Page.get_texttrace() leaks None references — Fatal Python error (none_dealloc) in long-running processes (1.27.2.3 & 1.28.0) #5042

Closed

Description

@manya4ello

Description

Every call to Page.get_texttrace() decrements the reference count of None more times than it increments it. On Python 3.11 (where None is not yet immortal) the deficit accumulates; once it exceeds None's base refcount (~12k), the interpreter dies with:

Fatal Python error: none_dealloc: deallocating None:
bug likely caused by a refcount error in a C extension

Long-running processes (batch conversion, large test suites) are affected; short single-document scripts usually stay under the threshold.

Minimal reproduction

import sys, pymupdf

doc = pymupdf.open()
page = doc.new_page()
for i in range(10):
    page.insert_text((72, 72 + i * 20), f"Hello world span {i}")

before = sys.getrefcount(None)
for _ in range(200):
    page.get_texttrace()
after = sys.getrefcount(None)
print("None refcount drift:", after - before)   # expected 0

Observed output: None refcount drift: -2657 (≈ −13 per call for this page). Increase the loop count and the interpreter eventually crashes with none_dealloc. All other hot APIs we probed (get_text, get_pixmap, open/close, page_count) show a drift of exactly 0.

Details we measured

  • The deficit scales with span count (≈ −4/call on an empty page, dozens on dense pages).
  • Part of the deficit fires when the result is disposed, not at call time: at construction a legitimate INCREF(None) and an erroneous extra DECREF(None) cancel numerically, but the slot still holds a pointer to None — disposing the result later performs a real, uncompensated DECREF(None). So a simple before/after window around the bare call underestimates the leak.

Environment

  • PyMuPDF 1.27.2.3 (MuPDF 1.27.2) — also reproduced on 1.28.0
  • Python 3.11 (Windows 11 x64; also reproduced on ubuntu-latest CI)

Prior art

Looks like the same defect class as #2146 (fixed in 2023), now present in get_texttrace().

Happy to test a fix; we currently work around it with a measured compensation wrapper on our side.

Activity

  1. self-assigned this
    on Jul 11, 2026
  2. JorjMcKie commented on Jul 11, 2026

    @JorjMcKie
    Collaborator

    Thanks for submitting this @manya4ello
    I have confirmed the bug and am developing fix.

  3. JorjMcKie commented on Jul 11, 2026

    @JorjMcKie
    Collaborator

    Developed a fix and submitted to review.

  4. manya4ello commented on Jul 11, 2026

    @manya4ello
    Author

    Thanks for the incredibly fast turnaround! Happy to verify — we'll run our refcount-drift reproducer against the fixed build as soon as it's available (release or pre-release) and confirm here.

  5. JorjMcKie commented on Jul 12, 2026

    @JorjMcKie
    Collaborator

    Thanks for your well prepared post - your reproducer is becoming part of our standard tests 👍.

  6. julian-smith-artifex-com commented on Aug 6, 2026

    @julian-smith-artifex-com
    Collaborator

    Fixed in PyMuPDF-1.28.2.

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

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions