Skip to content

Commit f484960

Browse files
authored
Handle arbitrarily high integer values in Process.sleep/1 (#13649)
Aligns Process.sleep/1 behaviour with OTP :timer.sleep/1 function. https://www.erlang.org/doc/apps/stdlib/timer.html#sleep/1
1 parent 4119ec4 commit f484960

File tree

2 files changed

+20
-0
lines changed

2 files changed

+20
-0
lines changed

lib/elixir/lib/process.ex

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -233,6 +233,12 @@ defmodule Process do
233233
the current process will sleep forever, and not
234234
consume or reply to messages.
235235
236+
> #### Sleeping limit {: .info }
237+
>
238+
> Before Elixir v1.18, `sleep/1` did not accept integer timeout values greater
239+
> than `16#ffffffff`, that is, `2^32-1`. Since Elixir v1.18, arbitrarily high integer
240+
> values are accepted.
241+
236242
**Use this function with extreme care**. For almost all situations
237243
where you would use `sleep/1` in Elixir, there is likely a
238244
more correct, faster and precise way of achieving the same with
@@ -299,7 +305,15 @@ defmodule Process do
299305
end
300306
301307
"""
308+
309+
# Max value for a receive's after clause
310+
@max_receive_after 0xFFFFFFFF
311+
302312
@spec sleep(timeout) :: :ok
313+
def sleep(timeout) when is_integer(timeout) and timeout > @max_receive_after do
314+
receive after: (@max_receive_after -> sleep(timeout - @max_receive_after))
315+
end
316+
303317
def sleep(timeout)
304318
when is_integer(timeout) and timeout >= 0
305319
when timeout == :infinity do

lib/elixir/test/elixir/process_test.exs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,12 @@ defmodule ProcessTest do
5757
assert Process.sleep(0) == :ok
5858
end
5959

60+
test "sleep/1 with 2^32" do
61+
{pid, monitor_ref} = spawn_monitor(fn -> Process.sleep(2 ** 32) end)
62+
refute_receive {:DOWN, ^monitor_ref, :process, ^pid, {:timeout_value, _trace}}
63+
Process.exit(pid, :kill)
64+
end
65+
6066
test "info/2" do
6167
pid = spawn(fn -> Process.sleep(1000) end)
6268
assert Process.info(pid, :priority) == {:priority, :normal}

0 commit comments

Comments
 (0)