Skip to content

Commit

Permalink
Improved Windows compatibility for machine command
Browse files Browse the repository at this point in the history
Signed-off-by: Arthur Sengileyev <[email protected]>
  • Loading branch information
arixmkii authored and mheon committed Sep 6, 2022
1 parent 8634f55 commit 7bb7908
Show file tree
Hide file tree
Showing 8 changed files with 101 additions and 34 deletions.
20 changes: 20 additions & 0 deletions pkg/machine/machine_windows.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
//go:build windows
// +build windows

package machine

import (
"syscall"
)

func GetProcessState(pid int) (active bool, exitCode int) {
const da = syscall.STANDARD_RIGHTS_READ | syscall.PROCESS_QUERY_INFORMATION | syscall.SYNCHRONIZE
handle, err := syscall.OpenProcess(da, false, uint32(pid))
if err != nil {
return false, int(syscall.ERROR_PROC_NOT_FOUND)
}

var code uint32
syscall.GetExitCodeProcess(handle, &code)
return code == 259, int(code)
}
24 changes: 5 additions & 19 deletions pkg/machine/qemu/machine.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
//go:build (amd64 && !windows) || (arm64 && !windows)
// +build amd64,!windows arm64,!windows
//go:build amd64 || arm64
// +build amd64 arm64

package qemu

Expand Down Expand Up @@ -33,7 +33,6 @@ import (
"github.com/digitalocean/go-qemu/qmp"
"github.com/docker/go-units"
"github.com/sirupsen/logrus"
"golang.org/x/sys/unix"
)

var (
Expand Down Expand Up @@ -125,7 +124,7 @@ func (p *Provider) NewMachine(opts machine.InitOptions) (machine.VM, error) {
return nil, err
}
vm.QMPMonitor = monitor
cmd = append(cmd, []string{"-qmp", monitor.Network + ":/" + monitor.Address.GetPath() + ",server=on,wait=off"}...)
cmd = append(cmd, []string{"-qmp", monitor.Network + ":" + monitor.Address.GetPath() + ",server=on,wait=off"}...)

// Add network
// Right now the mac address is hardcoded so that the host networking gives it a specific IP address. This is
Expand Down Expand Up @@ -629,14 +628,9 @@ func (v *MachineVM) Start(name string, _ machine.StartOptions) error {
break
}
// check if qemu is still alive
var status syscall.WaitStatus
pid, err := syscall.Wait4(cmd.Process.Pid, &status, syscall.WNOHANG, nil)
err := checkProcessStatus("qemu", cmd.Process.Pid, stderrBuf)
if err != nil {
return fmt.Errorf("failed to read qemu process status: %w", err)
}
if pid > 0 {
// child exited
return fmt.Errorf("qemu exited unexpectedly with exit code %d, stderr: %s", status.ExitStatus(), stderrBuf.String())
return err
}
time.Sleep(wait)
wait++
Expand Down Expand Up @@ -1724,14 +1718,6 @@ func (p *Provider) RemoveAndCleanMachines() error {
return prevErr
}

func isProcessAlive(pid int) bool {
err := unix.Kill(pid, syscall.Signal(0))
if err == nil || err == unix.EPERM {
return true
}
return false
}

func (p *Provider) VMType() string {
return vmtype
}
Expand Down
33 changes: 33 additions & 0 deletions pkg/machine/qemu/machine_unix.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
//go:build darwin || dragonfly || freebsd || linux || netbsd || openbsd
// +build darwin dragonfly freebsd linux netbsd openbsd

package qemu

import (
"bytes"
"fmt"
"syscall"

"golang.org/x/sys/unix"
)

func isProcessAlive(pid int) bool {
err := unix.Kill(pid, syscall.Signal(0))
if err == nil || err == unix.EPERM {
return true
}
return false
}

func checkProcessStatus(processHint string, pid int, stderrBuf *bytes.Buffer) error {
var status syscall.WaitStatus
pid, err := syscall.Wait4(pid, &status, syscall.WNOHANG, nil)
if err != nil {
return fmt.Errorf("failed to read qem%su process status: %w", processHint, err)
}
if pid > 0 {
// child exited
return fmt.Errorf("%s exited unexpectedly with exit code %d, stderr: %s", processHint, status.ExitStatus(), stderrBuf.String())
}
return nil
}
4 changes: 2 additions & 2 deletions pkg/machine/qemu/machine_unsupported.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
//go:build (!amd64 && !arm64) || windows
// +build !amd64,!arm64 windows
//go:build (!amd64 && !arm64)
// +build !amd64,!arm64

package qemu
27 changes: 27 additions & 0 deletions pkg/machine/qemu/machine_windows.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package qemu

import (
"bytes"
"fmt"

"github.com/containers/podman/v4/pkg/machine"
)

func isProcessAlive(pid int) bool {
if checkProcessStatus("process", pid, nil) == nil {
return true
}
return false
}

func checkProcessStatus(processHint string, pid int, stderrBuf *bytes.Buffer) error {
active, exitCode := machine.GetProcessState(pid)
if !active {
if stderrBuf != nil {
return fmt.Errorf("%s exited unexpectedly, exit code: %d stderr: %s", processHint, exitCode, stderrBuf.String())
} else {
return fmt.Errorf("%s exited unexpectedly, exit code: %d", processHint, exitCode)
}
}
return nil
}
13 changes: 13 additions & 0 deletions pkg/machine/qemu/options_windows.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package qemu

import (
"os"
)

func getRuntimeDir() (string, error) {
tmpDir, ok := os.LookupEnv("TEMP")
if !ok {
tmpDir = os.Getenv("LOCALAPPDATA") + "\\Temp"
}
return tmpDir, nil
}
2 changes: 1 addition & 1 deletion pkg/machine/wsl/machine.go
Original file line number Diff line number Diff line change
Expand Up @@ -1063,7 +1063,7 @@ func launchWinProxy(v *MachineVM) (bool, string, error) {
}

return globalName, pipePrefix + waitPipe, waitPipeExists(waitPipe, 30, func() error {
active, exitCode := getProcessState(cmd.Process.Pid)
active, exitCode := machine.GetProcessState(cmd.Process.Pid)
if !active {
return fmt.Errorf("win-sshproxy.exe failed to start, exit code: %d (see windows event logs)", exitCode)
}
Expand Down
12 changes: 0 additions & 12 deletions pkg/machine/wsl/util_windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -280,18 +280,6 @@ func obtainShutdownPrivilege() error {
return nil
}

func getProcessState(pid int) (active bool, exitCode int) {
const da = syscall.STANDARD_RIGHTS_READ | syscall.PROCESS_QUERY_INFORMATION | syscall.SYNCHRONIZE
handle, err := syscall.OpenProcess(da, false, uint32(pid))
if err != nil {
return false, int(syscall.ERROR_PROC_NOT_FOUND)
}

var code uint32
syscall.GetExitCodeProcess(handle, &code)
return code == 259, int(code)
}

func addRunOnceRegistryEntry(command string) error {
k, _, err := registry.CreateKey(registry.CURRENT_USER, `Software\Microsoft\Windows\CurrentVersion\RunOnce`, registry.WRITE)
if err != nil {
Expand Down

0 comments on commit 7bb7908

Please sign in to comment.