| index 5279718d8..460c2b8a0 100644 |
| --- a/internal/activator/activator.go |
| +++ b/internal/activator/activator.go |
| @@ -508,9 +508,9 @@ type actEntry struct { |
| // exited, so an intentional stop is never read as a crash (spec §6.4). |
| // Written under a.mu. |
| settleCancel context.CancelFunc |
| - // genReaping is true while reapCurrentGen (or, flag off, |
| - // reapUncontainedStop) is running for this pending stop, so |
| - // finishPendingStops does not start a second one. Written under a.mu. |
| + // genReaping is true while reapCurrentGen is running for this pending |
| + // stop, so finishPendingStops does not start a second one. Written |
| + // under a.mu. |
| genReaping bool |
| // sidecarJoin is a sidecar start a flag-off terminal stop stopped |
| // waiting for (sidecarStartJoinWait) while it was still in flight: the |
| @@ -3574,7 +3574,7 @@ func (a *Service) stop(e *actEntry) { |
| // the lease, until the start returns and has stopped what it started |
| // (the restart goroutine stops it before it closes sidecarStartDone). |
| // Only then is the host cgroup proven empty and the lease released |
| - // (reapUncontainedStop). |
| + // (reapCurrentGen). |
| a.mu.Lock() |
| startDone, hook := e.sidecarStartDone, a.joinWaiting |
| a.mu.Unlock() |
| @@ -3750,7 +3750,7 @@ func (a *Service) stop(e *actEntry) { |
| // Flag off, the leader's exit says nothing of what it forked (Task |
| // 8, F6): the host cgroup is proven empty first. Unproven, the stop |
| // stays pending with the lease, as for ErrStillRunning, and the |
| - // sweep retries the proof (reapUncontainedStop). |
| + // sweep retries the proof (reapCurrentGen). |
| log.Printf("activator: stop %s: its host cgroup is not proven empty; keeping the lease until it is", e.host) |
| a.mu.Lock() |
| a.keepPendingLocked(e, outcome) |
| @@ -3821,28 +3821,19 @@ func (a *Service) finishPendingStops() { |
| if !e.pendingStop || len(e.ops.members) > 0 || !a.respawnSettledLocked(e) { |
| continue |
| } |
| - if a.gens && (e.proc == nil || e.proc.Exited()) { |
| + if e.proc == nil || e.proc.Exited() { |
| // Members gone and the main process (if any) exited: the stop |
| - // finishes once the retain-until-proven rule holds (releasable, |
| - // in reapCurrentGen). A process still alive falls through to |
| - // main's re-stop cadence below. |
| - if !e.genReaping { |
| + // finishes once its termination proof holds (reapCurrentGen): |
| + // flag on, the retain-until-proven rule (releasable); flag off, |
| + // once a sidecar start it left in flight has returned, the host |
| + // cgroup proven empty (Task 8, F6). A process still alive falls |
| + // through to main's re-stop cadence below. |
| + if !e.genReaping && (a.gens || sidecarStartJoined(e.sidecarJoin)) { |
| e.genReaping = true |
| go a.reapCurrentGen(e) |
| } |
| continue |
| } |
| - if !a.gens && (e.proc == nil || e.proc.Exited()) { |
| - // Flag off, the main process (if any) exited: the stop finishes |
| - // once a sidecar start it left in flight has returned and the |
| - // host cgroup is proven empty (Task 8, F6; reapUncontainedStop). |
| - // A process still alive falls through to the re-stop cadence. |
| - if !e.genReaping && sidecarStartJoined(e.sidecarJoin) { |
| - e.genReaping = true |
| - go a.reapUncontainedStop(e) |
| - } |
| - continue |
| - } |
| // Still running: spec §6.3 says sweepOnce retries proc.Stop on its |
| // own cadence until done closes, and that applies here too, not only |
| // once termination has already been proven some other way. Without |