mirror of
https://github.com/golang/sys.git
synced 2026-02-09 04:06:04 +03:00
Second argument of servicemain is a pointer. See https://msdn.microsoft.com/en-us/library/windows/desktop/ms685138(v=vs.85).aspx So amd64 assembler code should use MOVQ to read that value. I probably copied 386 assembler code into amd64 and did not adjust the code. Broken code was used to pass parameters to the service, so add some tests to verify that parameter passing works. Fixes golang/go#24575 Change-Id: I89f8cad026ea13f8a5d78ff3e24b7236e27fc91f Reviewed-on: https://go-review.googlesource.com/110160 Run-TryBot: Alex Brainman <alex.brainman@gmail.com> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
136 lines
3.2 KiB
Go
136 lines
3.2 KiB
Go
// Copyright 2012 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 svc_test
|
|
|
|
import (
|
|
"fmt"
|
|
"io/ioutil"
|
|
"math/rand"
|
|
"os"
|
|
"os/exec"
|
|
"path/filepath"
|
|
"strings"
|
|
"testing"
|
|
"time"
|
|
|
|
"golang.org/x/sys/windows/svc"
|
|
"golang.org/x/sys/windows/svc/mgr"
|
|
)
|
|
|
|
func getState(t *testing.T, s *mgr.Service) svc.State {
|
|
status, err := s.Query()
|
|
if err != nil {
|
|
t.Fatalf("Query(%s) failed: %s", s.Name, err)
|
|
}
|
|
return status.State
|
|
}
|
|
|
|
func testState(t *testing.T, s *mgr.Service, want svc.State) {
|
|
have := getState(t, s)
|
|
if have != want {
|
|
t.Fatalf("%s state is=%d want=%d", s.Name, have, want)
|
|
}
|
|
}
|
|
|
|
func waitState(t *testing.T, s *mgr.Service, want svc.State) {
|
|
for i := 0; ; i++ {
|
|
have := getState(t, s)
|
|
if have == want {
|
|
return
|
|
}
|
|
if i > 10 {
|
|
t.Fatalf("%s state is=%d, waiting timeout", s.Name, have)
|
|
}
|
|
time.Sleep(300 * time.Millisecond)
|
|
}
|
|
}
|
|
|
|
func TestExample(t *testing.T) {
|
|
if testing.Short() {
|
|
t.Skip("skipping test in short mode - it modifies system services")
|
|
}
|
|
|
|
const name = "myservice"
|
|
|
|
m, err := mgr.Connect()
|
|
if err != nil {
|
|
t.Fatalf("SCM connection failed: %s", err)
|
|
}
|
|
defer m.Disconnect()
|
|
|
|
dir, err := ioutil.TempDir("", "svc")
|
|
if err != nil {
|
|
t.Fatalf("failed to create temp directory: %v", err)
|
|
}
|
|
defer os.RemoveAll(dir)
|
|
|
|
exepath := filepath.Join(dir, "a.exe")
|
|
o, err := exec.Command("go", "build", "-o", exepath, "golang.org/x/sys/windows/svc/example").CombinedOutput()
|
|
if err != nil {
|
|
t.Fatalf("failed to build service program: %v\n%v", err, string(o))
|
|
}
|
|
|
|
s, err := m.OpenService(name)
|
|
if err == nil {
|
|
err = s.Delete()
|
|
if err != nil {
|
|
s.Close()
|
|
t.Fatalf("Delete failed: %s", err)
|
|
}
|
|
s.Close()
|
|
}
|
|
s, err = m.CreateService(name, exepath, mgr.Config{DisplayName: "my service"}, "is", "auto-started")
|
|
if err != nil {
|
|
t.Fatalf("CreateService(%s) failed: %v", name, err)
|
|
}
|
|
defer s.Close()
|
|
|
|
args := []string{"is", "manual-started", fmt.Sprintf("%d", rand.Int())}
|
|
|
|
testState(t, s, svc.Stopped)
|
|
err = s.Start(args...)
|
|
if err != nil {
|
|
t.Fatalf("Start(%s) failed: %s", s.Name, err)
|
|
}
|
|
waitState(t, s, svc.Running)
|
|
time.Sleep(1 * time.Second)
|
|
|
|
// testing deadlock from issues 4.
|
|
_, err = s.Control(svc.Interrogate)
|
|
if err != nil {
|
|
t.Fatalf("Control(%s) failed: %s", s.Name, err)
|
|
}
|
|
_, err = s.Control(svc.Interrogate)
|
|
if err != nil {
|
|
t.Fatalf("Control(%s) failed: %s", s.Name, err)
|
|
}
|
|
time.Sleep(1 * time.Second)
|
|
|
|
_, err = s.Control(svc.Stop)
|
|
if err != nil {
|
|
t.Fatalf("Control(%s) failed: %s", s.Name, err)
|
|
}
|
|
waitState(t, s, svc.Stopped)
|
|
|
|
err = s.Delete()
|
|
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)
|
|
}
|
|
}
|