File 1382-Fix-erlang-cancel_timer-_-info-false.patch of Package erlang

From 7760cca94081a9d7d0607967277ea77c5234bc91 Mon Sep 17 00:00:00 2001
From: Rickard Green <rickard@erlang.org>
Date: Thu, 3 Jun 2021 11:52:37 +0200
Subject: [PATCH] Fix erlang:cancel_timer(_, [{info, false}])

---
 erts/emulator/beam/erl_hl_timer.c      | 15 ++++---
 erts/emulator/test/timer_bif_SUITE.erl | 58 +++++++++++++++++++++++++-
 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 b0eb0e85c0..d34846b3a9 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 7d682897f8..f72b14bedb 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,
@@ -62,7 +62,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,
@@ -163,6 +163,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)),
-- 
2.26.2

openSUSE Build Service is sponsored by