浏览代码

Merge pull request #1483 from docker/windows_sucks

make windows "kill children process" code simpler
Guillaume Tardif 4 年之前
父节点
当前提交
6a0269f7b9
共有 2 个文件被更改,包括 17 次插入69 次删除
  1. 16 69
      cli/mobycli/job_windows.go
  2. 1 0
      go.mod

+ 16 - 69
cli/mobycli/job_windows.go

@@ -18,9 +18,9 @@ package mobycli
 
 import (
 	"fmt"
-	"os"
-	"syscall"
 	"unsafe"
+
+	"golang.org/x/sys/windows"
 )
 
 func init() {
@@ -29,81 +29,28 @@ func init() {
 	}
 }
 
-var (
-	kernel32 = syscall.NewLazyDLL("kernel32.dll")
-)
-
-type jobObjectExtendedLimitInformation struct {
-	BasicLimitInformation struct {
-		PerProcessUserTimeLimit uint64
-		PerJobUserTimeLimit     uint64
-		LimitFlags              uint32
-		MinimumWorkingSetSize   uintptr
-		MaximumWorkingSetSize   uintptr
-		ActiveProcessLimit      uint32
-		Affinity                uintptr
-		PriorityClass           uint32
-		SchedulingClass         uint32
-	}
-	IoInfo struct {
-		ReadOperationCount  uint64
-		WriteOperationCount uint64
-		OtherOperationCount uint64
-		ReadTransferCount   uint64
-		WriteTransferCount  uint64
-		OtherTransferCount  uint64
-	}
-	ProcessMemoryLimit    uintptr
-	JobMemoryLimit        uintptr
-	PeakProcessMemoryUsed uintptr
-	PeakJobMemoryUsed     uintptr
-}
-
 // killSubProcessesOnClose will ensure on windows that all child processes of the current process are killed if parent is killed.
 func killSubProcessesOnClose() error {
-	job, err := createJobObject()
+	job, err := windows.CreateJobObject(nil, nil)
 	if err != nil {
 		return err
 	}
-	info := jobObjectExtendedLimitInformation{}
-	info.BasicLimitInformation.LimitFlags = 0x2000
-	if err := setInformationJobObject(job, info); err != nil {
-		_ = syscall.CloseHandle(job)
+	info := windows.JOBOBJECT_EXTENDED_LIMIT_INFORMATION{
+		BasicLimitInformation: windows.JOBOBJECT_BASIC_LIMIT_INFORMATION{
+			LimitFlags: windows.JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE,
+		},
+	}
+	if _, err := windows.SetInformationJobObject(
+		job,
+		windows.JobObjectExtendedLimitInformation,
+		uintptr(unsafe.Pointer(&info)),
+		uint32(unsafe.Sizeof(info))); err != nil {
+		_ = windows.CloseHandle(job)
 		return err
 	}
-	proc, err := syscall.GetCurrentProcess()
-	if err != nil {
-		_ = syscall.CloseHandle(job)
+	if err := windows.AssignProcessToJobObject(job, windows.CurrentProcess()); err != nil {
+		_ = windows.CloseHandle(job)
 		return err
 	}
-	if err := assignProcessToJobObject(job, proc); err != nil {
-		_ = syscall.CloseHandle(job)
-		return err
-	}
-	return nil
-}
-
-func createJobObject() (syscall.Handle, error) {
-	res, _, err := kernel32.NewProc("CreateJobObjectW").Call(uintptr(unsafe.Pointer(nil)), uintptr(unsafe.Pointer(nil)))
-	if res == 0 {
-		return syscall.InvalidHandle, os.NewSyscallError("CreateJobObject", err)
-	}
-	return syscall.Handle(res), nil
-}
-
-func setInformationJobObject(job syscall.Handle, info jobObjectExtendedLimitInformation) error {
-	infoClass := uint32(9)
-	res, _, err := kernel32.NewProc("SetInformationJobObject").Call(uintptr(job), uintptr(infoClass), uintptr(unsafe.Pointer(&info)), uintptr(uint32(unsafe.Sizeof(info))))
-	if res == 0 {
-		return os.NewSyscallError("SetInformationJobObject", err)
-	}
-	return nil
-}
-
-func assignProcessToJobObject(job syscall.Handle, process syscall.Handle) error {
-	res, _, err := kernel32.NewProc("AssignProcessToJobObject").Call(uintptr(job), uintptr(process))
-	if res == 0 {
-		return os.NewSyscallError("AssignProcessToJobObject", err)
-	}
 	return nil
 }

+ 1 - 0
go.mod

@@ -56,6 +56,7 @@ require (
 	github.com/valyala/fasttemplate v1.2.1 // indirect
 	golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58
 	golang.org/x/sync v0.0.0-20210220032951-036812b2e83c
+	golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4
 	google.golang.org/grpc v1.33.2
 	google.golang.org/protobuf v1.25.0
 	gopkg.in/ini.v1 v1.62.0