summaryrefslogtreecommitdiff
path: root/src/basic
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
parente002b8a28acc24e0a29cdc3f6cf759a197203f4a (diff)
downloadsystemd-ed6a6bac45e2674d5834510390cb2e5121bbb444.tar.gz
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')
-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) {