Skip to content

fix: close SQLite storage in Harness.cleanup()#2507

Draft
tonyandrewmeyer wants to merge 4 commits into
canonical:mainfrom
tonyandrewmeyer:rainy/harness-teardown-werror
Draft

fix: close SQLite storage in Harness.cleanup()#2507
tonyandrewmeyer wants to merge 4 commits into
canonical:mainfrom
tonyandrewmeyer:rainy/harness-teardown-werror

Conversation

@tonyandrewmeyer
Copy link
Copy Markdown
Collaborator

@tonyandrewmeyer tonyandrewmeyer commented May 26, 2026

We don't normally do fixes in Harness, but this will allow charms that are not yet migrated to Scenario to run with -Werror and not get hit by a resource warning we cause.

Harness builds a framework.Framework backed by an in-memory SQLiteStorage, but Harness.cleanup() never closes it. The sqlite3 connection is only released when the Harness is garbage-collected, at which point its destructor emits unclosed database in <sqlite3.Connection ...>. pytest wraps that as PytestUnraisableExceptionWarning and -W error turns it into a test failure — even for callers who correctly call harness.cleanup().

This is one of the bug classes flagged by a recent canonical/hyrum (super-tox) run across the canonical charm collection: under -Werror, charms whose tests use ops.testing.Harness regress even though their own code is clean.

Changes:

  • Harness.cleanup(): call self._framework.close() after the backend cleanup so the SQLiteStorage connection is closed eagerly. sqlite3's close() is idempotent, so repeated cleanup() calls stay safe.
  • Add a regression test that asserts the storage's underlying connection is closed after harness.cleanup().

Harness held a TemporaryDirectory and an SQLiteStorage that were only
released when the object was garbage-collected. On Python 3.14 those
fallbacks emit ResourceWarning (Implicitly cleaning up TemporaryDirectory,
unclosed database), which pytest wraps as PytestUnraisableExceptionWarning
and -W error turns into a test failure. This was a major contributor to
downstream charm test failures under -Werror in canonical/hyrum runs.

Mirror the approach being taken for scenario.Context in canonical#2506: replace
the two TemporaryDirectory instances with mkdtemp + weakref.finalize so
the GC-time cleanup path is silent, and register a finalizer that closes
Harness's Framework (and thus the SQLite connection) if the caller forgot
to call cleanup(). cleanup() itself remains the eager-cleanup entry point
and is idempotent.

Adds two regression tests: one asserting cleanup() releases the tempdir,
and one asserting that dropping a Harness without cleanup() does not emit
any ResourceWarning.
@tonyandrewmeyer tonyandrewmeyer changed the title fix(testing): close resources eagerly in Harness teardown fix: close resources eagerly in Harness teardown May 26, 2026
@dwilding
Copy link
Copy Markdown
Contributor

under -Werror, charms whose tests use ops.testing.Harness regress even though their own code is clean

To help my understanding: Are those charm tests not using harness.cleanup()? Or would the warnings happen even if they're using harness.cleanup()?

@tonyandrewmeyer
Copy link
Copy Markdown
Collaborator Author

under -Werror, charms whose tests use ops.testing.Harness regress even though their own code is clean

To help my understanding: Are those charm tests not using harness.cleanup()? Or would the warnings happen even if they're using harness.cleanup()?

There are two pieces in the PR:

  • closing the framework's sqlite3 storage -- without the PR this is always leaked until gc
  • the temp directory cleanup switch to weaker -- this is a safety net for not calling cleanup()

Thinking about this more, I think the second case should be dropped; people should explicitly call cleanup(). I'll remove that part of the PR.

@tonyandrewmeyer tonyandrewmeyer changed the title fix: close resources eagerly in Harness teardown fix: close SQLite storage in Harness.cleanup() May 27, 2026
@tonyandrewmeyer
Copy link
Copy Markdown
Collaborator Author

Hmm, that data failure looks like it may be a real issue. Moving to draft while I figure that out.

@tonyandrewmeyer
Copy link
Copy Markdown
Collaborator Author

Hmm, that data failure looks like it may be a real issue. Moving to draft while I figure that out.

It's a downstream bug. We should wait for the PR with a fix to land before merging this, to avoid disabling our CI. There's no particular urgency.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants