1package sdnotify
2
3import (
4 "fmt"
5 "math"
6 "net"
7 "os"
8 "strconv"
9 "time"
10)
11
12const (
13 SocketEnv = "NOTIFY_SOCKET"
14 WatchdogUsecEnv = "WATCHDOG_USEC"
15 WatchdogPIDEnv = "WATCHDOG_PID"
16)
17
18const (
19 Ready = "READY=1"
20 Stopping = "STOPPING=1"
21 Watchdog = "WATCHDOG=1"
22)
23
24func WatchdogInterval() (time.Duration, bool) {
25 usec, err := strconv.ParseInt(os.Getenv(WatchdogUsecEnv), 10, 64)
26 if err != nil || usec <= 0 || usec > math.MaxInt64/int64(time.Microsecond) {
27 return 0, false
28 }
29 if pid := os.Getenv(WatchdogPIDEnv); pid != "" && pid != strconv.Itoa(os.Getpid()) {
30 return 0, false
31 }
32 return time.Duration(usec) * time.Microsecond, true
33}
34
35func Notify(state string) error {
36 name := os.Getenv(SocketEnv)
37 if name == "" {
38 return nil
39 }
40 if name[0] != '/' && name[0] != '@' {
41 return fmt.Errorf("%s=%q is neither an absolute path nor an abstract socket (@name)", SocketEnv, name)
42 }
43 conn, err := net.DialUnix("unixgram", nil, &net.UnixAddr{Name: name, Net: "unixgram"})
44 if err != nil {
45 return fmt.Errorf("notify %s: %w", state, err)
46 }
47 defer conn.Close()
48 if _, err := conn.Write([]byte(state)); err != nil {
49 return fmt.Errorf("notify %s: %w", state, err)
50 }
51 return nil
52}