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
//! Operator termination signal for long-lived MobKit binaries.
//!
//! # Why this module exists
//!
//! [`tokio::signal::ctrl_c`] listens for **SIGINT and nothing else**. Both
//! gateway binaries waited on it alone, which is correct for an interactive
//! ctrl-c and wrong for every other way a long-lived process is stopped:
//! Kubernetes, systemd and `docker stop` all send **SIGTERM** first and
//! escalate to SIGKILL only after a grace period. SIGTERM's default
//! disposition terminates the process immediately, so a `ctrl_c`-only wait
//! means the graceful shutdown path never runs on an ordinary deploy.
//!
//! That was survivable until meerkat 0.8.22 introduced the schedule executor
//! lease, which made an ungraceful exit *cost* something durable. The lease is
//! released only on the graceful path (`ScheduleHostHandle::shutdown`). Skip
//! it and the row keeps a future `expires_at_utc`, so the replacement process
//! gets `AcquireScheduleExecutorLeaseOutcome::Busy`, its tick returns without
//! calling `claim_due_occurrences`, and **schedules do not fire for up to
//! `lease_duration` (60s by default) after every restart**. The claim watchdog
//! cannot see it either: its overdue threshold is 2 minutes, longer than the
//! window it would need to observe.
//!
//! So this is not a tidiness fix. On a container platform the pre-0.8.22
//! behaviour was "an ungraceful stop loses nothing"; after 0.8.22 it is "every
//! deploy silently stops firing schedules for a minute".
//!
//! # Contract
//!
//! Resolves on the FIRST of SIGINT or SIGTERM. It does not tell the caller
//! which arrived, because no caller has a reason to behave differently - both
//! mean "an operator or supervisor is stopping this process, run the shutdown
//! sequence". Callers keep owning what shutdown means; this only decides when.
//!
//! If the SIGTERM handler cannot be installed the function degrades to SIGINT
//! only rather than failing the process. A binary that refuses to start
//! because it could not register a signal handler is strictly worse than one
//! that starts and handles fewer signals.
/// Resolve when the process is asked to terminate, by SIGINT or SIGTERM.
///
/// See the module docs for why waiting on [`tokio::signal::ctrl_c`] alone is
/// insufficient for any process that will be deployed in a container.
pub async
/// Non-Unix fallback: SIGTERM has no equivalent, so this is SIGINT only.
pub async