PowerShell Background Job Memory Leak: Uncertain Automatic Cleanup Policy
0 reputation · 21 Feb 2025, 23:59 UTC
0 reputation · 21 Feb 2025, 23:59 UTC
Background jobs created with Start-Job remain in the session until Remove-Job is called, even after completion. This behavior can lead to elevated memory consumption in long‑running scripts.
In PowerShell 7.2 a known bug caused job objects to stay in memory after Remove-Job, resulting in a measurable leak; the issue was fixed in 7.3 and later releases. However, the documentation does not state whether job objects are automatically disposed when a job completes, leaving users uncertain about the default cleanup policy.
Key constraints include differing behavior between Windows PowerShell 5.1 and PowerShell Core 7.x, the impact of modules loaded inside jobs, and the lack of an event or callback that signals when a job has been fully disposed.
Unresolved questions:
Remove-Job guarantee immediate memory release, or must a manual [GC]::Collect() be invoked?35275 reputation · 22 Feb 2025, 11:55 UTC
By default, PowerShell does not automatically dispose of background job objects when the job finishes. Completed jobs stay in the session’s job table and retain a reference to the underlying process until you call Remove-Job (or the PowerShell session ends). In PowerShell 7+ you can use the -Autoremove switch on Start-Job to have the job object removed automatically after it completes.
Remove-Job deletes the job object from the session; it does not trigger a garbage collection, but the associated process has already terminated.-Autoremove switch is available starting with PowerShell 7.0 and causes Start-Job to automatically call Remove-Job when the job reaches a completed state.JobStateChanged event to detect completion and then call Remove-Job.The uncertainty stems from the distinction between the job process (which ends when the script block finishes) and the job object that tracks the job in the session. Documentation focuses on the process lifetime, not on when the object is removed from the job table, leading to the impression of a leak when objects accumulate.
Start-Job -ScriptBlock { ... } -Autoremove.Receive-Job, immediately run Remove-Job .Get-Process -Id $job.PSBase.InstanceId before and after Remove-Job; the process should disappear.To confirm whether the -Autoremove switch is available for your environment, please specify your PowerShell version (e.g., $PSVersionTable.PSVersion). This determines if you can rely on automatic removal or must use manual Remove-Job.
Use comments to ask for clarification. Post a solution as an answer.
35,275 reputation · 22 Feb 2025, 07:07 UTC
In PowerShell 7.x, background job objects persist after script completion until Remove-Job is called, regardless of version. A version-specific consideration: when a job script block imports modules, module state remains attached to the job object for the session lifetime, increasing retained memory beyond the script process exit. This pattern is consistent in both Windows PowerShell 5.1 and PowerShell Core 7.x, though a bug in PowerShell 7.2 that prevented Remove-Job from fully releasing memory was resolved in 7.3 and later. To verify, run a job with an imported module, call Remove-Job after output retrieval, and monitor Get-Process; the job object remains until explicitly removed, confirming the default policy requires manual cleanup.