Merge pull request #44297 from thaJeztah/22.06_backport_windows_bits

[22.06 backport] windows cleanups
This commit is contained in:
Sebastiaan van Stijn 2022-10-21 02:44:02 +02:00 committed by GitHub
commit 28c34259c7
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 59 additions and 84 deletions

View file

@ -10,7 +10,6 @@ import (
"os/exec"
"path/filepath"
"time"
"unsafe"
"github.com/sirupsen/logrus"
"github.com/spf13/pflag"
@ -27,9 +26,8 @@ var (
flUnregisterService *bool
flRunService *bool
setStdHandle = windows.NewLazySystemDLL("kernel32.dll").NewProc("SetStdHandle")
oldStderr windows.Handle
panicFile *os.File
oldStderr windows.Handle
panicFile *os.File
service *handler
)
@ -188,35 +186,14 @@ func registerService() error {
}
defer s.Close()
// See http://stackoverflow.com/questions/35151052/how-do-i-configure-failure-actions-of-a-windows-service-written-in-go
const (
scActionNone = 0
scActionRestart = 1
scActionReboot = 2
scActionRunCommand = 3
serviceConfigFailureActions = 2
err = s.SetRecoveryActions(
[]mgr.RecoveryAction{
{Type: mgr.ServiceRestart, Delay: 15 * time.Second},
{Type: mgr.ServiceRestart, Delay: 15 * time.Second},
{Type: mgr.NoAction},
},
uint32(24*time.Hour/time.Second),
)
type serviceFailureActions struct {
ResetPeriod uint32
RebootMsg *uint16
Command *uint16
ActionsCount uint32
Actions uintptr
}
type scAction struct {
Type uint32
Delay uint32
}
t := []scAction{
{Type: scActionRestart, Delay: uint32(60 * time.Second / time.Millisecond)},
{Type: scActionRestart, Delay: uint32(60 * time.Second / time.Millisecond)},
{Type: scActionNone},
}
lpInfo := serviceFailureActions{ResetPeriod: uint32(24 * time.Hour / time.Second), ActionsCount: uint32(3), Actions: uintptr(unsafe.Pointer(&t[0]))}
err = windows.ChangeServiceConfig2(s.Handle, serviceConfigFailureActions, (*byte)(unsafe.Pointer(&lpInfo)))
if err != nil {
return err
}
@ -264,7 +241,8 @@ func initService(daemonCli *DaemonCli) (bool, bool, error) {
return false, false, nil
}
interactive, err := svc.IsAnInteractiveSession()
// Check if we're running as a Windows service or interactively.
isService, err := svc.IsWindowsService()
if err != nil {
return false, false, err
}
@ -276,7 +254,7 @@ func initService(daemonCli *DaemonCli) (bool, bool, error) {
}
var log *eventlog.Log
if !interactive {
if isService {
log, err = eventlog.Open(*flServiceName)
if err != nil {
return false, false, err
@ -288,10 +266,10 @@ func initService(daemonCli *DaemonCli) (bool, bool, error) {
service = h
go func() {
if interactive {
err = debug.Run(*flServiceName, h)
} else {
if isService {
err = svc.Run(*flServiceName, h)
} else {
err = debug.Run(*flServiceName, h)
}
h.fromsvc <- err
@ -387,21 +365,19 @@ func initPanicFile(path string) error {
// Update STD_ERROR_HANDLE to point to the panic file so that Go writes to
// it when it panics. Remember the old stderr to restore it before removing
// the panic file.
sh := uint32(windows.STD_ERROR_HANDLE)
h, err := windows.GetStdHandle(sh)
h, err := windows.GetStdHandle(windows.STD_ERROR_HANDLE)
if err != nil {
return err
}
oldStderr = h
err = windows.SetStdHandle(windows.STD_ERROR_HANDLE, windows.Handle(panicFile.Fd()))
if err != nil {
return err
}
oldStderr = h
r, _, err := setStdHandle.Call(uintptr(sh), uintptr(panicFile.Fd()))
if r == 0 && err != nil {
return err
}
// Reset os.Stderr to the panic file (so fmt.Fprintf(os.Stderr,...) actually gets redirected)
os.Stderr = os.NewFile(uintptr(panicFile.Fd()), "/dev/stderr")
os.Stderr = os.NewFile(panicFile.Fd(), "/dev/stderr")
// Force threads that panic to write to stderr (the panicFile handle now), otherwise it will go into the ether
log.SetOutput(os.Stderr)
@ -412,8 +388,7 @@ func initPanicFile(path string) error {
func removePanicFile() {
if st, err := panicFile.Stat(); err == nil {
if st.Size() == 0 {
sh := uint32(windows.STD_ERROR_HANDLE)
setStdHandle.Call(uintptr(sh), uintptr(oldStderr))
windows.SetStdHandle(windows.STD_ERROR_HANDLE, oldStderr)
panicFile.Close()
os.Remove(panicFile.Name())
}

View file

@ -16,12 +16,11 @@ import (
"strconv"
"strings"
"sync"
"syscall"
"time"
"unsafe"
winio "github.com/Microsoft/go-winio"
"github.com/Microsoft/go-winio/backuptar"
winiofs "github.com/Microsoft/go-winio/pkg/fs"
"github.com/Microsoft/go-winio/vhd"
"github.com/Microsoft/hcsshim"
"github.com/Microsoft/hcsshim/osversion"
@ -100,7 +99,7 @@ type Driver struct {
func InitFilter(home string, options []string, _ idtools.IdentityMapping) (graphdriver.Driver, error) {
logrus.Debugf("WindowsGraphDriver InitFilter at %s", home)
fsType, err := getFileSystemType(string(home[0]))
fsType, err := winiofs.GetFileSystemType(home)
if err != nil {
return nil, err
}
@ -137,37 +136,6 @@ func InitFilter(home string, options []string, _ idtools.IdentityMapping) (graph
return d, nil
}
// win32FromHresult is a helper function to get the win32 error code from an HRESULT
func win32FromHresult(hr uintptr) uintptr {
if hr&0x1fff0000 == 0x00070000 {
return hr & 0xffff
}
return hr
}
// getFileSystemType obtains the type of a file system through GetVolumeInformation
// https://msdn.microsoft.com/en-us/library/windows/desktop/aa364993(v=vs.85).aspx
func getFileSystemType(drive string) (fsType string, hr error) {
var (
modkernel32 = windows.NewLazySystemDLL("kernel32.dll")
procGetVolumeInformation = modkernel32.NewProc("GetVolumeInformationW")
buf = make([]uint16, 255)
size = windows.MAX_PATH + 1
)
if len(drive) != 1 {
hr = errors.New("getFileSystemType must be called with a drive letter")
return
}
drive += `:\`
n := uintptr(unsafe.Pointer(nil))
r0, _, _ := syscall.Syscall9(procGetVolumeInformation.Addr(), 8, uintptr(unsafe.Pointer(windows.StringToUTF16Ptr(drive))), n, n, n, n, n, uintptr(unsafe.Pointer(&buf[0])), uintptr(size), 0)
if int32(r0) < 0 {
hr = syscall.Errno(win32FromHresult(r0))
}
fsType = windows.UTF16ToString(buf)
return
}
// String returns the string representation of a driver. This should match
// the name the graph driver has been registered with.
func (d *Driver) String() string {
@ -346,7 +314,6 @@ func (d *Driver) Remove(id string) error {
if err != nil {
return err
}
defer container.Close()
err = container.Terminate()
if hcsshim.IsPending(err) {
err = container.Wait()
@ -354,6 +321,7 @@ func (d *Driver) Remove(id string) error {
err = nil
}
_ = container.Close()
if err != nil {
return err
}

View file

@ -0,0 +1,31 @@
package fs
import (
"errors"
"path/filepath"
"golang.org/x/sys/windows"
)
var (
// ErrInvalidPath is returned when the location of a file path doesn't begin with a driver letter.
ErrInvalidPath = errors.New("the path provided to GetFileSystemType must start with a drive letter")
)
// GetFileSystemType obtains the type of a file system through GetVolumeInformation.
// https://msdn.microsoft.com/en-us/library/windows/desktop/aa364993(v=vs.85).aspx
func GetFileSystemType(path string) (fsType string, err error) {
drive := filepath.VolumeName(path)
if len(drive) != 2 {
return "", ErrInvalidPath
}
var (
buf = make([]uint16, 255)
size = uint32(windows.MAX_PATH + 1)
)
drive += `\`
err = windows.GetVolumeInformation(windows.StringToUTF16Ptr(drive), nil, 0, nil, nil, nil, &buf[0], size)
fsType = windows.UTF16ToString(buf)
return
}

1
vendor/modules.txt vendored
View file

@ -24,6 +24,7 @@ github.com/Microsoft/go-winio
github.com/Microsoft/go-winio/backuptar
github.com/Microsoft/go-winio/pkg/etw
github.com/Microsoft/go-winio/pkg/etwlogrus
github.com/Microsoft/go-winio/pkg/fs
github.com/Microsoft/go-winio/pkg/guid
github.com/Microsoft/go-winio/pkg/security
github.com/Microsoft/go-winio/vhd