fix: track Windows local process trees safely
This commit is contained in:
@@ -90,11 +90,27 @@ function Get-RecordedProcesses {
|
||||
|
||||
function Test-RecordedProcess {
|
||||
param($Record)
|
||||
$process = Get-Process -Id $Record.Pid -ErrorAction SilentlyContinue
|
||||
|
||||
try {
|
||||
$recordedProcessId = [int]$Record.Pid
|
||||
if ($recordedProcessId -le 0) { return $false }
|
||||
$recordedStartTime = if ($Record.StartTimeUtc -is [datetime]) {
|
||||
$Record.StartTimeUtc.ToUniversalTime()
|
||||
}
|
||||
else {
|
||||
[datetime]::Parse(
|
||||
[string]$Record.StartTimeUtc,
|
||||
[System.Globalization.CultureInfo]::InvariantCulture,
|
||||
[System.Globalization.DateTimeStyles]::RoundtripKind
|
||||
).ToUniversalTime()
|
||||
}
|
||||
}
|
||||
catch { return $false }
|
||||
|
||||
$process = Get-Process -Id $recordedProcessId -ErrorAction SilentlyContinue
|
||||
if (-not $process) { return $false }
|
||||
try {
|
||||
$actual = $process.StartTime.ToUniversalTime().ToString('o')
|
||||
return $actual -eq $Record.StartTimeUtc
|
||||
return $process.StartTime.ToUniversalTime().Ticks -eq $recordedStartTime.Ticks
|
||||
}
|
||||
catch { return $false }
|
||||
}
|
||||
|
||||
@@ -63,6 +63,43 @@ try {
|
||||
Assert-Equal './cmd/worker' $commands.Worker.Arguments[1] 'Worker command should follow the backend contract'
|
||||
Assert-Equal 'run' $commands.Frontend.Arguments[0] 'Frontend should use its checked-in dev script'
|
||||
|
||||
$stateDirectory = Join-Path $fixture '.local'
|
||||
New-Item -ItemType Directory -Path $stateDirectory -Force | Out-Null
|
||||
$currentProcess = Get-Process -Id $PID
|
||||
@([pscustomobject]@{
|
||||
Name = 'test-host'
|
||||
Pid = $currentProcess.Id
|
||||
StartTimeUtc = $currentProcess.StartTime.ToUniversalTime().ToString('o')
|
||||
}) | ConvertTo-Json | Set-Content -LiteralPath (Join-Path $stateDirectory 'processes.json') -Encoding utf8
|
||||
$status = @(Get-LocalDevStatus -DeploymentPath $fixture)
|
||||
Assert-Equal $true $status[0].Running 'Status should recognize a recorded live process after JSON date conversion'
|
||||
|
||||
$childTreeRoot = Start-Process -FilePath 'cmd.exe' -ArgumentList @('/c', 'powershell.exe -NoProfile -Command "Start-Sleep -Seconds 60"') -WindowStyle Hidden -PassThru
|
||||
try {
|
||||
$childTreeRoot.Refresh()
|
||||
@([pscustomobject]@{
|
||||
Name = 'test-tree'
|
||||
Pid = $childTreeRoot.Id
|
||||
StartTimeUtc = $childTreeRoot.StartTime.ToUniversalTime().ToString('o')
|
||||
}) | ConvertTo-Json | Set-Content -LiteralPath (Join-Path $stateDirectory 'processes.json') -Encoding utf8
|
||||
|
||||
$deadline = [DateTime]::UtcNow.AddSeconds(5)
|
||||
do {
|
||||
$child = Get-CimInstance Win32_Process -Filter "ParentProcessId=$($childTreeRoot.Id)" -ErrorAction SilentlyContinue | Select-Object -First 1
|
||||
if (-not $child) { Start-Sleep -Milliseconds 50 }
|
||||
} while (-not $child -and [DateTime]::UtcNow -lt $deadline)
|
||||
if (-not $child) { throw 'Test child process did not start' }
|
||||
|
||||
Stop-LocalDev -DeploymentPath $fixture
|
||||
Assert-Equal $null (Get-Process -Id $childTreeRoot.Id -ErrorAction SilentlyContinue) 'Stop should terminate the recorded wrapper process'
|
||||
Assert-Equal $null (Get-Process -Id $child.ProcessId -ErrorAction SilentlyContinue) 'Stop should terminate descendants of the recorded wrapper process'
|
||||
}
|
||||
finally {
|
||||
if (Get-Process -Id $childTreeRoot.Id -ErrorAction SilentlyContinue) {
|
||||
& taskkill.exe /PID $childTreeRoot.Id /T /F | Out-Null
|
||||
}
|
||||
}
|
||||
|
||||
Remove-Item -LiteralPath (Join-Path $backend 'cmd\worker') -Recurse
|
||||
Assert-Throws { Resolve-LocalDevCommands -BackendPath $backend -FrontendPath $frontend } 'cmd/worker' 'A missing worker entrypoint must be actionable'
|
||||
|
||||
|
||||
Reference in New Issue
Block a user