File 0211-fix-simple-handler.patch of Package erlang

From 6a047827a6cfc157351fa3839d4ce84875f812a0 Mon Sep 17 00:00:00 2001
From: Marko Mindek <marko.mindek@gmail.com>
Date: Mon, 17 Mar 2025 12:54:30 +0100
Subject: [PATCH] fix: simple handler

---
 lib/kernel/src/logger.erl        | 56 +++++++++++++++++---------------
 lib/kernel/test/logger_SUITE.erl | 22 ++++++++++---
 2 files changed, 47 insertions(+), 31 deletions(-)

diff --git a/lib/kernel/src/logger.erl b/lib/kernel/src/logger.erl
index 002c7bfe8e..23c474ca2e 100644
--- a/lib/kernel/src/logger.erl
+++ b/lib/kernel/src/logger.erl
@@ -826,6 +826,24 @@ referring to this handler.
       HandlerId :: logger_handler:id(),
       Module :: module(),
       Config :: logger_handler:config().
+add_handler(default = HandlerId, Module, Config)
+        when not is_map_key(filters, Config) ->
+    %% The default handler should have a couple of extra filters
+    %% set on it by default.
+    DefConfig = #{ filter_default => stop,
+                   filters => get_default_handler_filters()},
+    add_handler(HandlerId,Module,maps:merge(DefConfig, Config));
+add_handler(default = HandlerId, Module, Config) ->
+    case logger_server:add_handler(HandlerId,Module,Config) of
+        ok ->
+            %% If a default handler was added we try to remove the simple_logger
+            %% If the simple logger exists it will replay its log events
+            %% to the handler(s) added in the fold above.
+            logger_server:remove_handler(simple),
+            ok;
+        Error ->
+            Error
+    end;
 add_handler(HandlerId,Module,Config) ->
     logger_server:add_handler(HandlerId,Module,Config).
 
@@ -1508,6 +1526,13 @@ Reconfigure Logger using updated `kernel` configuration that was set after
 
 Beware, that this is meant to be run only by the build tools, not manually
 during application lifetime, as this may cause missing log entries.
+
+Before reconfiguration, `simple` logger handler is added to capture log events
+before the logging infrastructure is started and prints them to standard
+output. After the `default` handler is added again, all log events captured by
+the `simple` handler are replayed to the `default` handler, and the `simple`
+handler is removed. Notice that if you don't add the `default` handler,
+`simple` handler will persist.
 """.
 -doc(#{title => <<"Miscellaneous API functions">>,since => <<"OTP 24.2">>}).
 -spec reconfigure() -> ok | {error,term()}.
@@ -1516,13 +1541,13 @@ during application lifetime, as this may cause missing log entries.
 %% before running main application.
 reconfigure() ->
     try
+        _ = logger:add_handler(simple,logger_simple_h,
+                            #{filter_default=>stop,
+                              filters=>?DEFAULT_HANDLER_FILTERS}),
         [case logger:remove_handler(Id) of
              ok -> ok;
              {error, Reason} -> throw({remove, Id, Reason})
-         end || #{id := Id} <- logger:get_handler_config()],
-        ok=logger:add_handler(simple,logger_simple_h,
-                              #{filter_default=>stop,
-                                filters=>?DEFAULT_HANDLER_FILTERS}),
+         end || Id <- logger:get_handler_ids(), Id =/= simple],
         logger:unset_module_level(),
         internal_init_logger()
     of
@@ -1659,28 +1684,7 @@ add_handlers(HandlerConfig) ->
 add_handlers(App,HandlerConfig) ->
     try
         check_logger_config(App,HandlerConfig),
-        DefaultAdded =
-            lists:foldl(
-              fun({handler, default = Id, Module, Config}, _)
-                    when not is_map_key(filters, Config) ->
-                      %% The default handler should have a couple of extra filters
-                      %% set on it by default.
-                      DefConfig = #{ filter_default => stop,
-                                     filters => get_default_handler_filters()},
-                      setup_handler(Id, Module, maps:merge(DefConfig,Config)),
-                      true;
-                 ({handler, Id, Module, Config}, Default) ->
-                      setup_handler(Id, Module, Config),
-                      Default orelse Id == default;
-                 (_,Default) -> Default
-              end, false, HandlerConfig),
-        %% If a default handler was added we try to remove the simple_logger
-        %% If the simple logger exists it will replay its log events
-        %% to the handler(s) added in the fold above.
-        [case logger:remove_handler(simple) of
-             ok -> ok;
-             {error,{not_found,simple}} -> ok
-         end || DefaultAdded],
+        [setup_handler(Id,Module,Config) || {handler,Id,Module,Config} <- HandlerConfig],
         ok
     catch throw:Reason0 ->
             Reason =
diff --git a/lib/kernel/test/logger_SUITE.erl b/lib/kernel/test/logger_SUITE.erl
index 3041fb0755..c56a5ce0be 100644
--- a/lib/kernel/test/logger_SUITE.erl
+++ b/lib/kernel/test/logger_SUITE.erl
@@ -1047,19 +1047,31 @@ app_config(Config) ->
 
     ok = peer:stop(Peer2),
 
+    %% Start a node with no default handler, then add an own default handler,
+    %% but via logger:add_handler/3
+    {ok, #{handlers := [#{id := simple}]}, Peer3, Node3} =
+        logger_test_lib:setup(Config, [{logger, [{handler, default, undefined}]}]),
+
+    ok = rpc:call(Node3,logger,add_handler,[default, logger_std_h, #{}]),
+
+    #{handlers:=[#{id:=default,filters:=DF}]} =
+        rpc:call(Node3,logger,get_config,[]),
+
+    ok = peer:stop(Peer3),
+
     %% Start a silent node, then add an own default handler
-    {ok,#{handlers:=[]}, Peer3, Node3} =
+    {ok,#{handlers:=[]}, Peer4, Node4} =
         logger_test_lib:setup(Config,[{error_logger,silent}]),
 
     {error,{bad_config,{handler,[{some,bad,config}]}}} =
-        rpc:call(Node3,logger,add_handlers,[[{some,bad,config}]]),
-    ok = rpc:call(Node3,logger,add_handlers,
+        rpc:call(Node4,logger,add_handlers,[[{some,bad,config}]]),
+    ok = rpc:call(Node4,logger,add_handlers,
                   [[{handler,default,logger_std_h,#{}}]]),
 
     #{handlers:=[#{id:=default,filters:=DF}]} =
-        rpc:call(Node3,logger,get_config,[]),
+        rpc:call(Node4,logger,get_config,[]),
 
-    ok = peer:stop(Peer3).
+    ok = peer:stop(Peer4).
 
 %% This test case is mainly to see code coverage. Note that
 %% logger_env_var_SUITE tests a lot of the same, and checks the
-- 
2.43.0

openSUSE Build Service is sponsored by