diff options
author | Nick Vatamaniuc <vatamane@gmail.com> | 2021-10-15 11:00:03 -0400 |
---|---|---|
committer | Nick Vatamaniuc <nickva@users.noreply.github.com> | 2021-10-15 11:53:29 -0400 |
commit | c3f08f770d66b486fb2cbe8b4a7fe50551303f8f (patch) | |
tree | 8565288f82c269d23262f4aac742fdff703a0dbe | |
parent | 029612b27c78405790fd550958028cec5c84e9c8 (diff) | |
download | couchdb-c3f08f770d66b486fb2cbe8b4a7fe50551303f8f.tar.gz |
Fix badarith error in get_db_timeout when request timeout = infinity
`infinity` it turns out is a valid configuration value for fabric
request_timeout. We can pass that to Erlang `receive` statement, any arithmetic
with it would fail.
To guard against the crash use the max small int value (60 bits). With enough
shards, due to the exponential nature of the algorithm, we still get a nice
progression from the minimum 100 msec all the way up to the large int value.
This case is illustrated in the test.
Issue: https://github.com/apache/couchdb/issues/3789
-rw-r--r-- | src/fabric/src/fabric_util.erl | 10 |
1 files changed, 9 insertions, 1 deletions
diff --git a/src/fabric/src/fabric_util.erl b/src/fabric/src/fabric_util.erl index e07ab7b55..4c4031627 100644 --- a/src/fabric/src/fabric_util.erl +++ b/src/fabric/src/fabric_util.erl @@ -138,6 +138,10 @@ get_shard([#shard{node = Node, name = Name} | Rest], Opts, Timeout, Factor) -> rexi_monitor:stop(Mon) end. +get_db_timeout(N, Factor, MinTimeout, infinity) -> + % MaxTimeout may be infinity so we just use the largest Erlang small int to + % avoid blowing up the arithmetic + get_db_timeout(N, Factor, MinTimeout, 1 bsl 59); get_db_timeout(N, Factor, MinTimeout, MaxTimeout) -> % % The progression of timeouts forms a geometric series: @@ -460,4 +464,8 @@ get_db_timeout_test() -> ?assertEqual(28346, get_db_timeout(2 * 3, 2, 100, 3600000)), % No shards at all - ?assertEqual(60000, get_db_timeout(0, 2, 100, 60000)). + ?assertEqual(60000, get_db_timeout(0, 2, 100, 60000)), + + % request_timeout was set to infinity, with enough shards it still gets to + % 100 min timeout at the start from the exponential logic + ?assertEqual(100, get_db_timeout(64, 2, 100, infinity)). |