diff --git a/.github/actions/windows_plain_smoke_test/action.yml b/.github/actions/windows_plain_smoke_test/action.yml index 2ca4b7dc..477ec299 100644 --- a/.github/actions/windows_plain_smoke_test/action.yml +++ b/.github/actions/windows_plain_smoke_test/action.yml @@ -17,6 +17,17 @@ inputs: the template or Lima's default decides. required: false default: '' + launch-default-distro-during-stop: + description: > + When 'true', test that `limactl stop` completes even if the instance's + distro restarts during it. GitHub's runner agent sometimes runs + `wsl -u root -e ls`, which starts the default distro, and that is the + instance's when no other is installed. The step runs the same command + while the stop terminates the instance. If the stop's status checks then + keep the restarted distro running, the stop times out. Only for the WSL2 + driver. + required: false + default: 'false' runs: using: composite steps: @@ -27,6 +38,7 @@ runs: INSTANCE: ${{ inputs.instance-name }} TEMPLATE: ${{ inputs.template }} VM_TYPE: ${{ inputs.vm-type }} + LAUNCH_DEFAULT_DISTRO_DURING_STOP: ${{ inputs.launch-default-distro-during-stop }} run: | $ErrorActionPreference = 'Stop' # $ErrorActionPreference does not stop on a native command's exit code. @@ -53,7 +65,25 @@ runs: if ($back -ne 'roundtrip') { throw "round-trip mismatch: expected 'roundtrip', got '$back'" } + if ($env:LAUNCH_DEFAULT_DISTRO_DURING_STOP -eq 'true') { + $launcher = Start-Job -ScriptBlock { + while (-not (Get-CimInstance Win32_Process -Filter "Name='wsl.exe'" | + Where-Object { $_.CommandLine -like '*--terminate*' })) { + Start-Sleep -Milliseconds 100 + } + # Give the terminate time to begin, so the launch starts the distro again. + Start-Sleep -Milliseconds 200 + wsl.exe -u root -e ls *> $null + if ($LASTEXITCODE -ne 0) { throw "wsl.exe -u root -e ls exited $LASTEXITCODE" } + 'launched' + } + } Invoke-Limactl stop $env:INSTANCE + if ($launcher) { + $launched = Wait-Job $launcher -Timeout 30 | Receive-Job + Remove-Job $launcher -Force + if ($launched -ne 'launched') { throw 'default-distro launch during limactl stop did not complete' } + } Invoke-Limactl delete --force $env:INSTANCE - name: Dump Lima logs on failure diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 53f805d5..c9d44dc0 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -250,6 +250,7 @@ jobs: - uses: $/.github/actions/windows_plain_smoke_test with: template: .\templates\experimental\wsl2.yaml + launch-default-distro-during-stop: 'true' windows-plain-qemu: # Like windows-plain-wsl2, for the QEMU driver. The reverse-sshfs mount diff --git a/pkg/driver/wsl2/wsl_driver_windows.go b/pkg/driver/wsl2/wsl_driver_windows.go index 02498578..e134adfb 100644 --- a/pkg/driver/wsl2/wsl_driver_windows.go +++ b/pkg/driver/wsl2/wsl_driver_windows.go @@ -222,7 +222,11 @@ func (l *LimaWslDriver) InspectStatus(ctx context.Context, inst *limatype.Instan inst.SSHLocalPort = 22 - if inst.Status == limatype.StatusRunning { + // Each `wsl -d` from getSSHAddress restarts WSL's idle timer for the + // distro, so skip it while no host agent runs. Otherwise, when another + // program relaunches the distro after `limactl stop` terminates it, the + // status checks keep it from going idle and the stop times out. + if inst.Status == limatype.StatusRunning && inst.HostAgentPID != 0 { sshAddr, err := getSSHAddress(ctx, inst.Name) if err == nil { inst.SSHAddress = sshAddr