aboutsummaryrefslogtreecommitdiffstats
path: root/erts/emulator
diff options
context:
space:
mode:
Diffstat (limited to 'erts/emulator')
-rw-r--r--erts/emulator/beam/bif.c58
-rw-r--r--erts/emulator/beam/erl_bif_info.c2
-rw-r--r--erts/emulator/beam/erl_trace.c44
-rw-r--r--erts/emulator/beam/erl_trace.h2
-rw-r--r--erts/emulator/test/system_info_SUITE.erl84
5 files changed, 122 insertions, 68 deletions
diff --git a/erts/emulator/beam/bif.c b/erts/emulator/beam/bif.c
index 457910f913..000397e790 100644
--- a/erts/emulator/beam/bif.c
+++ b/erts/emulator/beam/bif.c
@@ -4701,6 +4701,9 @@ BIF_RETTYPE system_flag_2(BIF_ALIST_2)
return erts_bind_schedulers(BIF_P, BIF_ARG_2);
} else if (ERTS_IS_ATOM_STR("erts_alloc", BIF_ARG_1)) {
return erts_alloc_set_dyn_param(BIF_P, BIF_ARG_2);
+ } else if (ERTS_IS_ATOM_STR("system_logger", BIF_ARG_1)) {
+ Eterm res = erts_set_system_logger(BIF_ARG_2);
+ if (is_value(res)) BIF_RET(res);
}
error:
BIF_ERROR(BIF_P, BADARG);
@@ -5203,61 +5206,6 @@ erts_call_dirty_bif(ErtsSchedulerData *esdp, Process *c_p, BeamInstr *I, Eterm *
return exiting;
}
-
-
-#ifdef HARDDEBUG
-/*
-You'll need this line in bif.tab to be able to use this debug bif
-
-bif erlang:send_to_logger/2
-
-*/
-BIF_RETTYPE send_to_logger_2(BIF_ALIST_2)
-{
- byte *buf;
- ErlDrvSizeT len;
- if (!is_atom(BIF_ARG_1) || !(is_list(BIF_ARG_2) ||
- is_nil(BIF_ARG_1))) {
- BIF_ERROR(BIF_P,BADARG);
- }
- if (erts_iolist_size(BIF_ARG_2, &len) != 0)
- BIF_ERROR(BIF_P,BADARG);
- else if (len == 0)
- buf = "";
- else {
-#ifdef DEBUG
- ErlDrvSizeT len2;
-#endif
- buf = (byte *) erts_alloc(ERTS_ALC_T_TMP, len+1);
-#ifdef DEBUG
- len2 =
-#else
- (void)
-#endif
- erts_iolist_to_buf(BIF_ARG_2, buf, len);
- ASSERT(len2 == len);
- buf[len] = '\0';
- switch (BIF_ARG_1) {
- case am_info:
- erts_send_info_to_logger(BIF_P->group_leader, buf, len);
- break;
- case am_warning:
- erts_send_warning_to_logger(BIF_P->group_leader, buf, len);
- break;
- case am_error:
- erts_send_error_to_logger(BIF_P->group_leader, buf, len);
- break;
- default:
- {
- BIF_ERROR(BIF_P,BADARG);
- }
- }
- erts_free(ERTS_ALC_T_TMP, (void *) buf);
- }
- BIF_RET(am_true);
-}
-#endif /* HARDDEBUG */
-
BIF_RETTYPE get_module_info_1(BIF_ALIST_1)
{
Eterm ret = erts_module_info_0(BIF_P, BIF_ARG_1);
diff --git a/erts/emulator/beam/erl_bif_info.c b/erts/emulator/beam/erl_bif_info.c
index 7fada0d548..9cc95a5c09 100644
--- a/erts/emulator/beam/erl_bif_info.c
+++ b/erts/emulator/beam/erl_bif_info.c
@@ -3139,6 +3139,8 @@ BIF_RETTYPE system_info_1(BIF_ALIST_1)
DECL_AM(tag);
BIF_RET(AM_tag);
#endif
+ } else if (ERTS_IS_ATOM_STR("system_logger", BIF_ARG_1)) {
+ BIF_RET(erts_get_system_logger());
}
BIF_ERROR(BIF_P, BADARG);
diff --git a/erts/emulator/beam/erl_trace.c b/erts/emulator/beam/erl_trace.c
index 2350d4c02f..701fb38147 100644
--- a/erts/emulator/beam/erl_trace.c
+++ b/erts/emulator/beam/erl_trace.c
@@ -72,6 +72,7 @@ static ErtsTracer default_port_tracer;
static Eterm system_monitor;
static Eterm system_profile;
+static erts_aint_t system_logger;
#ifdef HAVE_ERTS_NOW_CPU
int erts_cpu_timestamp;
@@ -340,6 +341,7 @@ void erts_init_trace(void) {
default_port_trace_flags = F_INITIAL_TRACE_FLAGS;
default_port_tracer = erts_tracer_nil;
system_seq_tracer = erts_tracer_nil;
+ erts_atomic_init_nob(&system_logger, am_logger);
init_sys_msg_dispatcher();
init_tracer_nif();
}
@@ -2027,10 +2029,24 @@ enqueue_sys_msg(enum ErtsSysMsgType type,
erts_mtx_unlock(&smq_mtx);
}
+Eterm
+erts_get_system_logger(void)
+{
+ return (Eterm)erts_atomic_read_nob(&system_logger);
+}
+
+Eterm
+erts_set_system_logger(Eterm logger)
+{
+ if (logger != am_logger && logger != am_undefined && !is_internal_pid(logger))
+ return THE_NON_VALUE;
+ return (Eterm)erts_atomic_xchg_nob(&system_logger, logger);
+}
+
void
erts_queue_error_logger_message(Eterm from, Eterm msg, ErlHeapFragment *bp)
{
- enqueue_sys_msg(SYS_MSG_TYPE_ERRLGR, from, am_logger, msg, bp);
+ enqueue_sys_msg(SYS_MSG_TYPE_ERRLGR, from, erts_get_system_logger(), msg, bp);
}
void
@@ -2271,7 +2287,7 @@ sys_msg_dispatcher_func(void *unused)
}
break;
case SYS_MSG_TYPE_ERRLGR:
- receiver = am_logger;
+ receiver = smqp->to;
break;
default:
receiver = NIL;
@@ -2285,8 +2301,15 @@ sys_msg_dispatcher_func(void *unused)
if (is_internal_pid(receiver)) {
proc = erts_pid2proc(NULL, 0, receiver, proc_locks);
if (!proc) {
- /* Bad tracer */
- goto failure;
+ if (smqp->type == SYS_MSG_TYPE_ERRLGR) {
+ /* Bad logger process, send to kernel 'logger' process */
+ erts_set_system_logger(am_logger);
+ receiver = erts_get_system_logger();
+ goto logger;
+ } else {
+ /* Bad tracer */
+ goto failure;
+ }
}
else {
ErtsMessage *mp;
@@ -2299,9 +2322,9 @@ sys_msg_dispatcher_func(void *unused)
#endif
erts_proc_unlock(proc, proc_locks);
}
- }
- else if (receiver == am_logger) {
- proc = erts_whereis_process(NULL,0,receiver,proc_locks,0);
+ } else if (receiver == am_logger) {
+ logger:
+ proc = erts_whereis_process(NULL,0,am_logger,proc_locks,0);
if (!proc)
goto failure;
else if (smqp->from == proc->common.id)
@@ -2309,7 +2332,10 @@ sys_msg_dispatcher_func(void *unused)
else
goto queue_proc_msg;
}
- else if (is_internal_port(receiver)) {
+ else if (receiver == am_undefined) {
+ goto drop_sys_msg;
+ }
+ else if (is_internal_port(receiver)) {
port = erts_thr_id2port_sflgs(receiver,
ERTS_PORT_SFLGS_INVALID_TRACER_LOOKUP);
if (!port)
@@ -2366,7 +2392,7 @@ erts_foreach_sys_msg_in_q(void (*func)(Eterm,
to = erts_get_system_profile();
break;
case SYS_MSG_TYPE_ERRLGR:
- to = am_logger;
+ to = erts_get_system_logger();
break;
default:
to = NIL;
diff --git a/erts/emulator/beam/erl_trace.h b/erts/emulator/beam/erl_trace.h
index bccf31606e..b7844d1cb0 100644
--- a/erts/emulator/beam/erl_trace.h
+++ b/erts/emulator/beam/erl_trace.h
@@ -94,6 +94,8 @@ void erts_foreach_sys_msg_in_q(void (*func)(Eterm,
Eterm,
Eterm,
ErlHeapFragment *));
+Eterm erts_set_system_logger(Eterm);
+Eterm erts_get_system_logger(void);
void erts_queue_error_logger_message(Eterm, Eterm, ErlHeapFragment *);
void erts_send_sys_msg_proc(Eterm, Eterm, Eterm, ErlHeapFragment *);
diff --git a/erts/emulator/test/system_info_SUITE.erl b/erts/emulator/test/system_info_SUITE.erl
index 21ab6b378a..4e663fed7f 100644
--- a/erts/emulator/test/system_info_SUITE.erl
+++ b/erts/emulator/test/system_info_SUITE.erl
@@ -37,8 +37,9 @@
-export([process_count/1, system_version/1, misc_smoke_tests/1,
heap_size/1, wordsize/1, memory/1, ets_limit/1, atom_limit/1,
- ets_count/1,
- atom_count/1]).
+ ets_count/1, atom_count/1, system_logger/1]).
+
+-export([init/1, handle_event/2, handle_call/2]).
suite() ->
[{ct_hooks,[ts_install_cth]},
@@ -46,8 +47,8 @@ suite() ->
all() ->
[process_count, system_version, misc_smoke_tests,
- ets_count,
- heap_size, wordsize, memory, ets_limit, atom_limit, atom_count].
+ ets_count, heap_size, wordsize, memory, ets_limit, atom_limit, atom_count,
+ system_logger].
%%%
%%% The test cases -------------------------------------------------------------
@@ -573,3 +574,78 @@ atom_count(Config) when is_list(Config) ->
true = Limit >= Count2,
true = Count2 > Count1,
ok.
+
+
+system_logger(Config) when is_list(Config) ->
+
+ TC = self(),
+
+ ok = error_logger:add_report_handler(?MODULE, [TC]),
+
+ generate_log_event(),
+
+ flush(1, report_handler),
+
+ Initial = erlang:system_info(system_logger),
+
+ {Logger,_} = spawn_monitor(fun F() -> receive M -> TC ! {system_logger,M}, F() end end),
+
+ Initial = erlang:system_flag(system_logger, Logger),
+ Logger = erlang:system_info(system_logger),
+
+ generate_log_event(),
+ flush(1, system_logger),
+
+ Logger = erlang:system_flag(system_logger, Logger),
+
+ generate_log_event(),
+ flush(1, system_logger),
+
+ exit(Logger, die),
+ receive {'DOWN',_,_,_,_} -> ok end,
+
+ generate_log_event(),
+ flush(1, report_handler),
+
+ logger = erlang:system_info(system_logger),
+
+ logger = erlang:system_flag(system_logger, undefined),
+ generate_log_event(),
+ flush(),
+
+ undefined = erlang:system_flag(system_logger, Initial),
+
+ ok.
+
+flush() ->
+ receive
+ M ->
+ ct:fail({unexpected_message, M})
+ after 0 ->
+ ok
+ end.
+
+flush(0, _Pat) ->
+ flush();
+flush(Cnt, Pat) ->
+ receive
+ M when element(1,M) =:= Pat ->
+ ct:log("~p",[M]),
+ flush(Cnt-1, Pat)
+ after 500 ->
+ ct:fail({missing, Cnt, Pat})
+ end.
+
+generate_log_event() ->
+ {_Pid, Ref} = spawn_monitor(fun() -> ok = nok end),
+ receive {'DOWN', Ref, _, _, _} -> ok end.
+
+init([To]) ->
+ {ok, To}.
+
+handle_call(Msg, State) ->
+ {ok, Msg, State}.
+
+handle_event(Event, State) ->
+ State ! {report_handler, Event},
+ {ok, State}.