summaryrefslogtreecommitdiffstats
path: root/src/basic/ratelimit.c
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2023-04-20 10:31:44 +0200
committerLennart Poettering <lennart@poettering.net>2023-04-20 13:39:06 +0200
commited6a6bac45e2674d5834510390cb2e5121bbb444 (patch)
tree2fe25d7f3a5b82d8b6b4904a70dcfc3ccf2ae61b /src/basic/ratelimit.c
parentman: try to make clearer that /var/ is generally not available in /usr/lib/sy... (diff)
downloadsystemd-ed6a6bac45e2674d5834510390cb2e5121bbb444.tar.xz
systemd-ed6a6bac45e2674d5834510390cb2e5121bbb444.zip
ratelimit: handle counter overflows somewhat sanely
An overflow here (i.e. the counter reaching 2^32 within a ratelimit time window) is not so unlikely. Let's handle this somewhat sanely and simply stop counting, while remaining in the "limit is hit" state until the time window has passed.
Diffstat (limited to 'src/basic/ratelimit.c')
-rw-r--r--src/basic/ratelimit.c20
1 files changed, 11 insertions, 9 deletions
diff --git a/src/basic/ratelimit.c b/src/basic/ratelimit.c
index a0260bfe1c..5675ec2f46 100644
--- a/src/basic/ratelimit.c
+++ b/src/basic/ratelimit.c
@@ -10,7 +10,6 @@
bool ratelimit_below(RateLimit *r) {
usec_t ts;
- bool good = false;
assert(r);
@@ -21,22 +20,25 @@ bool ratelimit_below(RateLimit *r) {
if (r->begin <= 0 ||
usec_sub_unsigned(ts, r->begin) > r->interval) {
- r->begin = ts;
+ r->begin = ts; /* Start a new time window */
+ r->num = 1; /* Reset counter */
+ return true;
+ }
- /* Reset counter */
- r->num = 0;
- good = true;
- } else if (r->num < r->burst)
- good = true;
+ if (_unlikely_(r->num == UINT_MAX))
+ return false;
r->num++;
- return good;
+ return r->num <= r->burst;
}
unsigned ratelimit_num_dropped(RateLimit *r) {
assert(r);
- return r->num > r->burst ? r->num - r->burst : 0;
+ if (r->num == UINT_MAX) /* overflow, return as special case */
+ return UINT_MAX;
+
+ return LESS_BY(r->num, r->burst);
}
usec_t ratelimit_end(const RateLimit *rl) {