Skip to content

Comments

Fix multiprocessing.Manager resource leak in concurrent diff processing#4953

Closed
Bitshifter-9 wants to merge 5 commits intopsf:mainfrom
Bitshifter-9:main
Closed

Fix multiprocessing.Manager resource leak in concurrent diff processing#4953
Bitshifter-9 wants to merge 5 commits intopsf:mainfrom
Bitshifter-9:main

Conversation

@Bitshifter-9
Copy link

@Bitshifter-9 Bitshifter-9 commented Jan 11, 2026

When Black is run with --diff or --color-diff, it creates a multiprocessing.Manager() to share locks across worker processes. This Manager was never explicitly shut down, which can leave background processes running after Black finishes. This becomes problematic when Black is used as a library or invoked repeatedly in long-running environments such as editor integrations or CI pipelines.

This change ensures deterministic cleanup of the Manager by wrapping the main execution path in schedule_formatting() with a try–finally block and calling manager.shutdown() whenever a Manager is created, even if an exception occurs. The fix is intentionally minimal to avoid unnecessary diff noise and does not alter existing behavior beyond proper resource cleanup.

A new test suite in tests/test_manager_cleanup.py verifies that Manager.shutdown() is called on both successful execution and error paths, that no Manager is created when diff output modes are not used, and that early return paths do not create a Manager. All existing tests continue to pass, confirming backward compatibility and no functional regressions.

This prevents resource leaks and stray processes when Black is used repeatedly with diff output modes.
these fixes #4950

Closes #4952

Copilot AI review requested due to automatic review settings January 11, 2026 04:01
- Remove unused imports (Manager, call)
- Add type annotations to all functions
- Fix line length violations (break lines > 80 chars)
- Fix import order per Black conventions
Copy link
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 fixes a resource leak where multiprocessing.Manager() instances created for diff output modes (--diff or --color-diff) were never properly shut down, potentially leaving background processes running. The fix adds a try-finally block to ensure manager.shutdown() is called even when exceptions occur during formatting.

Changes:

  • Initialize manager variable to None and wrap the main formatting loop in a try-finally block that calls manager.shutdown() when the manager exists
  • Add comprehensive test suite to verify Manager cleanup on success, exception, non-diff modes, and early return paths

Reviewed changes

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

File Description
src/black/concurrency.py Adds manager variable initialization and try-finally block to ensure Manager.shutdown() is called
tests/test_manager_cleanup.py New test suite verifying Manager cleanup in various scenarios

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@Bitshifter-9
Copy link
Author

these fixes #4950 @cobaltt7

- Use actual source files ({Path('test.py')}) instead of empty set
- Properly mock executor.submit() to return completed Futures
- Tests now correctly FAIL on base commit (shutdown not called)
- Tests PASS on fixed commit (shutdown called in finally block)
@github-actions
Copy link

github-actions bot commented Jan 12, 2026

diff-shades results comparing this PR (2677604) to main (b41acd6):

--preview style: no changes

--stable style: no changes


What is this? | Workflow run | diff-shades documentation

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.

Manager not properly shut down in concurrency module - violates multiprocessing best practices

2 participants