diff options
author | Frédéric Guillot <fred@miniflux.net> | 2018-07-06 21:18:14 -0700 |
---|---|---|
committer | Frédéric Guillot <fred@miniflux.net> | 2018-07-06 21:18:14 -0700 |
commit | 459bb4531f92f8663afb6f36aa9be5b789bd591f (patch) | |
tree | f14e6c06b8e5c63612d1ff36f8cab40ae8a99d20 /vendor/golang.org/x/sys/windows/svc | |
parent | 34a3fe426b33a63f2d8e02d4a70c88f137fa5410 (diff) |
Update vendor dependencies
Diffstat (limited to 'vendor/golang.org/x/sys/windows/svc')
8 files changed, 224 insertions, 22 deletions
diff --git a/vendor/golang.org/x/sys/windows/svc/debug/service.go b/vendor/golang.org/x/sys/windows/svc/debug/service.go index 123df98..e621b87 100644 --- a/vendor/golang.org/x/sys/windows/svc/debug/service.go +++ b/vendor/golang.org/x/sys/windows/svc/debug/service.go @@ -31,7 +31,7 @@ func Run(name string, handler svc.Handler) error { for { select { case <-sig: - cmds <- svc.ChangeRequest{svc.Stop, 0, 0, status} + cmds <- svc.ChangeRequest{Cmd: svc.Stop, CurrentStatus: status} case status = <-changes: } } diff --git a/vendor/golang.org/x/sys/windows/svc/example/service.go b/vendor/golang.org/x/sys/windows/svc/example/service.go index 237e809..74c9393 100644 --- a/vendor/golang.org/x/sys/windows/svc/example/service.go +++ b/vendor/golang.org/x/sys/windows/svc/example/service.go @@ -8,6 +8,7 @@ package main import ( "fmt" + "strings" "time" "golang.org/x/sys/windows/svc" @@ -26,6 +27,7 @@ func (m *myservice) Execute(args []string, r <-chan svc.ChangeRequest, changes c slowtick := time.Tick(2 * time.Second) tick := fasttick changes <- svc.Status{State: svc.Running, Accepts: cmdsAccepted} + elog.Info(1, strings.Join(args, "-")) loop: for { select { diff --git a/vendor/golang.org/x/sys/windows/svc/mgr/config.go b/vendor/golang.org/x/sys/windows/svc/mgr/config.go index 0a6edba..d804e31 100644 --- a/vendor/golang.org/x/sys/windows/svc/mgr/config.go +++ b/vendor/golang.org/x/sys/windows/svc/mgr/config.go @@ -88,23 +88,11 @@ func (s *Service) Config() (Config, error) { } } - var p2 *windows.SERVICE_DESCRIPTION - n = uint32(1024) - for { - b := make([]byte, n) - p2 = (*windows.SERVICE_DESCRIPTION)(unsafe.Pointer(&b[0])) - err := windows.QueryServiceConfig2(s.Handle, - windows.SERVICE_CONFIG_DESCRIPTION, &b[0], n, &n) - if err == nil { - break - } - if err.(syscall.Errno) != syscall.ERROR_INSUFFICIENT_BUFFER { - return Config{}, err - } - if n <= uint32(len(b)) { - return Config{}, err - } + b, err := s.queryServiceConfig2(windows.SERVICE_CONFIG_DESCRIPTION) + if err != nil { + return Config{}, err } + p2 := (*windows.SERVICE_DESCRIPTION)(unsafe.Pointer(&b[0])) return Config{ ServiceType: p.ServiceType, @@ -121,7 +109,7 @@ func (s *Service) Config() (Config, error) { } func updateDescription(handle windows.Handle, desc string) error { - d := windows.SERVICE_DESCRIPTION{toPtr(desc)} + d := windows.SERVICE_DESCRIPTION{Description: toPtr(desc)} return windows.ChangeServiceConfig2(handle, windows.SERVICE_CONFIG_DESCRIPTION, (*byte)(unsafe.Pointer(&d))) } @@ -137,3 +125,21 @@ func (s *Service) UpdateConfig(c Config) error { } return updateDescription(s.Handle, c.Description) } + +// queryServiceConfig2 calls Windows QueryServiceConfig2 with infoLevel parameter and returns retrieved service configuration information. +func (s *Service) queryServiceConfig2(infoLevel uint32) ([]byte, error) { + n := uint32(1024) + for { + b := make([]byte, n) + err := windows.QueryServiceConfig2(s.Handle, infoLevel, &b[0], n, &n) + if err == nil { + return b, nil + } + if err.(syscall.Errno) != syscall.ERROR_INSUFFICIENT_BUFFER { + return nil, err + } + if n <= uint32(len(b)) { + return nil, err + } + } +} diff --git a/vendor/golang.org/x/sys/windows/svc/mgr/mgr_test.go b/vendor/golang.org/x/sys/windows/svc/mgr/mgr_test.go index 1569a22..13f1f38 100644 --- a/vendor/golang.org/x/sys/windows/svc/mgr/mgr_test.go +++ b/vendor/golang.org/x/sys/windows/svc/mgr/mgr_test.go @@ -95,6 +95,85 @@ func testConfig(t *testing.T, s *mgr.Service, should mgr.Config) mgr.Config { return is } +func testRecoveryActions(t *testing.T, s *mgr.Service, should []mgr.RecoveryAction) { + is, err := s.RecoveryActions() + if err != nil { + t.Fatalf("RecoveryActions failed: %s", err) + } + if len(should) != len(is) { + t.Errorf("recovery action mismatch: contains %v actions, but should have %v", len(is), len(should)) + } + for i, _ := range is { + if should[i].Type != is[i].Type { + t.Errorf("recovery action mismatch: Type is %v, but should have %v", is[i].Type, should[i].Type) + } + if should[i].Delay != is[i].Delay { + t.Errorf("recovery action mismatch: Delay is %v, but should have %v", is[i].Delay, should[i].Delay) + } + } +} + +func testResetPeriod(t *testing.T, s *mgr.Service, should uint32) { + is, err := s.ResetPeriod() + if err != nil { + t.Fatalf("ResetPeriod failed: %s", err) + } + if should != is { + t.Errorf("reset period mismatch: reset period is %v, but should have %v", is, should) + } +} + +func testSetRecoveryActions(t *testing.T, s *mgr.Service) { + r := []mgr.RecoveryAction{ + mgr.RecoveryAction{ + Type: mgr.NoAction, + Delay: 60000 * time.Millisecond, + }, + mgr.RecoveryAction{ + Type: mgr.ServiceRestart, + Delay: 4 * time.Minute, + }, + mgr.RecoveryAction{ + Type: mgr.ServiceRestart, + Delay: time.Minute, + }, + mgr.RecoveryAction{ + Type: mgr.RunCommand, + Delay: 4000 * time.Millisecond, + }, + } + + // 4 recovery actions with reset period + err := s.SetRecoveryActions(r, uint32(10000)) + if err != nil { + t.Fatalf("SetRecoveryActions failed: %v", err) + } + testRecoveryActions(t, s, r) + testResetPeriod(t, s, uint32(10000)) + + // Infinite reset period + err = s.SetRecoveryActions(r, syscall.INFINITE) + if err != nil { + t.Fatalf("SetRecoveryActions failed: %v", err) + } + testRecoveryActions(t, s, r) + testResetPeriod(t, s, syscall.INFINITE) + + // nil recovery actions + err = s.SetRecoveryActions(nil, 0) + if err.Error() != "recoveryActions cannot be nil" { + t.Fatalf("SetRecoveryActions failed with unexpected error message of %q", err) + } + + // Delete all recovery actions and reset period + err = s.ResetRecoveryActions() + if err != nil { + t.Fatalf("ResetRecoveryActions failed: %v", err) + } + testRecoveryActions(t, s, nil) + testResetPeriod(t, s, 0) +} + func remove(t *testing.T, s *mgr.Service) { err := s.Delete() if err != nil { @@ -165,5 +244,7 @@ func TestMyService(t *testing.T) { t.Errorf("ListServices failed to find %q service", name) } + testSetRecoveryActions(t, s) + remove(t, s) } diff --git a/vendor/golang.org/x/sys/windows/svc/mgr/recovery.go b/vendor/golang.org/x/sys/windows/svc/mgr/recovery.go new file mode 100644 index 0000000..9243dca --- /dev/null +++ b/vendor/golang.org/x/sys/windows/svc/mgr/recovery.go @@ -0,0 +1,96 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build windows + +package mgr + +import ( + "errors" + "time" + "unsafe" + + "golang.org/x/sys/windows" +) + +const ( + // Possible recovery actions that the service control manager can perform. + NoAction = windows.SC_ACTION_NONE // no action + ComputerReboot = windows.SC_ACTION_REBOOT // reboot the computer + ServiceRestart = windows.SC_ACTION_RESTART // restart the service + RunCommand = windows.SC_ACTION_RUN_COMMAND // run a command +) + +// RecoveryAction represents an action that the service control manager can perform when service fails. +// A service is considered failed when it terminates without reporting a status of SERVICE_STOPPED to the service controller. +type RecoveryAction struct { + Type int // one of NoAction, ComputerReboot, ServiceRestart or RunCommand + Delay time.Duration // the time to wait before performing the specified action +} + +// SetRecoveryActions sets actions that service controller performs when service fails and +// the time after which to reset the service failure count to zero if there are no failures, in seconds. +// Specify INFINITE to indicate that service failure count should never be reset. +func (s *Service) SetRecoveryActions(recoveryActions []RecoveryAction, resetPeriod uint32) error { + if recoveryActions == nil { + return errors.New("recoveryActions cannot be nil") + } + actions := []windows.SC_ACTION{} + for _, a := range recoveryActions { + action := windows.SC_ACTION{ + Type: uint32(a.Type), + Delay: uint32(a.Delay.Nanoseconds() / 1000000), + } + actions = append(actions, action) + } + rActions := windows.SERVICE_FAILURE_ACTIONS{ + ActionsCount: uint32(len(actions)), + Actions: &actions[0], + ResetPeriod: resetPeriod, + } + return windows.ChangeServiceConfig2(s.Handle, windows.SERVICE_CONFIG_FAILURE_ACTIONS, (*byte)(unsafe.Pointer(&rActions))) +} + +// RecoveryActions returns actions that service controller performs when service fails. +// The service control manager counts the number of times service s has failed since the system booted. +// The count is reset to 0 if the service has not failed for ResetPeriod seconds. +// When the service fails for the Nth time, the service controller performs the action specified in element [N-1] of returned slice. +// If N is greater than slice length, the service controller repeats the last action in the slice. +func (s *Service) RecoveryActions() ([]RecoveryAction, error) { + b, err := s.queryServiceConfig2(windows.SERVICE_CONFIG_FAILURE_ACTIONS) + if err != nil { + return nil, err + } + p := (*windows.SERVICE_FAILURE_ACTIONS)(unsafe.Pointer(&b[0])) + if p.Actions == nil { + return nil, err + } + + var recoveryActions []RecoveryAction + actions := (*[1024]windows.SC_ACTION)(unsafe.Pointer(p.Actions))[:p.ActionsCount] + for _, action := range actions { + recoveryActions = append(recoveryActions, RecoveryAction{Type: int(action.Type), Delay: time.Duration(action.Delay) * time.Millisecond}) + } + return recoveryActions, nil +} + +// ResetRecoveryActions deletes both reset period and array of failure actions. +func (s *Service) ResetRecoveryActions() error { + actions := make([]windows.SC_ACTION, 1) + rActions := windows.SERVICE_FAILURE_ACTIONS{ + Actions: &actions[0], + } + return windows.ChangeServiceConfig2(s.Handle, windows.SERVICE_CONFIG_FAILURE_ACTIONS, (*byte)(unsafe.Pointer(&rActions))) +} + +// ResetPeriod is the time after which to reset the service failure +// count to zero if there are no failures, in seconds. +func (s *Service) ResetPeriod() (uint32, error) { + b, err := s.queryServiceConfig2(windows.SERVICE_CONFIG_FAILURE_ACTIONS) + if err != nil { + return 0, err + } + p := (*windows.SERVICE_FAILURE_ACTIONS)(unsafe.Pointer(&b[0])) + return p.ResetPeriod, nil +} diff --git a/vendor/golang.org/x/sys/windows/svc/service.go b/vendor/golang.org/x/sys/windows/svc/service.go index 903cba3..cda26b5 100644 --- a/vendor/golang.org/x/sys/windows/svc/service.go +++ b/vendor/golang.org/x/sys/windows/svc/service.go @@ -334,8 +334,8 @@ func Run(name string, handler Handler) error { var svcmain uintptr getServiceMain(&svcmain) t := []windows.SERVICE_TABLE_ENTRY{ - {syscall.StringToUTF16Ptr(s.name), svcmain}, - {nil, 0}, + {ServiceName: syscall.StringToUTF16Ptr(s.name), ServiceProc: svcmain}, + {ServiceName: nil, ServiceProc: 0}, } goWaitsH = uintptr(s.goWaits.h) diff --git a/vendor/golang.org/x/sys/windows/svc/svc_test.go b/vendor/golang.org/x/sys/windows/svc/svc_test.go index da7ec66..60eb447 100644 --- a/vendor/golang.org/x/sys/windows/svc/svc_test.go +++ b/vendor/golang.org/x/sys/windows/svc/svc_test.go @@ -7,10 +7,13 @@ package svc_test import ( + "fmt" "io/ioutil" + "math/rand" "os" "os/exec" "path/filepath" + "strings" "testing" "time" @@ -86,8 +89,10 @@ func TestExample(t *testing.T) { } defer s.Close() + args := []string{"is", "manual-started", fmt.Sprintf("%d", rand.Int())} + testState(t, s, svc.Stopped) - err = s.Start("is", "manual-started") + err = s.Start(args...) if err != nil { t.Fatalf("Start(%s) failed: %s", s.Name, err) } @@ -115,4 +120,16 @@ func TestExample(t *testing.T) { if err != nil { t.Fatalf("Delete failed: %s", err) } + + cmd := `Get-Eventlog -LogName Application -Newest 100` + + ` | Where Source -eq "myservice"` + + ` | Select -first 10` + + ` | Format-table -HideTableHeaders -property ReplacementStrings` + out, err := exec.Command("powershell", "-Command", cmd).CombinedOutput() + if err != nil { + t.Fatalf("powershell failed: %v\n%v", err, string(out)) + } + if want := strings.Join(append([]string{name}, args...), "-"); !strings.Contains(string(out), want) { + t.Errorf("%q string does not contain %q", string(out), want) + } } diff --git a/vendor/golang.org/x/sys/windows/svc/sys_amd64.s b/vendor/golang.org/x/sys/windows/svc/sys_amd64.s index 06b4259..bde25e9 100644 --- a/vendor/golang.org/x/sys/windows/svc/sys_amd64.s +++ b/vendor/golang.org/x/sys/windows/svc/sys_amd64.s @@ -7,7 +7,7 @@ // func servicemain(argc uint32, argv **uint16) TEXT ·servicemain(SB),7,$0 MOVL CX, ·sArgc(SB) - MOVL DX, ·sArgv(SB) + MOVQ DX, ·sArgv(SB) SUBQ $32, SP // stack for the first 4 syscall params |