diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/kernel/doc/src/logger.xml | 33 | ||||
-rw-r--r-- | lib/kernel/doc/src/logger_arch.png | bin | 32407 -> 32187 bytes | |||
-rw-r--r-- | lib/kernel/doc/src/logger_chapter.xml | 137 | ||||
-rw-r--r-- | lib/kernel/src/logger_disk_log_h.erl | 6 | ||||
-rw-r--r-- | lib/kernel/src/logger_std_h.erl | 6 | ||||
-rw-r--r-- | lib/kernel/test/logger_disk_log_h_SUITE.erl | 77 | ||||
-rw-r--r-- | lib/kernel/test/logger_std_h_SUITE.erl | 31 |
7 files changed, 169 insertions, 121 deletions
diff --git a/lib/kernel/doc/src/logger.xml b/lib/kernel/doc/src/logger.xml index 7f35a5d752..8940c89ab8 100644 --- a/lib/kernel/doc/src/logger.xml +++ b/lib/kernel/doc/src/logger.xml @@ -86,6 +86,14 @@ logger:error("error happened because: ~p", [Reason]). % Without macro <item>built-in filters, see <seealso marker="logger_filters">logger_filters</seealso>.</item> </list> + + <note> + <p>Since Logger is new in Erlang/OTP 21.0, we do reserve the right + to introduce changes to the Logger API and functionality in + patches following this release. These changes might or might not + be backwards compatible with the initial version.</p> + </note> + </description> <datatypes> @@ -939,7 +947,8 @@ logger:set_process_metadata(maps:merge(logger:get_process_metadata(), Meta)). <funcs> <func> - <name>HModule:adding_handler(Config1) -> {ok, Config2} | {error, Reason}</name> + <name>HModule:adding_handler(Config1) -> {ok, Config2} | {error, + Reason}</name> <fsummary>An instance of this handler is about to be added.</fsummary> <type> <v>Config1 = Config2 = @@ -948,9 +957,10 @@ logger:set_process_metadata(maps:merge(logger:get_process_metadata(), Meta)). </type> <desc> <p>This callback function is optional.</p> - <p>The function is called when an new handler is about to be - added, and the purpose is to verify the configuration and - initiate all resources needed by the handler.</p> + <p>The function is called on a temporary process when an new + handler is about to be added. The purpose is to verify the + configuration and initiate all resources needed by the + handler.</p> <p>The handler identity is associated with the <c>id</c> key in <c>Config1</c>.</p> <p>If everything succeeds, the callback function can add @@ -972,9 +982,9 @@ logger:set_process_metadata(maps:merge(logger:get_process_metadata(), Meta)). </type> <desc> <p>This callback function is optional.</p> - <p>The function is called when the configuration for a handler - is about to change, and the purpose is to verify and act on - the new configuration.</p> + <p>The function is called on a temporary process when the + configuration for a handler is about to change. The purpose + is to verify and act on the new configuration.</p> <p><c>Config1</c> is the existing configuration and <c>Config2</c> is the new configuration.</p> <p>The handler identity is associated with the <c>id</c> key @@ -999,7 +1009,8 @@ logger:set_process_metadata(maps:merge(logger:get_process_metadata(), Meta)). <p>This callback function is mandatory.</p> <p>The function is called when all primary filters and all handler filters for the handler in question have passed for - the given log event.</p> + the given log event. It is called on the client process, that + is, the process that issued the log event.</p> <p>The handler identity is associated with the <c>id</c> key in <c>Config</c>.</p> <p>The handler must log the event.</p> @@ -1017,9 +1028,9 @@ logger:set_process_metadata(maps:merge(logger:get_process_metadata(), Meta)). </type> <desc> <p>This callback function is optional.</p> - <p>The function is called when a handler is about to be - removed, and the purpose is to release all resources used by - the handler.</p> + <p>The function is called on a temporary process when a + handler is about to be removed. The purpose is to release + all resources used by the handler.</p> <p>The handler identity is associated with the <c>id</c> key in <c>Config</c>.</p> <p>The return value is ignored by Logger.</p> diff --git a/lib/kernel/doc/src/logger_arch.png b/lib/kernel/doc/src/logger_arch.png Binary files differindex a9b9a658b4..a3a863c511 100644 --- a/lib/kernel/doc/src/logger_arch.png +++ b/lib/kernel/doc/src/logger_arch.png diff --git a/lib/kernel/doc/src/logger_chapter.xml b/lib/kernel/doc/src/logger_chapter.xml index a4951022bb..208193ee42 100644 --- a/lib/kernel/doc/src/logger_chapter.xml +++ b/lib/kernel/doc/src/logger_chapter.xml @@ -48,6 +48,13 @@ handler, replace it by a custom handler, and install additional handlers.</p> + <note> + <p>Since Logger is new in Erlang/OTP 21.0, we do reserve the right + to introduce changes to the Logger API and functionality in + patches following this release. These changes might or might not + be backwards compatible with the initial version.</p> + </note> + <section> <title>Overview</title> <p>A <em>log event</em> consists of a <em>log level</em>, the @@ -84,11 +91,11 @@ section <seealso marker="#filters">Filters</seealso> for more details.</p> <p>If a log event passes through all primary filters and all - handler filters for a specific handler, Logger forwards the event - to the handler callback. The handler formats and prints the - event to its destination. See - section <seealso marker="#handlers">Handlers</seealso> for - more details.</p> + handler filters for a specific handler, Logger forwards the + event to the <em>handler callback</em>. The handler formats and + prints the event to its destination. See + section <seealso marker="#handlers">Handlers</seealso> for more + details.</p> <p>Everything up to and including the call to the handler callbacks is executed on the client process, that is, the process where the log event was issued. It is up to the handler @@ -114,10 +121,11 @@ <marker id="log_level"/> <title>Log Level</title> <p>The log level indicates the severity of a event. In - accordance with the Syslog protocol, RFC-5424, eight log - levels can be specified. The following table lists all - possible log levels by name (atom), integer value, and - description:</p> + accordance with the Syslog protocol, + <url href="https://www.ietf.org/rfc/rfc5424.txt">RFC + 5424</url>, eight log levels can be specified. The following + table lists all possible log levels by name (atom), integer + value, and description:</p> <table align="left"> <row> @@ -338,7 +346,7 @@ logger:debug(#{got => connection_request, id => Id, state => State}, <marker id="handlers"/> <title>Handlers</title> <p>A handler is defined as a module exporting at least the - following function:</p> + following callback function:</p> <pre><seealso marker="logger#HModule:log-2">log(LogEvent, Config) -> void()</seealso></pre> @@ -935,50 +943,50 @@ error_logger:add_report_handler/1,2. </section> <section> - <title>Example: Add a handler to log debug events to file</title> + <title>Example: Add a handler to log info events to file</title> <p>When starting an Erlang node, the default behaviour is that all - log events on level info or more severe, are logged to the - terminal via the default handler. To also log debug events, you - can either change the primary log level to <c>debug</c>:</p> + log events on level <c>notice</c> or more severe, are logged to + the terminal via the default handler. To also log info events, + you can either change the primary log level to <c>info</c>:</p> <pre> -1> <input>logger:set_primary_config(level, debug).</input> +1> <input>logger:set_primary_config(level, info).</input> ok</pre> <p>or set the level for one or a few modules only:</p> <pre> -2> <input>logger:set_module_level(mymodule, debug).</input> +2> <input>logger:set_module_level(mymodule, info).</input> ok</pre> - <p>This allows debug events to pass through to the default handler, - and be printed to the terminal as well. If there are many debug + <p>This allows info events to pass through to the default handler, + and be printed to the terminal as well. If there are many info events, it can be useful to print these to a file instead.</p> - <p>First, set the log level of the default handler to <c>info</c>, - preventing it from printing debug events to the terminal:</p> + <p>First, set the log level of the default handler + to <c>notice</c>, preventing it from printing info events to the + terminal:</p> <pre> -3> <input>logger:set_handler_config(default, level, info).</input> +3> <input>logger:set_handler_config(default, level, notice).</input> ok</pre> <p>Then, add a new handler which prints to file. You can use the handler module <seealso marker="logger_std_h"><c>logger_std_h</c></seealso>, - and specify type <c>{file,File}</c>. The default handler level - is <c>all</c>, so you don't need to specify that:</p> + and specify type <c>{file,File}</c>.:</p> <pre> -4> <input>Config = #{config => #{type => {file,"./debug.log"}}}.</input> -#{config => #{type => {file,"./debug.log"}}} -5> <input>logger:add_handler(debugger, logger_std_h, Config).</input> +4> <input>Config = #{config => #{type => {file,"./info.log"}}, level => info}.</input> +#{config => #{type => {file,"./info.log"}},level => info} +5> <input>logger:add_handler(myhandler, logger_std_h, Config).</input> ok</pre> <p>Since <c>filter_default</c> defaults to <c>log</c>, this - handler now receives all log events. If you want debug events - only in the file, you must add a filter to stop all non-debug + handler now receives all log events. If you want info events + only in the file, you must add a filter to stop all non-info events. The built-in filter <seealso marker="logger_filters#level-2"> <c>logger_filters:level/2</c></seealso> can do this:</p> <pre> -6> <input>logger:add_handler_filter(debugger, stop_non_debug, - {fun logger_filters:level/2, {stop, neq, debug}}).</input> +6> <input>logger:add_handler_filter(myhandler, stop_non_info, + {fun logger_filters:level/2, {stop, neq, info}}).</input> ok</pre> <p>See section <seealso marker="#filters">Filters</seealso> for - more information about the filters and the <c>filter_default</c> - configuration parameter.</p> + more information about the filters and the <c>filter_default</c> + configuration parameter.</p> </section> @@ -1024,63 +1032,42 @@ ok</pre> <p>A simple handler that prints to the terminal can be implemented as follows:</p> <code> --module(myhandler). +-module(myhandler1). -export([log/2]). -log(LogEvent, #{formatter := {FModule, FConfig}) -> +log(LogEvent, #{formatter := {FModule, FConfig}}) -> io:put_chars(FModule:format(LogEvent, FConfig)). </code> - <p>A simple handler which prints to file can be implemented like - this:</p> - <code> --module(myhandler). --export([adding_handler/1, removing_handler/1, log/2]). --export([init/1, handle_call/3, handle_cast/2, terminate/2]). - -adding_handler(Config) -> - {ok, Fd} = file:open(File, [append, {encoding, utf8}]), - {ok, Config#{myhandler_fd => Fd}}. - -removing_handler(#{myhandler_fd := Fd}) -> - _ = file:close(Fd), - ok. - -log(LogEvent,#{myhandler_fd := Fd, formatter := {FModule, FConfig}}) -> - io:put_chars(Fd, FModule:format(LogEvent, FConfig)). - </code> - - <note> - <p>The above handlers do not have any overload - protection, and all log events are printed directly from the - client process.</p> - <p>For information and examples of overload protection, please - refer to - section <seealso marker="#overload_protection">Protecting the - Handler from Overload</seealso>, and the implementation - of <seealso marker="logger_std_h"><c>logger_std_h</c></seealso> - and <seealso marker="logger_disk_log_h"><c>logger_disk_log_h</c> - </seealso>.</p> - </note> - - <p>Below is a simpler example of a handler which logs through one - single process.</p> + <p>Notice that the above handler does not have any overload + protection, and all log events are printed directly from the + client process.</p> + <p>For information and examples of overload protection, please + refer to + section <seealso marker="#overload_protection">Protecting the + Handler from Overload</seealso>, and the implementation + of <seealso marker="logger_std_h"><c>logger_std_h</c></seealso> + and <seealso marker="logger_disk_log_h"><c>logger_disk_log_h</c> + </seealso>.</p> + <p>The following is a simpler example of a handler which logs to a + file through one single process:</p> <code> --module(myhandler). +-module(myhandler2). -export([adding_handler/1, removing_handler/1, log/2]). -export([init/1, handle_call/3, handle_cast/2, terminate/2]). adding_handler(Config) -> - {ok, Pid} = gen_server:start(?MODULE, Config), - {ok, Config#{myhandler_pid => Pid}}. + MyConfig = maps:get(config,Config,#{file => "myhandler2.log"}), + {ok, Pid} = gen_server:start(?MODULE, MyConfig, []), + {ok, Config#{config => MyConfig#{pid => Pid}}}. -removing_handler(#{myhandler_pid := Pid}) -> +removing_handler(#{config := #{pid := Pid}}) -> gen_server:stop(Pid). -log(LogEvent,#{myhandler_pid := Pid} = Config) -> +log(LogEvent,#{config := #{pid := Pid}} = Config) -> gen_server:cast(Pid, {log, LogEvent, Config}). -init(#{myhandler_file := File}) -> +init(#{file := File}) -> {ok, Fd} = file:open(File, [append, {encoding, utf8}]), {ok, #{file => File, fd => Fd}}. @@ -1091,7 +1078,7 @@ handle_cast({log, LogEvent, Config}, #{fd := Fd} = State) -> do_log(Fd, LogEvent, Config), {noreply, State}. -terminate(Reason, #{fd := Fd}) -> +terminate(_Reason, #{fd := Fd}) -> _ = file:close(Fd), ok. diff --git a/lib/kernel/src/logger_disk_log_h.erl b/lib/kernel/src/logger_disk_log_h.erl index f08621c9c5..cf8ea658e3 100644 --- a/lib/kernel/src/logger_disk_log_h.erl +++ b/lib/kernel/src/logger_disk_log_h.erl @@ -249,7 +249,8 @@ init([Name, max_no_files:=MNF}}, State = #{dl_sync_int := DLSyncInt}]) -> - register(?name_to_reg_name(?MODULE,Name), self()), + RegName = ?name_to_reg_name(?MODULE,Name), + register(RegName, self()), process_flag(trap_exit, true), process_flag(message_queue_data, off_heap), @@ -296,10 +297,12 @@ init([Name, enter_loop(Config1, State1) catch _:Error -> + unregister(RegName), logger_h_common:error_notify({open_disk_log,Name,Error}), proc_lib:init_ack(Error) end; Error -> + unregister(RegName), logger_h_common:error_notify({open_disk_log,Name,Error}), proc_lib:init_ack(Error) end. @@ -426,6 +429,7 @@ terminate(Reason, State = #{id := Name}) -> _ = logger_h_common:cancel_timer(maps:get(rep_sync_tref, State, undefined)), _ = close_disk_log(Name, normal), + unregister(?name_to_reg_name(?MODULE, Name)), logger_h_common:stop_or_restart(Name, Reason, State). code_change(_OldVsn, State, _Extra) -> diff --git a/lib/kernel/src/logger_std_h.erl b/lib/kernel/src/logger_std_h.erl index a03e1ffc2a..2a37076dda 100644 --- a/lib/kernel/src/logger_std_h.erl +++ b/lib/kernel/src/logger_std_h.erl @@ -229,7 +229,8 @@ log(LogEvent, Config = #{id := Name, init([Name, Config = #{config := HConfig}, State0 = #{type := Type, file_ctrl_sync_int := FileCtrlSyncInt}]) -> - register(?name_to_reg_name(?MODULE,Name), self()), + RegName = ?name_to_reg_name(?MODULE,Name), + register(RegName, self()), process_flag(trap_exit, true), process_flag(message_queue_data, off_heap), @@ -261,10 +262,12 @@ init([Name, Config = #{config := HConfig}, enter_loop(Config1, State1) catch _:Error -> + unregister(RegName), logger_h_common:error_notify({init_handler,Name,Error}), proc_lib:init_ack(Error) end; Error -> + unregister(RegName), logger_h_common:error_notify({init_handler,Name,Error}), proc_lib:init_ack(Error) end. @@ -415,6 +418,7 @@ terminate(Reason, State = #{id:=Name, file_ctrl_pid:=FWPid, false -> ok end, + unregister(?name_to_reg_name(?MODULE, Name)), logger_h_common:stop_or_restart(Name, Reason, State). code_change(_OldVsn, State, _Extra) -> diff --git a/lib/kernel/test/logger_disk_log_h_SUITE.erl b/lib/kernel/test/logger_disk_log_h_SUITE.erl index 4c6fa1b5af..7e5b574869 100644 --- a/lib/kernel/test/logger_disk_log_h_SUITE.erl +++ b/lib/kernel/test/logger_disk_log_h_SUITE.erl @@ -1066,7 +1066,7 @@ kill_disabled(cleanup, _Config) -> ok = stop_handler(?MODULE). qlen_kill_new(Config) -> - {_Log,HConfig,DLHConfig} = start_handler(?MODULE, ?FUNCTION_NAME, Config), + {Log,HConfig,DLHConfig} = start_handler(?MODULE, ?FUNCTION_NAME, Config), Pid0 = whereis(h_proc_name()), {_,Mem0} = process_info(Pid0, memory), RestartAfter = ?OVERLOAD_KILL_RESTART_AFTER, @@ -1079,7 +1079,7 @@ qlen_kill_new(Config) -> ok = logger:set_handler_config(?MODULE, NewHConfig), MRef = erlang:monitor(process, Pid0), NumOfReqs = 100, - Procs = 2, + Procs = 4, send_burst({n,NumOfReqs}, {spawn,Procs,0}, {chars,79}, notice), %% send_burst({n,NumOfReqs}, seq, {chars,79}, notice), receive @@ -1090,8 +1090,8 @@ qlen_kill_new(Config) -> killed -> ct:pal("Slow shutdown, handler process was killed!", []) end, - timer:sleep(RestartAfter + 2000), - true = is_pid(whereis(h_proc_name())), + file_delete(Log), + {ok,_} = wait_for_process_up(RestartAfter * 3), ok after 5000 -> @@ -1103,7 +1103,7 @@ qlen_kill_new(cleanup, _Config) -> ok = stop_handler(?MODULE). mem_kill_new(Config) -> - {_Log,HConfig,DLHConfig} = start_handler(?MODULE, ?FUNCTION_NAME, Config), + {Log,HConfig,DLHConfig} = start_handler(?MODULE, ?FUNCTION_NAME, Config), Pid0 = whereis(h_proc_name()), {_,Mem0} = process_info(Pid0, memory), RestartAfter = ?OVERLOAD_KILL_RESTART_AFTER, @@ -1116,7 +1116,7 @@ mem_kill_new(Config) -> ok = logger:set_handler_config(?MODULE, NewHConfig), MRef = erlang:monitor(process, Pid0), NumOfReqs = 100, - Procs = 2, + Procs = 4, send_burst({n,NumOfReqs}, {spawn,Procs,0}, {chars,79}, notice), %% send_burst({n,NumOfReqs}, seq, {chars,79}, notice), receive @@ -1127,8 +1127,8 @@ mem_kill_new(Config) -> killed -> ct:pal("Slow shutdown, handler process was killed!", []) end, - timer:sleep(RestartAfter + 2000), - true = is_pid(whereis(h_proc_name())), + file_delete(Log), + {ok,_} = wait_for_process_up(RestartAfter * 3), ok after 5000 -> @@ -1139,6 +1139,8 @@ mem_kill_new(Config) -> mem_kill_new(cleanup, _Config) -> ok = stop_handler(?MODULE). +restart_after() -> + [{timetrap,{minutes,2}}]. restart_after(Config) -> {Log,HConfig,DLHConfig} = start_handler(?MODULE, ?FUNCTION_NAME, Config), NewHConfig1 = @@ -1148,14 +1150,16 @@ restart_after(Config) -> ok = logger:set_handler_config(?MODULE, NewHConfig1), MRef1 = erlang:monitor(process, whereis(h_proc_name())), %% kill handler - send_burst({n,100}, {spawn,2,0}, {chars,79}, notice), + send_burst({n,100}, {spawn,4,0}, {chars,79}, notice), receive - {'DOWN', MRef1, _, _, _Info1} -> - timer:sleep(?OVERLOAD_KILL_RESTART_AFTER + 1000), - undefined = whereis(h_proc_name()), + {'DOWN', MRef1, _, _, _Reason1} -> + file_delete(Log), + error = wait_for_process_up(?OVERLOAD_KILL_RESTART_AFTER * 3), ok after 5000 -> + Info1 = logger_std_h:info(?MODULE), + ct:pal("Handler state = ~p", [Info1]), ct:fail("Handler not dead! It should not have survived this!") end, @@ -1169,16 +1173,17 @@ restart_after(Config) -> Pid0 = whereis(h_proc_name()), MRef2 = erlang:monitor(process, Pid0), %% kill handler - send_burst({n,100}, {spawn,2,0}, {chars,79}, notice), + send_burst({n,100}, {spawn,4,0}, {chars,79}, notice), receive - {'DOWN', MRef2, _, _, _Info2} -> - timer:sleep(RestartAfter + 2000), - Pid1 = whereis(h_proc_name()), - true = is_pid(Pid1), + {'DOWN', MRef2, _, _, _Reason2} -> + file_delete(Log), + {ok,Pid1} = wait_for_process_up(RestartAfter * 3), false = (Pid1 == Pid0), ok after 5000 -> + Info2 = logger_std_h:info(?MODULE), + ct:pal("Handler state = ~p", [Info2]), ct:fail("Handler not dead! It should not have survived this!") end, ok. @@ -1283,13 +1288,9 @@ send_n_burst(N, seq, Text, Class) -> send_n_burst(N-1, seq, Text, Class); send_n_burst(N, {spawn,Ps,TO}, Text, Class) -> ct:pal("~w processes each sending ~w messages", [Ps,N]), - PerProc = fun() -> - process_flag(priority,high), - send_n_burst(N, seq, Text, Class) - end, MRefs = [begin if TO == 0 -> ok; true -> timer:sleep(TO) end, - monitor(process,spawn_link(PerProc)) end || - _ <- lists:seq(1,Ps)], + monitor(process,spawn_link(per_proc_fun(N,Text,Class,X))) + end || X <- lists:seq(1,Ps)], lists:foreach(fun(MRef) -> receive {'DOWN', MRef, _, _, _} -> @@ -1308,6 +1309,16 @@ send_t_burst(T0, T, Text, Class, N) -> send_t_burst(T0, T, Text, Class, N+1) end. +per_proc_fun(N,Text,Class,X) when X rem 2 == 0 -> + fun() -> + process_flag(priority,high), + send_n_burst(N, seq, Text, Class) + end; +per_proc_fun(N,Text,Class,_) -> + fun() -> + send_n_burst(N, seq, Text, Class) + end. + %%%----------------------------------------------------------------- %%% Formatter callback %%% Using this to send the formatted string back to the test case @@ -1542,3 +1553,23 @@ h_proc_name(Name) -> file_delete(Log) -> file:delete(Log). + +wait_for_process_up(T) -> + wait_for_process_up(h_proc_name(),T). + +wait_for_process_up(Name,T) -> + N = (T div 500) + 1, + wait_for_process_up1(Name,N). + +wait_for_process_up1(Name,0) -> + error; +wait_for_process_up1(Name,N) -> + timer:sleep(500), + case whereis(Name) of + Pid when is_pid(Pid) -> + %% ct:pal("Process ~p up (~p tries left)",[Name,N]), + {ok,Pid}; + undefined -> + %% ct:pal("Waiting for process ~p (~p tries left)",[Name,N]), + wait_for_process_up1(Name,N-1) + end. diff --git a/lib/kernel/test/logger_std_h_SUITE.erl b/lib/kernel/test/logger_std_h_SUITE.erl index 134358bb64..ca54458ac1 100644 --- a/lib/kernel/test/logger_std_h_SUITE.erl +++ b/lib/kernel/test/logger_std_h_SUITE.erl @@ -992,7 +992,7 @@ qlen_kill_new(Config) -> ct:pal("Slow shutdown, handler process was killed!", []) end, file_delete(Log), - {ok,_} = wait_for_process_up(h_proc_name(), RestartAfter * 3), + {ok,_} = wait_for_process_up(RestartAfter * 3), ok after 5000 -> @@ -1043,7 +1043,7 @@ mem_kill_new(Config) -> ct:pal("Slow shutdown, handler process was killed!", []) end, file_delete(Log), - {ok,_} = wait_for_process_up(h_proc_name(), RestartAfter * 3), + {ok,_} = wait_for_process_up(RestartAfter * 3), ok after 5000 -> @@ -1074,7 +1074,7 @@ restart_after(Config) -> receive {'DOWN', MRef1, _, _, _Reason1} -> file_delete(Log), - error = wait_for_process_up(h_proc_name(),?OVERLOAD_KILL_RESTART_AFTER * 3), + error = wait_for_process_up(?OVERLOAD_KILL_RESTART_AFTER * 3), ok after 5000 -> @@ -1097,7 +1097,7 @@ restart_after(Config) -> receive {'DOWN', MRef2, _, _, _Reason2} -> file_delete(Log), - {ok,Pid1} = wait_for_process_up(h_proc_name(),RestartAfter * 3), + {ok,Pid1} = wait_for_process_up(RestartAfter * 3), false = (Pid1 == Pid0), ok after @@ -1254,13 +1254,9 @@ send_n_burst(N, seq, Text, Class) -> send_n_burst(N-1, seq, Text, Class); send_n_burst(N, {spawn,Ps,TO}, Text, Class) -> ct:pal("~w processes each sending ~w messages", [Ps,N]), - PerProc = fun() -> - process_flag(priority,high), - send_n_burst(N, seq, Text, Class) - end, MRefs = [begin if TO == 0 -> ok; true -> timer:sleep(TO) end, - monitor(process,spawn_link(PerProc)) end || - _ <- lists:seq(1,Ps)], + monitor(process,spawn_link(per_proc_fun(N,Text,Class,X))) + end || X <- lists:seq(1,Ps)], lists:foreach(fun(MRef) -> receive {'DOWN', MRef, _, _, _} -> @@ -1279,6 +1275,16 @@ send_t_burst(T0, T, Text, Class, N) -> send_t_burst(T0, T, Text, Class, N+1) end. +per_proc_fun(N,Text,Class,X) when X rem 2 == 0 -> + fun() -> + process_flag(priority,high), + send_n_burst(N, seq, Text, Class) + end; +per_proc_fun(N,Text,Class,_) -> + fun() -> + send_n_burst(N, seq, Text, Class) + end. + %%%----------------------------------------------------------------- %%% Formatter callback %%% Using this to send the formatted string back to the test case @@ -1567,6 +1573,9 @@ h_proc_name(Name) -> file_delete(Log) -> file:delete(Log). +wait_for_process_up(T) -> + wait_for_process_up(h_proc_name(),T). + wait_for_process_up(Name,T) -> N = (T div 500) + 1, wait_for_process_up1(Name,N). @@ -1577,8 +1586,10 @@ wait_for_process_up1(Name,N) -> timer:sleep(500), case whereis(Name) of Pid when is_pid(Pid) -> + %% ct:pal("Process ~p up (~p tries left)",[Name,N]), {ok,Pid}; undefined -> + %% ct:pal("Waiting for process ~p (~p tries left)",[Name,N]), wait_for_process_up1(Name,N-1) end. |