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
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
package devsup
import (
"errors"
"log/slog"
"syscall"
"time"
"github.com/johnandersen777/socialweb-computer-kcp/internal/hostsvc"
)
const (
EnvUnit = "SWC_UNIT"
EnvDevsup = "SWC_DEVSUP"
EnvInvocation = "INVOCATION_ID"
EnvInstance = "SWC_INSTANCE"
)
const (
EnvNotifySocket = "NOTIFY_SOCKET"
EnvListenFDs = "LISTEN_FDS"
EnvListenNames = "LISTEN_FDNAMES"
)
const (
DefaultStopTimeout = 30 * time.Second
RestartDelay = 100 * time.Millisecond
StartLimitBurst = 5
StartLimitInterval = 10 * time.Second
OrphanScanInterval = time.Second
ExitStatusExec = 203
CodeExited = 1
CodeKilled = 2
CodeDumped = 3
)
type Options struct {
State string
Socket string
DieWith int
Instance string
Log *slog.Logger
}
type Record struct {
Spec hostsvc.UnitSpec `json:"spec"`
Status hostsvc.UnitStatus `json:"status"`
PGID int `json:"pgid"`
LeaderTicks uint64 `json:"leaderTicks"`
BootID string `json:"bootID"`
Devsup string `json:"devsup"`
Order int `json:"order"`
}
type ProcEntry struct {
PID int
PGID int
Ticks uint64
}
type SweepVerdict int
const (
SweepNothing SweepVerdict = iota
SweepGroup
SweepRefuseReused
)
type SweepReport struct {
Unit string `json:"unit"`
PGID int `json:"pgid"`
Verdict string `json:"verdict"`
}
var errGone = errors.New("the process is gone")
func (v SweepVerdict) String() string {
switch v {
case SweepGroup:
return "signal the group"
case SweepRefuseReused:
return "refused: the leader pid was reused"
}
return "nothing left"
}
func SweepDecision(rec Record, table []ProcEntry) SweepVerdict {
if rec.PGID <= 0 {
return SweepNothing
}
members := 0
for _, p := range table {
if p.PID == rec.PGID {
if p.Ticks == rec.LeaderTicks {
return SweepGroup
}
return SweepRefuseReused
}
if p.PGID == rec.PGID {
members++
}
}
if members > 0 {
return SweepGroup
}
return SweepNothing
}
func CleanSignal(sig syscall.Signal) bool {
switch sig {
case syscall.SIGTERM, syscall.SIGINT, syscall.SIGHUP, syscall.SIGPIPE:
return true
}
return false
}