Skip to content

test_concurrent_lazy_import_reification is flaky #154561

Closed as duplicate
Closed as duplicate

Description

@StanFromIreland

Bug report

Bug description:

See for example, this run:


======================================================================
FAIL: test_concurrent_lazy_import_reification (test.test_lazy_import.ThreadSafetyTests.test_concurrent_lazy_import_reification)
Multiple threads racing to reify the same lazy import should succeed.
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/var/lib/buildbot/workers/rise-riscv64-3/3.x.rise-riscv64-3.nogil/build/Lib/test/test_lazy_import/__init__.py", line 1820, in test_concurrent_lazy_import_reification
    self.assertEqual(errors, [], f"Errors occurred: {errors}")
    ~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
AssertionError: Lists differ: [(9, AttributeError("module 'test.test_laz[39 chars]'"))] != []

First list contains 1 additional elements.
First extra element 0:
(9, AttributeError("module 'test.test_lazy_import.data' has no attribute 'basic2'"))

+ []
- [(9,
-   AttributeError("module 'test.test_lazy_import.data' has no attribute 'basic2'"))] : Errors occurred: [(9, AttributeError("module 'test.test_lazy_import.data' has no attribute 'basic2'"))]

----------------------------------------------------------------------
Ran 128 tests in 78.334s

FAILED (failures=1)
test test_lazy_import failed

CPython versions tested on:

CPython main branch

Operating systems tested on:

No response

Linked PRs

Activity

  1. johnslavik commented on Jul 23, 2026

    @johnslavik
    Member
  2. johnslavik commented on Jul 23, 2026

    @johnslavik
    Member

    Oh, I thought this was new but it's an old one. I'll try to work on this. I reproduced it locally.

  3. self-assigned this
    on Jul 23, 2026
  4. BHUVANSH855 commented on Jul 24, 2026

    @BHUVANSH855
    Contributor

    Hi! I've been investigating the intermittent failure in test_concurrent_lazy_import_reification and have been able to reproduce it locally.

    So far I've instrumented both the C and Python sides of the lazy import path. Here's what I've observed:

    • setattr(parent_module, child, module) succeeds, and an immediate assert getattr(parent_module, child) is module always passes.
    • _find_and_load_lazy_submodule() is just a wrapper around _find_and_load(..., lazy_submodule=True).
    • _find_and_load_unlocked() publishes the child module on the parent and doesn't appear to remove it afterwards.
    • During a failing run, I see the following sequence:
      • the attribute is initially missing (has_key=0, contains=1),
      • it is successfully published,
      • the pending entry is discarded,
      • later another thread still gets AttributeError, and by then the pending-set entry is already gone (contains=0).

    At this point I'm not seeing any Python-level code that removes the published attribute after setattr(), so I'm wondering if I'm looking in the wrong place.

    Would you recommend continuing to investigate the free-threaded module attribute implementation / synchronization, or is there another part of the lazy import implementation that would be a better place to look?

  5. brittanyrey commented on Sep 18, 2026

    @brittanyrey
    Contributor

    This no longer repros.
    It looks like it was fixed when the fix for #155194 went in.
    cc: @johnslavik to close

  6. johnslavik commented on Sep 18, 2026

    @johnslavik
    Member

    I've stress-tested the test under a higher number of threads and confirm this no longer reproduces. Thank you @brittanyrey!

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

Metadata

Metadata

Assignees

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions