summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorErlang/OTP <otp@erlang.org>2021-09-02 12:15:36 +0200
committerErlang/OTP <otp@erlang.org>2021-09-02 12:15:36 +0200
commitf3a740a81d4f2ece608058706404c088e0afd5d1 (patch)
tree25689e7a48dd8cda423419886b32679566f60ba5
parent7c6a3990dc43e89d3de8185c7a0aebad542fc8ef (diff)
parent7760cca94081a9d7d0607967277ea77c5234bc91 (diff)
downloaderlang-f3a740a81d4f2ece608058706404c088e0afd5d1.tar.gz
Merge branch 'rickard/cancel_timer_no_info_fix/OTP-17472' into maint-22
* rickard/cancel_timer_no_info_fix/OTP-17472: Fix erlang:cancel_timer(_, [{info, false}])
-rw-r--r--erts/emulator/beam/erl_hl_timer.c15
-rw-r--r--erts/emulator/test/timer_bif_SUITE.erl58
2 files changed, 66 insertions, 7 deletions
diff --git a/erts/emulator/beam/erl_hl_timer.c b/erts/emulator/beam/erl_hl_timer.c
index aec31080d2..2966915256 100644
--- a/erts/emulator/beam/erl_hl_timer.c
+++ b/erts/emulator/beam/erl_hl_timer.c
@@ -1903,7 +1903,7 @@ send_async_info(Process *proc, ErtsProcLocks initial_locks,
static ERTS_INLINE Eterm
send_sync_info(Process *proc, ErtsProcLocks initial_locks,
- Uint32 *refn, int cancel, Sint64 time_left)
+ Uint32 *refn, int info, int cancel, Sint64 time_left)
{
ErtsProcLocks locks = initial_locks;
ErtsMessage *mp;
@@ -1923,7 +1923,9 @@ send_sync_info(Process *proc, ErtsProcLocks initial_locks,
ref = make_internal_ref(hp);
hp += ERTS_REF_THING_SIZE;
- if (time_left < 0)
+ if (!info)
+ res = am_ok;
+ else if (time_left < 0)
res = am_false;
else if (time_left <= (Sint64) MAX_SMALL)
res = make_small((Sint) time_left);
@@ -1974,7 +1976,7 @@ access_sched_local_btm(Process *c_p, Eterm pid,
time_left = access_btm(tmr, (Uint32) esdp->no, esdp, cancel);
- if (!info)
+ if (async && !info)
return am_ok;
if (c_p) {
@@ -1987,12 +1989,15 @@ access_sched_local_btm(Process *c_p, Eterm pid,
}
if (!async) {
- if (c_p)
+ if (c_p) {
+ if (!info)
+ return am_ok;
return return_info(c_p, time_left);
+ }
if (proc)
return send_sync_info(proc, proc_locks,
- rrefn, cancel, time_left);
+ rrefn, info, cancel, time_left);
}
else if (proc) {
Eterm ref;
diff --git a/erts/emulator/test/timer_bif_SUITE.erl b/erts/emulator/test/timer_bif_SUITE.erl
index 98d43cb70d..28f4fdf943 100644
--- a/erts/emulator/test/timer_bif_SUITE.erl
+++ b/erts/emulator/test/timer_bif_SUITE.erl
@@ -23,7 +23,7 @@
-export([all/0, suite/0, init_per_suite/1, end_per_suite/1,
init_per_testcase/2,end_per_testcase/2]).
-export([start_timer_1/1, send_after_1/1, send_after_2/1, send_after_3/1,
- cancel_timer_1/1,
+ cancel_timer_1/1, cancel_timer_sync/1,
start_timer_big/1, send_after_big/1,
start_timer_e/1, send_after_e/1, cancel_timer_e/1,
read_timer_trivial/1, read_timer/1, read_timer_async/1,
@@ -63,7 +63,7 @@ suite() ->
all() ->
[start_timer_1, send_after_1, send_after_2,
- cancel_timer_1, start_timer_e, send_after_e,
+ cancel_timer_1, cancel_timer_sync, start_timer_e, send_after_e,
cancel_timer_e, start_timer_big, send_after_big,
read_timer_trivial, read_timer, read_timer_async,
cleanup, evil_timers, registered_process,
@@ -165,6 +165,60 @@ cancel_timer_1(Config) when is_list(Config) ->
ok.
+cancel_timer_sync(Config) when is_list(Config) ->
+ cancel_timer_sync_test(true),
+ cancel_timer_sync_test(false).
+
+cancel_timer_sync_test(SameSched) ->
+ process_flag(scheduler, 1),
+
+ R1 = erlang:send_after(1000, self(), cling),
+ R2 = erlang:send_after(1000, self(), clong),
+ R3 = erlang:send_after(1000, self(), clang),
+ TsSet = erlang:monotonic_time(),
+ R4 = erlang:send_after(0, self(), pling),
+ R5 = erlang:send_after(0, self(), plong),
+ R6 = erlang:send_after(0, self(), plang),
+ R7 = make_ref(),
+ R8 = make_ref(),
+ R9 = make_ref(),
+
+ case SameSched of
+ true ->
+ %% Cancel from the same scheduler...
+ ok;
+ false->
+ %% Cancel from different scheduler...
+ process_flag(scheduler, erlang:system_info(schedulers_online))
+ end,
+
+ C1 = erlang:cancel_timer(R1),
+ true = is_integer(C1),
+ C2 = erlang:cancel_timer(R2, [{info, true}]),
+ true = is_integer(C2),
+ ok = erlang:cancel_timer(R3, [{info, false}]),
+
+ receive pling -> ok end,
+ receive plong -> ok end,
+ receive plang -> ok end,
+
+ false = erlang:cancel_timer(R4),
+ false = erlang:cancel_timer(R5, [{info, true}]),
+ ok = erlang:cancel_timer(R6, [{info, false}]),
+
+ false = erlang:cancel_timer(R7),
+ false = erlang:cancel_timer(R8, [{info, true}]),
+ ok = erlang:cancel_timer(R9, [{info, false}]),
+
+ Wait = 1500 - erlang:convert_time_unit(erlang:monotonic_time() - TsSet,
+ native, millisecond),
+
+ receive TMO when TMO == cling; TMO == clang; TMO == clong ->
+ ct:fail({unexpected_timeout, TMO})
+ after Wait ->
+ ok
+ end.
+
%% Error cases for start_timer/3
start_timer_e(Config) when is_list(Config) ->
{'EXIT', _} = (catch erlang:start_timer(-4, self(), hej)),