Skip to content

Commit

Permalink
Merge branch 'sverker/erts/multi-trace-27.0'
Browse files Browse the repository at this point in the history
  • Loading branch information
sverker committed Apr 30, 2024
2 parents c5d4e73 + dd3b041 commit b8d646f
Show file tree
Hide file tree
Showing 9 changed files with 145 additions and 81 deletions.
6 changes: 2 additions & 4 deletions erts/emulator/beam/beam_bp.c
Original file line number Diff line number Diff line change
Expand Up @@ -961,7 +961,7 @@ do_session_breakpoint(Process *c_p, ErtsCodeInfo *info, Eterm *reg,
ErtsTracerRef* ref;
Uint bp_flags;

if (erts_atomic_read_nob(&g->session->state) != ERTS_TRACE_SESSION_ALIVE) {
if (!erts_is_trace_session_alive(g->session)) {
return 0;
}

Expand Down Expand Up @@ -2068,9 +2068,7 @@ Eterm erts_make_bp_session_list(ErtsHeapFactory * factory,
Eterm list = tail;

for (g = ci->gen_bp ; g; g = g->next) {
if (erts_atomic_read_nob(&g->session->state)
== ERTS_TRACE_SESSION_ALIVE) {

if (erts_is_trace_session_alive(g->session)) {
Eterm *hp = erts_produce_heap(factory,
ERTS_TRACE_SESSION_WEAK_REF_SZ+2, 0);
Eterm weak_ref = erts_make_trace_session_weak_ref(g->session, &hp);
Expand Down
81 changes: 61 additions & 20 deletions erts/emulator/beam/erl_bif_trace.c
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,8 @@ int erts_trace_session_init(ErtsTraceSession* s, ErtsTracer tracer,
/*
* Does refc++ on returned trace session.
*/
static int term_to_session(Eterm term, ErtsTraceSession **session_p)
static int term_to_session(Eterm term, ErtsTraceSession **session_p,
int allow_dead)
{
ErtsTraceSession *s = NULL;
Binary *bin;
Expand All @@ -190,6 +191,10 @@ static int term_to_session(Eterm term, ErtsTraceSession **session_p)
for (s = erts_trace_session_0.next; s; s = s->next) {
ASSERT(s != &erts_trace_session_0);
if (s->name_atom == name && s->weak_id == weak_id) {
if (!allow_dead && !erts_is_trace_session_alive(s)) {
s = NULL;
break;
}
bin = &ERTS_MAGIC_BIN_FROM_DATA(s)->binary;
/*
* Make sure we don't resurrect a dying session with refc==0.
Expand All @@ -212,7 +217,10 @@ static int term_to_session(Eterm term, ErtsTraceSession **session_p)
s = (ErtsTraceSession*) ERTS_MAGIC_BIN_DATA(bin);
ASSERT(s != &erts_trace_session_0);

if (s->name_atom != weak_tpl[1] || s->weak_id != weak_tpl[2]) {
if (s->name_atom != weak_tpl[1]
|| s->weak_id != weak_tpl[2]
|| (!allow_dead && !erts_is_trace_session_alive(s))) {

return 0;
}

Expand Down Expand Up @@ -269,9 +277,8 @@ erts_internal_trace_pattern_4(BIF_ALIST_4)
{
ErtsTraceSession* session;

if (!term_to_session(BIF_ARG_1, &session)) {
BIF_P->fvalue = am_session;
BIF_ERROR(BIF_P, BADARG | EXF_HAS_EXT_INFO);
if (!term_to_session(BIF_ARG_1, &session, 0)) {
goto session_error;
}

if (!erts_try_seize_code_mod_permission(BIF_P)) {
Expand All @@ -280,7 +287,18 @@ erts_internal_trace_pattern_4(BIF_ALIST_4)
BIF_P, BIF_ARG_1, BIF_ARG_2, BIF_ARG_3, BIF_ARG_4);
}

/* Double check liveness with seized code mod permission */
if (!erts_is_trace_session_alive(session)) {
erts_release_code_mod_permission();
erts_deref_trace_session(session);
goto session_error;
}

return trace_pattern(BIF_P, session, BIF_ARG_2, BIF_ARG_3, BIF_ARG_4);

session_error:
BIF_P->fvalue = am_session;
BIF_ERROR(BIF_P, BADARG | EXF_HAS_EXT_INFO);
}

static Eterm
Expand Down Expand Up @@ -847,20 +865,30 @@ Eterm erts_internal_trace_4(BIF_ALIST_4)
ErtsTraceSession* session;
Eterm ret;

if (!term_to_session(BIF_ARG_1, &session)) {
BIF_P->fvalue = am_session;
BIF_ERROR(BIF_P, BADARG | EXF_HAS_EXT_INFO);
if (!term_to_session(BIF_ARG_1, &session, 0)) {
goto session_error;
}
if (!erts_try_seize_code_mod_permission(BIF_P)) {
erts_deref_trace_session(session);
ERTS_BIF_YIELD4(BIF_TRAP_EXPORT(BIF_erts_internal_trace_4),
BIF_P, BIF_ARG_1, BIF_ARG_2, BIF_ARG_3, BIF_ARG_4);
}

/* Double check liveness with seized code mod permission */
if (!erts_is_trace_session_alive(session)) {
erts_release_code_mod_permission();
erts_deref_trace_session(session);
goto session_error;
}

ret = trace(BIF_P, session, BIF_ARG_2, BIF_ARG_3, BIF_ARG_4);

erts_deref_trace_session(session);
return ret;

session_error:
BIF_P->fvalue = am_session;
BIF_ERROR(BIF_P, BADARG | EXF_HAS_EXT_INFO);
}

static
Expand Down Expand Up @@ -1135,7 +1163,7 @@ tracer_session_destructor(Binary *bin)
{
ErtsTraceSession *s = (ErtsTraceSession*) ERTS_MAGIC_BIN_DATA(bin);

if (erts_atomic_read_nob(&s->state) == ERTS_TRACE_SESSION_ALIVE) {
if (erts_is_trace_session_alive(s)) {
/*
* trace_session_destroy() not called.
* We must initiate cleanup here without a process.
Expand Down Expand Up @@ -1224,13 +1252,13 @@ Eterm
erts_internal_trace_session_destroy_1(BIF_ALIST_1)
{
ErtsTraceSession* session;
if (!term_to_session(BIF_ARG_1, &session)) {
if (!term_to_session(BIF_ARG_1, &session, 1)) {
BIF_P->fvalue = am_badopt;
BIF_ERROR(BIF_P, BADARG | EXF_HAS_EXT_INFO);
}
if (erts_atomic_read_nob(&session->state) != ERTS_TRACE_SESSION_ALIVE) {
if (!erts_is_trace_session_alive(session)) {
erts_deref_trace_session(session);
BIF_RET(am_ok);
BIF_RET(am_false);
}
if (!erts_try_seize_code_mod_permission(BIF_P)) {
erts_deref_trace_session(session);
Expand All @@ -1252,13 +1280,13 @@ erts_internal_trace_session_destroy_1(BIF_ALIST_1)

erts_proc_inc_refc(BIF_P);
erts_suspend(BIF_P, ERTS_PROC_LOCK_MAIN, NULL);
ERTS_BIF_YIELD_RETURN(BIF_P, am_ok);
ERTS_BIF_YIELD_RETURN(BIF_P, am_true);
}
else {
erts_release_code_mod_permission();
erts_deref_trace_session(erts_staging_trace_session);
}
BIF_RET(am_ok);
BIF_RET(am_false);
}

static void trace_session_destroy_aux(void *session_v)
Expand All @@ -1272,6 +1300,10 @@ static void trace_session_destroy_aux(void *session_v)

erts_lc_soften_code_mod_permission_check();

/*
* We came here from destructor as refc==0 and session was ALIVE.
* No one else could have done anything to the session.
*/
ASSERT(erts_atomic_read_nob(&s->state) == ERTS_TRACE_SESSION_ALIVE);
erts_atomic_set_nob(&s->state, ERTS_TRACE_SESSION_CLEARING);

Expand Down Expand Up @@ -1339,9 +1371,8 @@ Eterm erts_internal_trace_info_3(BIF_ALIST_3)
if (BIF_ARG_1 == am_any) {
session = NULL;
}
else if (!term_to_session(BIF_ARG_1, &session)) {
BIF_P->fvalue = am_session;
BIF_ERROR(BIF_P, BADARG | EXF_HAS_EXT_INFO);
else if (!term_to_session(BIF_ARG_1, &session, 0)) {
goto session_error;
}

if (!erts_try_seize_code_mod_permission(BIF_P)) {
Expand All @@ -1351,12 +1382,24 @@ Eterm erts_internal_trace_info_3(BIF_ALIST_3)
ERTS_BIF_YIELD3(BIF_TRAP_EXPORT(BIF_erts_internal_trace_info_3),
BIF_P, BIF_ARG_1, BIF_ARG_2, BIF_ARG_3);
}

/* Double check session liveness with seized code mod permission */
if (session && !erts_is_trace_session_alive(session)) {
erts_release_code_mod_permission();
erts_deref_trace_session(session);
goto session_error;
}

ret = trace_info(BIF_P, session, BIF_ARG_2, BIF_ARG_3);
erts_release_code_mod_permission();
if (session) {
erts_deref_trace_session(session);
}
return ret;

session_error:
BIF_P->fvalue = am_session;
BIF_ERROR(BIF_P, BADARG | EXF_HAS_EXT_INFO);
}

static
Expand Down Expand Up @@ -1477,9 +1520,7 @@ build_trace_sessions_term(Eterm **hpp, Uint *szp, ErtsPTabElementCommon *t_p)
}

for (ref = t_p->tracee.first_ref; ref; ref = ref->next) {
if (erts_atomic_read_nob(&ref->session->state)
== ERTS_TRACE_SESSION_ALIVE) {

if (erts_is_trace_session_alive(ref->session)) {
sz += ERTS_TRACE_SESSION_WEAK_REF_SZ + 2;
if (hp) {
Eterm weak_ref = erts_make_trace_session_weak_ref(ref->session, &hp);
Expand Down
1 change: 1 addition & 0 deletions erts/emulator/beam/erl_db_util.c
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,7 @@ set_match_trace(Process *tracee_p, Eterm fail_term, ErtsTracer tracer,
|| erts_thr_progress_is_blocking());

if (ERTS_TRACER_IS_NIL(tracer)
|| !erts_is_trace_session_alive(session)
|| erts_is_tracer_enabled(tracer, &tracee_p->common))
return set_tracee_flags(tracee_p, tracer, session, d_flags, e_flags);
return fail_term;
Expand Down
30 changes: 15 additions & 15 deletions erts/emulator/beam/erl_trace.c
Original file line number Diff line number Diff line change
Expand Up @@ -3003,8 +3003,6 @@ is_tracer_ref_enabled(Process* c_p, ErtsProcLocks c_p_locks,
ErtsTracerNif **tnif_ret,
enum ErtsTracerOpt topt, Eterm tag)
{
Eterm nif_result;

ASSERT(t_p);
ASSERT(ref);

Expand All @@ -3023,18 +3021,20 @@ is_tracer_ref_enabled(Process* c_p, ErtsProcLocks c_p_locks,
}
#endif

nif_result = call_enabled_tracer(ref->tracer, tnif_ret,
if (erts_is_trace_session_alive(ref->session)) {
Eterm nif_result = call_enabled_tracer(ref->tracer, tnif_ret,
topt, tag, t_p->id);
switch (nif_result) {
case am_discard: return 0;
case am_trace: return 1;
case THE_NON_VALUE:
case am_remove: ASSERT(tag == am_trace_status); break;
default:
/* only am_remove should be returned, but if
something else is returned we fall-through
and remove the tracer. */
ASSERT(0);
switch (nif_result) {
case am_discard: return 0;
case am_trace: return 1;
case THE_NON_VALUE:
case am_remove: ASSERT(tag == am_trace_status); break;
default:
/* only am_remove should be returned, but if
something else is returned we fall-through
and remove the tracer. */
ASSERT(0);
}
}

/* Only remove tracer on (self() or ports) AND we are on a normal scheduler */
Expand Down Expand Up @@ -3352,7 +3352,7 @@ ErtsTracerRef* new_tracer_ref(ErtsPTabElementCommon* t_p,
ErtsTracerRef *ref = t_p->tracee.first_ref;

ASSERT(get_tracer_ref(t_p, session) == NULL);
ASSERT(erts_atomic_read_nob(&session->state) == ERTS_TRACE_SESSION_ALIVE);
ASSERT(erts_is_trace_session_alive(session));

ref = erts_alloc(ERTS_ALC_T_HEAP_FRAG, // ToDo type?
sizeof(ErtsTracerRef));
Expand Down Expand Up @@ -3425,7 +3425,7 @@ Uint delete_unalive_trace_refs(ErtsPTabElementCommon* t_p)
next_ref = ref->next;

ASSERT(ref->session);
if (erts_atomic_read_nob(&ref->session->state) == ERTS_TRACE_SESSION_ALIVE) {
if (erts_is_trace_session_alive(ref->session)) {
prev_p = &ref->next;
} else {
dbg_remove_p_ref(t_p, ref);
Expand Down
10 changes: 10 additions & 0 deletions erts/emulator/beam/erl_trace.h
Original file line number Diff line number Diff line change
Expand Up @@ -296,4 +296,14 @@ ERTS_DECLARE_DUMMY(erts_tracer_nil) = NIL;
#define ERTS_TRACER_FROM_ETERM(termp) \
((ErtsTracer*)(termp))

ERTS_GLB_INLINE Eterm erts_is_trace_session_alive(ErtsTraceSession*);
#if ERTS_GLB_INLINE_INCL_FUNC_DEF
ERTS_GLB_INLINE Eterm erts_is_trace_session_alive(ErtsTraceSession *s) {
return ERTS_LIKELY(erts_atomic_read_nob(&s->state)
== ERTS_TRACE_SESSION_ALIVE);

}
#endif


#endif /* ERL_TRACE_H__ */
42 changes: 21 additions & 21 deletions erts/emulator/test/trace_session_SUITE.erl
Original file line number Diff line number Diff line change
Expand Up @@ -205,9 +205,9 @@ test_set_on_spawn(_Config) ->
set_on_spawn2(S0, Tracer0, [{tracer,Tracer0}],
S1, Tracer1, []),

ok = trace:session_destroy(S0),
ok = trace:session_destroy(S1),
ok = trace:session_destroy(S2),
true = trace:session_destroy(S0),
true = trace:session_destroy(S1),
true = trace:session_destroy(S2),

unlink(Tracer0),
exit(Tracer0, die),
Expand Down Expand Up @@ -238,9 +238,9 @@ test_set_on_first_spawn(_Config) ->
set_on_first_spawn2(S0, Tracer0, [{tracer,Tracer0}],
S1, Tracer1, []),

ok = trace:session_destroy(S0),
ok = trace:session_destroy(S1),
ok = trace:session_destroy(S2),
true = trace:session_destroy(S0),
true = trace:session_destroy(S1),
true = trace:session_destroy(S2),

unlink(Tracer0),
exit(Tracer0, die),
Expand Down Expand Up @@ -270,9 +270,9 @@ test_set_on_link(_Config) ->
S0, Tracer0, [{tracer,Tracer0}]),
set_on_link2(S0, Tracer0, [{tracer,Tracer0}],
S1, Tracer1, []),
ok = trace:session_destroy(S0),
ok = trace:session_destroy(S1),
ok = trace:session_destroy(S2),
true = trace:session_destroy(S0),
true = trace:session_destroy(S1),
true = trace:session_destroy(S2),

unlink(Tracer0),
exit(Tracer0, die),
Expand Down Expand Up @@ -303,9 +303,9 @@ test_set_on_first_link(_Config) ->
S0, Tracer0, [{tracer,Tracer0}]),
set_on_first_link2(S0, Tracer0, [{tracer,Tracer0}],
S1, Tracer1, []),
ok = trace:session_destroy(S0),
ok = trace:session_destroy(S1),
ok = trace:session_destroy(S2),
true = trace:session_destroy(S0),
true = trace:session_destroy(S1),
true = trace:session_destroy(S2),

unlink(Tracer0),
exit(Tracer0, die),
Expand Down Expand Up @@ -817,9 +817,9 @@ procs(_Config) ->
procs_do2(S0, Tracer0, [{tracer,Tracer0}],
S1, Tracer1, []),

ok = trace:session_destroy(S0),
ok = trace:session_destroy(S1),
ok = trace:session_destroy(S2),
true = trace:session_destroy(S0),
true = trace:session_destroy(S1),
true = trace:session_destroy(S2),

unlink(Tracer0),
exit(Tracer0, die),
Expand Down Expand Up @@ -953,9 +953,9 @@ basic(_Config) ->
basic_do2(S0, Tracer0, [{tracer,Tracer0}],
S1, Tracer1, []),

ok = trace:session_destroy(S0),
ok = trace:session_destroy(S1),
ok = trace:session_destroy(S2),
true = trace:session_destroy(S0),
true = trace:session_destroy(S1),
true = trace:session_destroy(S2),

unlink(Tracer0),
exit(Tracer0, die),
Expand Down Expand Up @@ -1052,9 +1052,9 @@ call(_Config) ->
{[local], fun() -> ?MODULE:foo() end}]
],

ok = trace:session_destroy(S0),
ok = trace:session_destroy(S1),
ok = trace:session_destroy(S2),
true = trace:session_destroy(S0),
true = trace:session_destroy(S1),
true = trace:session_destroy(S2),

unlink(Tracer0),
exit(Tracer0, die),
Expand Down
Loading

0 comments on commit b8d646f

Please sign in to comment.