Skip to content

fix: handle closed logging streams in dispose_engine shutdown#1526

Open
2byrds wants to merge 5 commits intomicrosoft:mainfrom
2byrds:fix/shutdown-logging-error-1520
Open

fix: handle closed logging streams in dispose_engine shutdown#1526
2byrds wants to merge 5 commits intomicrosoft:mainfrom
2byrds:fix/shutdown-logging-error-1520

Conversation

@2byrds
Copy link
Copy Markdown

@2byrds 2byrds commented Mar 21, 2026

Summary

  • Wraps the logger.info call in SQLiteMemory.dispose_engine() with try/except (ValueError, OSError) to handle closed logging streams during interpreter shutdown
  • Adds a regression test that reproduces the issue by closing a log handler's stream before calling dispose_engine()

Closes #1520

Root cause

MemoryInterface.cleanup() registers dispose_engine via both atexit.register and weakref.finalize. During interpreter shutdown, these callbacks can fire after other code (test runners, application cleanup) has already closed logging handler streams, causing ValueError: I/O operation on closed file.

Fix

The standard CPython pattern for atexit/finalizer logging: guard the log call with try/except since module globals and I/O streams may be unavailable during teardown. The fix is intentionally minimal — it does not restructure the cleanup registration, only makes the existing logging call shutdown-safe.

Test plan

Made with Cursor

During interpreter shutdown, atexit/weakref finalizer callbacks can
fire after logging handler streams are already closed, raising
ValueError. Wrap the logger.info call in dispose_engine with a
try/except so cleanup is silent when streams are unavailable.

Closes microsoft#1520

Made-with: Cursor
@2byrds
Copy link
Copy Markdown
Author

2byrds commented Mar 21, 2026

@microsoft-github-policy-service agree company="ClearEdge IT Solutions, LLC"

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR aims to make SQLiteMemory.dispose_engine() safe to run during interpreter shutdown by preventing shutdown-time logging failures when logging streams/handlers have already been closed (issue #1520).

Changes:

  • Wraps SQLiteMemory.dispose_engine()’s informational log line in a try/except (ValueError, OSError) block.
  • Adds a unit regression test intended to reproduce the closed-log-stream shutdown scenario.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 3 comments.

File Description
pyrit/memory/sqlite_memory.py Attempts to guard shutdown-time logger.info(...) against failures when streams are closed.
tests/unit/memory/test_sqlite_memory.py Adds a regression test for disposing with a closed logging stream.

Byrd and others added 2 commits March 21, 2026 16:20
…afety

Address Copilot review feedback:
- StreamHandler.emit() catches ValueError internally and calls
  handleError() which prints to stderr without re-raising, so a
  try/except around logger.info() won't suppress the shutdown noise.
  Use logging.raiseExceptions = False instead, which handleError()
  checks before printing.
- Test now uses sqlite_instance fixture instead of direct construction,
  sets logger level to INFO so the log line actually emits, and asserts
  no "Logging error" appears in stderr via capsys.

Made-with: Cursor
- Use logging.raiseExceptions pattern in both SQLiteMemory and
  AzureSQLMemory dispose_engine() to suppress logging errors when
  handler streams are already closed during interpreter shutdown
- Move inline imports to module level in the test file
- Add comment explaining why raiseExceptions is needed (logging
  framework catches ValueError internally, so try/except at the
  call site does not help)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@rlundeen2
Copy link
Copy Markdown
Contributor

Thx @2byrds! I made some small changes but will merge once gates finish

@2byrds
Copy link
Copy Markdown
Author

2byrds commented Mar 22, 2026

Thx @2byrds! I made some small changes but will merge once gates finish

Thank you @rlundeen2 we appreciate this project!

@2byrds
Copy link
Copy Markdown
Author

2byrds commented Mar 24, 2026

Thx @2byrds! I made some small changes but will merge once gates finish

i saw the upstream branch had received changes so i updated the pr @rlundeen2

@2byrds
Copy link
Copy Markdown
Author

2byrds commented Mar 25, 2026

i continue to keep this updated with upstream @rlundeen2

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.

Shutdown-time logging error: SQLiteMemory.dispose_engine() logs after handler stream closed (ValueError: I/O operation on closed file)

3 participants