@marcel91200 / caddy Mirror · read-only / commits / 409a0721
Fork 0

Fast and extensible multi-platform HTTP/1-2-3 web server with automatic HTTPS

Mirrored from https://github.com/Slazee/caddy.git

Synced Nov 11, 17:15 UTC

notify: implement windows service status and error notifications (#7389)

* implement service status and error notifications * adjust return of Error function * configure accepts on status * align windows with linux semantics

EINIER FREYRE CORONA committed Dec 12, 2025 at 12:56 UTC 409a0721354354a2d13e5c110be0f7f03363652b
1 file changed +64 -5
notify/notify_windows.go
+64 -5
@@ -14,16 +14,26 @@
14
15 package notify
16
17 -import "golang.org/x/sys/windows/svc"
17 +import (
18 + "log"
19 + "strings"
20 +
21 + "golang.org/x/sys/windows/svc"
22 +)
23
24 // globalStatus store windows service status, it can be
25 // use to notify caddy status.
26 var globalStatus chan<- svc.Status
27
28 +// SetGlobalStatus assigns the channel through which status updates
29 +// will be sent to the SCM. This is typically provided by the service
30 +// handler when the service starts.
31 func SetGlobalStatus(status chan<- svc.Status) {
32 globalStatus = status
33 }
34
35 +// Ready notifies the SCM that the service is fully running and ready
36 +// to accept stop or shutdown control requests.
37 func Ready() error {
38 if globalStatus != nil {
39 globalStatus <- svc.Status{
@@ -34,6 +44,8 @@ func Ready() error {
44 return nil
45 }
46
47 +// Reloading notifies the SCM that the service is entering a transitional
48 +// state.
49 func Reloading() error {
50 if globalStatus != nil {
51 globalStatus <- svc.Status{State: svc.StartPending}
@@ -41,6 +53,8 @@ func Reloading() error {
53 return nil
54 }
55
56 +// Stopping notifies the SCM that the service is in the process of stopping.
57 +// This allows Windows to track the shutdown transition properly.
58 func Stopping() error {
59 if globalStatus != nil {
60 globalStatus <- svc.Status{State: svc.StopPending}
@@ -48,8 +62,53 @@ func Stopping() error {
62 return nil
63 }
64
51 -// TODO: not implemented
52 -func Status(_ string) error { return nil }
65 +// Status sends an arbitrary service state to the SCM based on a string
66 +// identifier of [svc.State].
67 +// The unknown states will be logged.
68 +func Status(name string) error {
69 + if globalStatus == nil {
70 + return nil
71 + }
72 +
73 + var state svc.State
74 + var accepts svc.Accepted
75 + accepts = 0
76 +
77 + switch strings.ToLower(name) {
78 + case "stopped":
79 + state = svc.Stopped
80 + case "start_pending":
81 + state = svc.StartPending
82 + case "stop_pending":
83 + state = svc.StopPending
84 + case "running":
85 + state = svc.Running
86 + accepts = svc.AcceptStop | svc.AcceptShutdown
87 + case "continue_pending":
88 + state = svc.ContinuePending
89 + case "pause_pending":
90 + state = svc.PausePending
91 + case "paused":
92 + state = svc.Paused
93 + accepts = svc.AcceptStop | svc.AcceptShutdown | svc.AcceptPauseAndContinue
94 + default:
95 + log.Printf("unknown state: %s", name)
96 + return nil
97 + }
98 +
99 + globalStatus <- svc.Status{State: state, Accepts: accepts}
100 + return nil
101 +}
102
54 -// TODO: not implemented
55 -func Error(_ error, _ int) error { return nil }
103 +// Error notifies the SCM that the service is stopping due to a failure,
104 +// including a service-specific exit code.
105 +func Error(err error, code int) error {
106 + if globalStatus != nil {
107 + globalStatus <- svc.Status{
108 + State: svc.StopPending,
109 + ServiceSpecificExitCode: uint32(code),
110 + }
111 + }
112 +
113 + return nil
114 +}