Skip to content

Commit

Permalink
Handle arbitrarily high integer values in Process.sleep/1 (elixir-lan…
Browse files Browse the repository at this point in the history
…g#13649)

Aligns Process.sleep/1 behaviour with OTP :timer.sleep/1 function.
https://www.erlang.org/doc/apps/stdlib/timer.html#sleep/1
  • Loading branch information
vegris authored Jun 9, 2024
1 parent 4119ec4 commit f484960
Show file tree
Hide file tree
Showing 2 changed files with 20 additions and 0 deletions.
14 changes: 14 additions & 0 deletions lib/elixir/lib/process.ex
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,12 @@ defmodule Process do
the current process will sleep forever, and not
consume or reply to messages.
> #### Sleeping limit {: .info }
>
> Before Elixir v1.18, `sleep/1` did not accept integer timeout values greater
> than `16#ffffffff`, that is, `2^32-1`. Since Elixir v1.18, arbitrarily high integer
> values are accepted.
**Use this function with extreme care**. For almost all situations
where you would use `sleep/1` in Elixir, there is likely a
more correct, faster and precise way of achieving the same with
Expand Down Expand Up @@ -299,7 +305,15 @@ defmodule Process do
end
"""

# Max value for a receive's after clause
@max_receive_after 0xFFFFFFFF

@spec sleep(timeout) :: :ok
def sleep(timeout) when is_integer(timeout) and timeout > @max_receive_after do
receive after: (@max_receive_after -> sleep(timeout - @max_receive_after))
end

def sleep(timeout)
when is_integer(timeout) and timeout >= 0
when timeout == :infinity do
Expand Down
6 changes: 6 additions & 0 deletions lib/elixir/test/elixir/process_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,12 @@ defmodule ProcessTest do
assert Process.sleep(0) == :ok
end

test "sleep/1 with 2^32" do
{pid, monitor_ref} = spawn_monitor(fn -> Process.sleep(2 ** 32) end)
refute_receive {:DOWN, ^monitor_ref, :process, ^pid, {:timeout_value, _trace}}
Process.exit(pid, :kill)
end

test "info/2" do
pid = spawn(fn -> Process.sleep(1000) end)
assert Process.info(pid, :priority) == {:priority, :normal}
Expand Down

0 comments on commit f484960

Please sign in to comment.