summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKerin Millar <kfm@plushkava.net>2024-08-09 00:51:46 +0100
committerSam James <sam@gentoo.org>2024-08-11 11:11:01 +0100
commit39a108d58143886c78c76fa1d9000210102624f7 (patch)
treea3c329d0bdc6f14927a40e70c24d055283e7a5c0
parentRename quote_args_bash() to _quote_args_bash() (diff)
downloadgentoo-functions-39a108d58143886c78c76fa1d9000210102624f7.tar.gz
gentoo-functions-39a108d58143886c78c76fa1d9000210102624f7.tar.bz2
gentoo-functions-39a108d58143886c78c76fa1d9000210102624f7.zip
Handle integer overflow as a special case in _should_throttle()
At the point that the genfun_time variable overflows, guarantee that the should_throttle() function behaves as if no throttling should occur rather than proceed to perform arithmetic based on the result of deducting genfun_last_time from genfun_time. Further, guarantee that the should_throttle() function behaves as if no throttling should occur upon the very first occasion that it is called, provided that the call to update_time() succeeds. Finally, add a test case. Signed-off-by: Kerin Millar <kfm@plushkava.net> Signed-off-by: Sam James <sam@gentoo.org>
-rw-r--r--functions.sh22
-rwxr-xr-xtest-functions47
2 files changed, 62 insertions, 7 deletions
diff --git a/functions.sh b/functions.sh
index 78830c6..e7ef6fe 100644
--- a/functions.sh
+++ b/functions.sh
@@ -756,15 +756,25 @@ _select_by_mtime()
#
# Considers the first parameter as a number of centiseconds and determines
# whether fewer have elapsed since the last occasion on which the function was
-# called.
+# called, or whether the last genfun_time update resulted in integer overflow.
#
_should_throttle()
{
_update_time || return
- if [ "$(( genfun_time - genfun_last_time > $1 ))" -eq 1 ]; then
- genfun_last_time=${genfun_time}
- false
- fi
+
+ _should_throttle()
+ {
+ _update_time || return
+ if [ "$(( (genfun_time < 0 && genfun_last_time >= 0) || genfun_time - genfun_last_time > $1 ))" -eq 1 ]
+ then
+ genfun_last_time=${genfun_time}
+ false
+ fi
+
+ }
+
+ genfun_last_time=${genfun_time}
+ false
}
#
@@ -817,8 +827,6 @@ _update_columns()
#
_update_time()
{
- genfun_last_time=0
-
# shellcheck disable=3028
if [ "${BASH_VERSINFO:-0}" -ge 5 ]; then
# shellcheck disable=2034,3045
diff --git a/test-functions b/test-functions
index 1f54208..34ffc41 100755
--- a/test-functions
+++ b/test-functions
@@ -1069,6 +1069,52 @@ test_update_time() {
iterate_tests 3 "$@"
}
+test_should_throttle() {
+ local bits max_int
+
+ genfun_time=
+ bits=30
+ while [ "${bits}" -lt 128 ]; do
+ # Dash is buggy and fails to handle $(( 1 << ++bits )).
+ bits=$(( bits + 1 ))
+ case $(( max_int = 1 << bits )) in
+ -*)
+ max_int=$(( max_int - 1 ))
+ genfun_time=$(( max_int - 4 ))
+ break
+ esac
+ done
+
+ if [ ! "${genfun_time}" ]; then
+ bailout "Failed to calculate the maximum possible integer value"
+ fi
+
+ # For the first test, genfun_last_time is not yet known. Therefore, the
+ # return value should always be 1. For the fifth test, integer overflow
+ # is expected to occur. Again, the return value should always be 1.
+ set -- \
+ ge 1 "${max_int}" \
+ eq 0 2 \
+ ge 1 1 \
+ ge 1 0 \
+ ge 1 2 \
+ eq 0 2 \
+ ge 1 1 \
+ ge 1 0
+
+ _update_time() {
+ true
+ }
+
+ callback() {
+ shift
+ test_description="_should_throttle $1 (${genfun_time}, $(( genfun_time += 1 )))"
+ _should_throttle "$1"
+ }
+
+ iterate_tests 3 "$@"
+}
+
iterate_tests() {
local code i j passed slice_width total
@@ -1152,6 +1198,7 @@ else
test_assign || rc=1
test_deref || rc=1
test_update_time || rc=1
+ test_should_throttle || rc=1
fi
cleanup_tmpdir