-
-
Notifications
You must be signed in to change notification settings - Fork 779
Expand file tree
/
Copy pathservice_wait.go
More file actions
73 lines (66 loc) · 1.76 KB
/
Copy pathservice_wait.go
File metadata and controls
73 lines (66 loc) · 1.76 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
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
package main
import (
"fmt"
"time"
)
type serviceWaitStatus struct {
state uint32
checkPoint uint32
waitHint uint32
win32ExitCode uint32
serviceSpecificExitCode uint32
}
const (
serviceWaitMinimumInterval = time.Second
serviceWaitMaximumInterval = 10 * time.Second
serviceWaitAbsoluteTimeout = 24 * time.Hour
)
func waitForServiceState(
query func() (serviceWaitStatus, error),
wanted uint32,
stopped uint32,
now func() time.Time,
sleep func(time.Duration),
) error {
startedAt := now()
lastProgressAt := startedAt
lastCheckPoint := uint32(0)
for {
status, err := query()
if err != nil {
return fmt.Errorf("query Windows service state: %w", err)
}
if status.state == wanted {
return nil
}
if wanted != stopped && status.state == stopped {
return fmt.Errorf(
"Windows service stopped during startup with exit code %d/%d",
status.win32ExitCode,
status.serviceSpecificExitCode,
)
}
currentTime := now()
if currentTime.Sub(startedAt) > serviceWaitAbsoluteTimeout {
return fmt.Errorf("timed out waiting for Windows service state %d", wanted)
}
waitHint := time.Duration(status.waitHint) * time.Millisecond
if waitHint < serviceWaitMinimumInterval {
waitHint = serviceWaitMinimumInterval
}
if status.checkPoint > lastCheckPoint {
lastCheckPoint = status.checkPoint
lastProgressAt = currentTime
} else if currentTime.Sub(lastProgressAt) > waitHint {
return fmt.Errorf("timed out waiting for Windows service state %d", wanted)
}
interval := waitHint / 10
if interval < serviceWaitMinimumInterval {
interval = serviceWaitMinimumInterval
}
if interval > serviceWaitMaximumInterval {
interval = serviceWaitMaximumInterval
}
sleep(interval)
}
}