diff --git a/scripts/Remove-BuildVM.ps1 b/scripts/Remove-BuildVM.ps1 index 21a2b3b..936a126 100644 --- a/scripts/Remove-BuildVM.ps1 +++ b/scripts/Remove-BuildVM.ps1 @@ -72,16 +72,37 @@ $stateOutput = & $VmrunPath -T ws getState $VMPath 2>&1 if ($stateOutput -match 'running') { Write-Host "[Remove-BuildVM] Graceful stop timed out — forcing hard stop..." & $VmrunPath -T ws stop $VMPath hard 2>&1 | Out-Null - Start-Sleep -Seconds 3 } -# ── Step 4: Delete VM via vmrun (removes VMX + delta VMDK) ─────────────────── +# Poll vmrun list until VMX is gone — vmware-vmx.exe may hold file locks briefly +# after stop. Waiting for the entry to disappear ensures deleteVM won't race the +# process exit. +$vmxNorm = $VMPath.Trim().ToLower() +$releaseDeadline = (Get-Date).AddSeconds(20) +while ((Get-Date) -lt $releaseDeadline) { + $listedVMs = & $VmrunPath -T ws list 2>&1 | + Where-Object { $_ -notmatch '^Total running' } | + ForEach-Object { "$_".Trim().ToLower() } + if ($listedVMs -notcontains $vmxNorm) { break } + Start-Sleep -Seconds 2 +} + +# ── Step 4: Delete VM via vmrun — retry up to 3× with backoff ──────────────── Write-Host "[Remove-BuildVM] Deleting VM..." -$deleteOutput = & $VmrunPath -T ws deleteVM $VMPath 2>&1 -$deleteExit = $LASTEXITCODE +$deleteOutput = '' +$deleteExit = -1 +foreach ($delay in @(0, 3, 6)) { + if ($delay -gt 0) { + Write-Host "[Remove-BuildVM] Retrying deleteVM in ${delay}s..." + Start-Sleep -Seconds $delay + } + $deleteOutput = & $VmrunPath -T ws deleteVM $VMPath 2>&1 + $deleteExit = $LASTEXITCODE + if ($deleteExit -eq 0) { break } +} if ($deleteExit -ne 0) { - Write-Warning "[Remove-BuildVM] vmrun deleteVM returned exit code $deleteExit : $deleteOutput" + Write-Warning "[Remove-BuildVM] vmrun deleteVM failed after retries (exit $deleteExit): $deleteOutput" Write-Warning "[Remove-BuildVM] Will attempt manual directory removal." }