Drop the never-ran reading: a start timestamp of 0 does not mean a one-shot never ran (issue 1126)
mesh/delivery merged: source.main moved to novox/mesh-host@b4fd2cc210bf
mesh/check being carried to 1a021052fe07 on b4fd2cc210bf | from 7a2af2376405
mesh/delivery merged: source.main moved to novox/mesh-host@b4fd2cc210bf
mesh/check being carried to 1a021052fe07 on b4fd2cc210bf | from 7a2af2376405
Review round 1 measured it on systemd 262.1: a finished one-shot nothing references is unloaded, and loaded again it reads inactive, ExecMainStatus=0 and a start timestamp of 0, as one that never ran does. The previous commit's rule read such a unit stopped, so a one-shot declared running would be started, read stopped and fail on every apply, and the hold, the take-over and the giving back would judge it wrongly. ServiceState keeps main's reading. ServiceAtRest and declaredState stay: they alone satisfy a stopped declaration for a one-shot at rest, which is the kernel cleanup's case. A one-shot declared running that must be seen to have run lingers (RemainAfterExit) or is enabled at boot. Unit tests: the arch table has 5 rows, the apply test 1; 1262 in all.
This commit is contained in:
+7
-14
@@ -217,16 +217,12 @@ func (arch) ServiceState(ctx context.Context, run Runner, unit string) (string,
|
||||
//
|
||||
// So for that shape, what "running" means is "it ran, and it worked".
|
||||
//
|
||||
// **And one that never ran is not one that worked** (novox/hq issue 1126). systemd says
|
||||
// ExecMainStatus=0 for a unit that has not run since the manager loaded it exactly as for one
|
||||
// that succeeded; only its start timestamp, 0, separates them. Read as "running", a package's
|
||||
// boot-time one-shot declared stopped could never be satisfied — stopping an inactive unit
|
||||
// changes nothing, and the read back said running again — and one declared running was never
|
||||
// started. A timestamp the manager did not say keeps the reading it had before.
|
||||
// It cannot be told from one that never ran: systemd says ExecMainStatus=0 and a start timestamp
|
||||
// of 0 for a one-shot that never ran, and also for one that ran and was unloaded because nothing
|
||||
// referenced it, then loaded again. So a one-shot declared running that must be seen to have run
|
||||
// lingers (RemainAfterExit) or is enabled at boot; one declared stopped is judged at rest by the
|
||||
// apply (ServiceAtRest, novox/hq issue 1126).
|
||||
if u.oneShotAtRest() {
|
||||
if u.started == "0" {
|
||||
return "stopped", nil
|
||||
}
|
||||
if u.exited == "0" || u.exited == "" {
|
||||
return "running", nil
|
||||
}
|
||||
@@ -259,7 +255,7 @@ func (arch) ServiceAtRest(ctx context.Context, run Runner, unit string) (bool, e
|
||||
|
||||
// shownUnit is what `systemctl show` says of a unit, as far as its state is read.
|
||||
type shownUnit struct {
|
||||
load, active, kind, remains, exited, started string
|
||||
load, active, kind, remains, exited string
|
||||
}
|
||||
|
||||
// oneShotAtRest is a one-shot that does not linger and is not running now.
|
||||
@@ -273,8 +269,7 @@ func (u shownUnit) oneShotAtRest() bool {
|
||||
func showUnit(ctx context.Context, run Runner, unit string) (shownUnit, error) {
|
||||
out, asked := run(ctx, "systemctl", "show",
|
||||
"--property=LoadState", "--property=ActiveState", "--property=Type",
|
||||
"--property=RemainAfterExit", "--property=ExecMainStatus",
|
||||
"--property=ExecMainStartTimestampMonotonic", "--", unit)
|
||||
"--property=RemainAfterExit", "--property=ExecMainStatus", "--", unit)
|
||||
var u shownUnit
|
||||
for _, line := range strings.Split(out, "\n") {
|
||||
key, value, found := strings.Cut(strings.TrimSpace(line), "=")
|
||||
@@ -292,8 +287,6 @@ func showUnit(ctx context.Context, run Runner, unit string) (shownUnit, error) {
|
||||
u.remains = value
|
||||
case "ExecMainStatus":
|
||||
u.exited = value
|
||||
case "ExecMainStartTimestampMonotonic":
|
||||
u.started = value
|
||||
}
|
||||
}
|
||||
if u.load == "" {
|
||||
|
||||
Reference in New Issue
Block a user