Skip to content

Neither background nor thread jobs seemingly automatically release COM / unmanaged resources when they complete / are stopped #24549

Open
@mklement0

Description

f### Prerequisites

Steps to reproduce

Note:

  • The repro below uses COM; I suspect - but haven't verified - that any unmanaged resources that aren't explicitly released are affected.

  • I would expect at least jobs that complete by themselves to auto-release such resources; ideally also when Stop-Job, Remove-Job -Force is used (don't know about the technical feasibility; Stop-Process applied to a regular session forcefully kills it and therefore does not auto-release).

    • That regular sessions do auto-release can be verified by setting $useJobs to $false below and re-running the script, which uses CLI calls instead of jobs.

    • Curiously, ForEach-Object -Parallel is seemingly not affected; in the following example the Excel processes do eventually disappear:

      Stop-Process -Name excel -ea ignore; 1, 2 | ForEach-Object -Parallel { $xl = New-Object -ComObject Excel.Application; $xl.Name; Start-Sleep 5 }
      
# Make sure no Excel processes are running
Get-Process -ErrorAction Ignore Excel | Stop-Process -Force -ErrorAction Stop


# A script block that creates a new Excel process via COM, assigns it to a variable, and waits 2  secs.
# before exiting (to ensure that it isn't garbage collected right away).
$sb = { $xl = New-Object -ComObject Excel.Application; $xl.Name; Start-Sleep 2 }

# Set this to $false to use CLI calls instead, which work correctly.
$useJobs = $true

if ($useJobs) {
  Write-Verbose -Verbose '--- Creating a background and a thread job each of which creates an Excel process via COM...'
  $jobs = (Start-Job $sb), (Start-ThreadJob $sb)
} else {
  Write-Verbose -Verbose '--- Calling the CLIs (powershell.exe and pwsh.exe) each of which create an Excel process via COM...'
  powershell -NoProfile $sb
  pwsh -NoProfile $sb
}

if ($useJobs) {
  $jobs | Receive-Job -Wait -AutoRemoveJob
}

# Wait a while to allow extra time for the COM resources to be released,
# which should result in the termination of the Excel processes.
Write-Verbose -Verbose 'Sleeping 30 secs. to wait for release of COM resources...'
Start-Sleep 30

# Now there should be NO Excel processes.
Write-Verbose -Verbose '--- Excel processes after (there should be no output)...'
Get-Process -ErrorAction Ignore Excel

Expected behavior

VERBOSE: --- Creating a background and a thread job each of which creates an Excel process via COM...
Microsoft Excel
Microsoft Excel
VERBOSE: Sleeping 30 secs. to wait for release of COM resources...
VERBOSE: --- Excel processes after (there should be no output)...

That is, the two Excel processes should eventually terminate due to auto-release of the COM wrapper.

Actual behavior

VERBOSE: --- Creating a background and a thread job each of which creates an Excel process via COM...
Microsoft Excel
Microsoft Excel
VERBOSE: Sleeping 30 secs. to wait for release of COM resources...
VERBOSE: --- Excel processes after (there should be no output)...

 NPM(K)    PM(M)      WS(M)     CPU(s)      Id  SI ProcessName
 ------    -----      -----     ------      --  -- -----------
     65    71.33     233.75       1.17    5900  12 EXCEL
     66    72.31     234.75       0.88   10488  12 EXCEL

That is, the two Excel processes linger, because the COM wrapper was never released.

Error details

No response

Environment data

PowerShell 7.5.0-preview.5

Visuals

No response

Metadata

Assignees

No one assigned

    Labels

    Needs-TriageThe issue is new and needs to be triaged by a work group.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions