Skip to content

Session-end gc.collect() in unraisableexception plugin runs after warning filters are torn down, silently losing ResourceWarnings #14263

@djrobstep

Description

@djrobstep

Hi there, I ran into an issue recently where ResourceWarnings weren't getting raised as errors as expected.

The unraisableexception plugin registers a config.add_cleanup() callback that forces 5 rounds of gc.collect() at session end to catch leaked resources. However, config.add_cleanup() pushes onto a contextlib.ExitStack (LIFO), and the warnings plugin registers its cleanup after unraisableexception in the default_plugins tuple. This means:

  1. warnings cleanup runs first — tears down the catch_warnings context, removing filterwarnings = error::ResourceWarning from pytest.ini
  2. unraisableexception cleanup runs second — calls gc.collect(), finalizing unclosed resources. Their __del__ methods emit ResourceWarning, but the error filter is gone. The warning is silently discarded and never reaches sys.unraisablehook.

Reproducible example here

Suggested fixes (either would work)

  1. Reorder default_plugins: Swap unraisableexception and warnings so that unraisableexception's cleanup (including gc.collect()) runs while warning filters are still active.
  2. Move the GC logic to pytest_unconfigure: pytest_unconfigure runs before _cleanup_stack.close(), so both warning filters and sys.unraisablehook are still wired up at that point. This avoids depending on registration order entirely.

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