Skip to content

Commit

Permalink
Merge pull request #8772 from garazdawi/lukas/stdlib/proc_lib-stop-ex…
Browse files Browse the repository at this point in the history
…pected-reason/OTP-19233

stdlib: Fix proc_lib:stop when exit reason is expected reason
  • Loading branch information
garazdawi authored Sep 17, 2024
2 parents df4d86a + 3f2d85a commit 41a43fe
Show file tree
Hide file tree
Showing 2 changed files with 20 additions and 4 deletions.
12 changes: 8 additions & 4 deletions lib/stdlib/src/proc_lib.erl
Original file line number Diff line number Diff line change
Expand Up @@ -1573,20 +1573,24 @@ about system messages, see `m:sys` and section
stop(Process, Reason, Timeout) ->
Mref = erlang:monitor(process, Process),
T0 = erlang:monotonic_time(millisecond),
StopTimeout = fun(infinity) -> infinity;
(T1) -> T1 - (((erlang:monotonic_time(microsecond) + 999) div 1000) - T0)
end,
RemainingTimeout = try
sys:terminate(Process, Reason, Timeout)
of
ok when Timeout =:= infinity ->
infinity;
ok ->
Timeout - (((erlang:monotonic_time(microsecond) + 999) div 1000) - T0)
ok -> StopTimeout(Timeout)
catch
exit:{noproc, {sys, terminate, _}} ->
demonitor(Mref, [flush]),
exit(noproc);
exit:{timeout, {sys, terminate, _}} ->
demonitor(Mref, [flush]),
exit(timeout);
exit:{Reason, {sys, terminate, _}} ->
StopTimeout(Timeout);
exit:Reason1 ->
demonitor(Mref, [flush]),
exit(Reason1)
Expand Down
12 changes: 12 additions & 0 deletions lib/stdlib/test/proc_lib_SUITE.erl
Original file line number Diff line number Diff line change
Expand Up @@ -695,6 +695,18 @@ stop(_Config) ->
timeout
end,

%% Ensure that if process stops with same reason just as stop is called,
%% stop does not throw an exception.
PidNormalStop = proc_lib:spawn(fun() -> timer:sleep(1000) end),
ok = proc_lib:stop(PidNormalStop,normal,2000),
false = erlang:is_process_alive(PidNormalStop),
PidDieStop = proc_lib:spawn(fun() -> timer:sleep(1000), exit(die) end),
ok = proc_lib:stop(PidDieStop,die,2000),
false = erlang:is_process_alive(PidDieStop),
PidDieStopCrash = proc_lib:spawn(fun() -> timer:sleep(1000), exit(die) end),
{'EXIT', {die, _}} = catch (proc_lib:stop(PidDieStopCrash,normal,2000)),
false = erlang:is_process_alive(PidDieStopCrash),

%% Success case with other reason than 'normal'
Pid5 = proc_lib:spawn(SysMsgProc),
ok = proc_lib:stop(Pid5,other_reason,infinity),
Expand Down

0 comments on commit 41a43fe

Please sign in to comment.