server_windows.go 1.63 KB
Newer Older
1
2
3
4
package lifecycle

import (
	"context"
5
	"fmt"
6
7
	"os/exec"
	"syscall"
8
9

	"golang.org/x/sys/windows"
10
11
12
13
)

func getCmd(ctx context.Context, exePath string) *exec.Cmd {
	cmd := exec.CommandContext(ctx, exePath, "serve")
14
15
16
17
18
	cmd.SysProcAttr = &syscall.SysProcAttr{
		HideWindow:    true,
		CreationFlags: windows.CREATE_NEW_PROCESS_GROUP,
	}

19
20
	return cmd
}
21
22
23
24
25
26

func terminate(cmd *exec.Cmd) error {
	dll, err := windows.LoadDLL("kernel32.dll")
	if err != nil {
		return err
	}
Michael Yang's avatar
Michael Yang committed
27
28
	//nolint:errcheck
	defer dll.Release()
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76

	pid := cmd.Process.Pid

	f, err := dll.FindProc("AttachConsole")
	if err != nil {
		return err
	}

	r1, _, err := f.Call(uintptr(pid))
	if r1 == 0 && err != syscall.ERROR_ACCESS_DENIED {
		return err
	}

	f, err = dll.FindProc("SetConsoleCtrlHandler")
	if err != nil {
		return err
	}

	r1, _, err = f.Call(0, 1)
	if r1 == 0 {
		return err
	}

	f, err = dll.FindProc("GenerateConsoleCtrlEvent")
	if err != nil {
		return err
	}

	r1, _, err = f.Call(windows.CTRL_BREAK_EVENT, uintptr(pid))
	if r1 == 0 {
		return err
	}

	r1, _, err = f.Call(windows.CTRL_C_EVENT, uintptr(pid))
	if r1 == 0 {
		return err
	}

	return nil
}

const STILL_ACTIVE = 259

func isProcessExited(pid int) (bool, error) {
	hProcess, err := windows.OpenProcess(windows.PROCESS_QUERY_INFORMATION, false, uint32(pid))
	if err != nil {
		return false, fmt.Errorf("failed to open process: %v", err)
	}
Michael Yang's avatar
Michael Yang committed
77
78
	//nolint:errcheck
	defer windows.CloseHandle(hProcess)
79
80
81
82
83
84
85
86
87
88
89
90
91

	var exitCode uint32
	err = windows.GetExitCodeProcess(hProcess, &exitCode)
	if err != nil {
		return false, fmt.Errorf("failed to get exit code: %v", err)
	}

	if exitCode == STILL_ACTIVE {
		return false, nil
	}

	return true, nil
}