From 771abbd23709b5a03416278595588931889ab7c5 Mon Sep 17 00:00:00 2001 From: Sverker Eriksson Date: Wed, 20 Sep 2017 15:06:07 +0200 Subject: erts: Keep magic ref to DistEntry in net_kernel to make sure it's kept alive. --- erts/emulator/beam/dist.c | 22 +++++++++++++++++----- erts/emulator/beam/dist.h | 24 ++++++++++++++++-------- erts/emulator/beam/erl_node_tables.c | 30 ++++++++++++++---------------- erts/emulator/beam/erl_node_tables.h | 1 + 4 files changed, 48 insertions(+), 29 deletions(-) (limited to 'erts') diff --git a/erts/emulator/beam/dist.c b/erts/emulator/beam/dist.c index 474b0e8364..c16579037c 100644 --- a/erts/emulator/beam/dist.c +++ b/erts/emulator/beam/dist.c @@ -3426,6 +3426,8 @@ BIF_RETTYPE new_connection_id_1(BIF_ALIST_1) { DistEntry* dep; Uint32 conn_id; + Eterm* hp; + Eterm dhandle; if (is_not_atom(BIF_ARG_1)) { BIF_ERROR(BIF_P, BADARG); @@ -3449,17 +3451,25 @@ BIF_RETTYPE new_connection_id_1(BIF_ALIST_1) conn_id = dep->connection_id; } erts_de_rwunlock(dep); - BIF_RET(make_small(conn_id)); + hp = HAlloc(BIF_P, 3 + ERTS_MAGIC_REF_THING_SIZE); + dhandle = erts_build_dhandle(&hp, &BIF_P->off_heap, dep); + erts_deref_dist_entry(dep); + BIF_RET(TUPLE2(hp, make_small(conn_id), dhandle)); } BIF_RETTYPE abort_connection_id_2(BIF_ALIST_2) { DistEntry* dep; + Eterm* tp; - if (is_not_atom(BIF_ARG_1) || is_not_small(BIF_ARG_2)) { + if (is_not_atom(BIF_ARG_1) || is_not_tuple_arity(BIF_ARG_2, 2)) { BIF_ERROR(BIF_P, BADARG); } - dep = erts_find_dist_entry(BIF_ARG_1); + tp = tuple_val(BIF_ARG_2); + dep = erts_dhandle_to_dist_entry(tp[2]); + if (is_not_small(tp[1]) || dep != erts_find_dist_entry(BIF_ARG_1)) { + BIF_ERROR(BIF_P, BADARG); + } ASSERT(dep != erts_this_dist_entry); /* SVERK: What to do? */ if (!dep) { @@ -3469,7 +3479,7 @@ BIF_RETTYPE abort_connection_id_2(BIF_ALIST_2) erts_de_rwlock(dep); if (dep->status == ERTS_DE_SFLG_PENDING - && dep->connection_id == unsigned_val(BIF_ARG_2)) { + && dep->connection_id == unsigned_val(tp[1])) { NetExitsContext nec = {dep}; ErtsLink *nlinks; @@ -3736,10 +3746,12 @@ monitor_node(Process* p, Eterm Node, Eterm Bool, Eterm Options) ++ERTS_LINK_REFC(lnk); lnk = erts_add_or_lookup_link(&ERTS_P_LINKS(p), LINK_NODE, Node); ++ERTS_LINK_REFC(lnk); + erts_de_links_unlock(dep); break; default: ERTS_ASSERT(! "Invalid dsig prepare result"); } + erts_deref_dist_entry(dep); } else { /* Bool == false */ dep = erts_sysname_to_connected_dist_entry(Node); @@ -3777,9 +3789,9 @@ monitor_node(Process* p, Eterm Node, Eterm Bool, Eterm Options) Node)); } } + erts_de_links_unlock(dep); } - erts_de_links_unlock(dep); erts_proc_unlock(p, ERTS_PROC_LOCK_LINK); done: diff --git a/erts/emulator/beam/dist.h b/erts/emulator/beam/dist.h index f9a2037687..2ead588ee9 100644 --- a/erts/emulator/beam/dist.h +++ b/erts/emulator/beam/dist.h @@ -161,6 +161,7 @@ erts_dsig_prepare(ErtsDSigData *dsdp, int connect) { DistEntry* dep = *depp; + int deref_dep = 0; int res; if (!erts_is_alive) @@ -171,6 +172,7 @@ erts_dsig_prepare(ErtsDSigData *dsdp, dep = erts_find_or_insert_dist_entry(dsdp->node); ASSERT(dep != erts_this_dist_entry); /* SVERK: What to do? */ + deref_dep = 1; } #ifdef ERTS_ENABLE_LOCK_CHECK @@ -208,7 +210,7 @@ retry: Eterm *hp; ErlOffHeap *ohp; ErtsMessage *mp; - Eterm msg, conn_id; + Eterm msg, conn_id, dhandle; dep->status = ERTS_DE_SFLG_PENDING; dep->flags = (DFLAG_DIST_MANDATORY | DFLAG_DIST_HOPEFULLY); @@ -220,16 +222,18 @@ retry: net_kernel = erts_whereis_process(proc, proc_locks, am_net_kernel, nk_locks, 0); if (!net_kernel) { - if (!*depp) { - erts_deref_dist_entry(dep); - } + if (deref_dep) + erts_deref_dist_entry(dep); return ERTS_DSIG_PREP_NOT_ALIVE; } - /* Send {auto_connect, Node, ConnId} to net_kernel */ - mp = erts_alloc_message_heap(net_kernel, &nk_locks, 4, &hp, &ohp); - msg = TUPLE3(hp, am_auto_connect, dep->sysname, conn_id); - erts_queue_message(net_kernel, nk_locks, mp, msg, proc->common.id); + /* Send {auto_connect, Node, ConnId, DHandle} to net_kernel */ + mp = erts_alloc_message_heap(net_kernel, &nk_locks, + 5 + ERTS_MAGIC_REF_THING_SIZE, + &hp, &ohp); + dhandle = erts_build_dhandle(&hp, ohp, dep); + msg = TUPLE4(hp, am_auto_connect, dep->sysname, conn_id, dhandle); + erts_queue_message(net_kernel, nk_locks, mp, msg, proc->common.id); erts_proc_unlock(net_kernel, nk_locks); } else @@ -255,6 +259,8 @@ retry: dsdp->no_suspend = no_suspend; if (dspl == ERTS_DSP_NO_LOCK) erts_de_runlock(dep); + if (deref_dep) + erts_deref_dist_entry(dep); *depp = dep; return res; @@ -263,6 +269,8 @@ retry: erts_de_rwunlock(dep); else erts_de_runlock(dep); + if (deref_dep) + erts_deref_dist_entry(dep); return res; } diff --git a/erts/emulator/beam/erl_node_tables.c b/erts/emulator/beam/erl_node_tables.c index 17d410e42b..7c75ec60e9 100644 --- a/erts/emulator/beam/erl_node_tables.c +++ b/erts/emulator/beam/erl_node_tables.c @@ -141,9 +141,7 @@ dist_table_cmp(void *dep1, void *dep2) static void* dist_table_alloc(void *dep_tmpl) { -#ifdef DEBUG erts_aint_t refc; -#endif Eterm sysname; Binary *bin; DistEntry *dep; @@ -160,13 +158,8 @@ dist_table_alloc(void *dep_tmpl) dist_entries++; -#ifdef DEBUG - refc = -#else - (void) -#endif - de_refc_dec_read(dep, -1); - ASSERT(refc == -1); + refc = de_refc_dec_read(dep, -1); + ASSERT(refc == -1); (void)refc; dep->prev = NULL; erts_rwmtx_init_opt(&dep->rwmtx, &rwmtx_opt, "dist_entry", sysname, @@ -227,6 +220,8 @@ dist_table_free(void *vdep) { DistEntry *dep = (DistEntry *) vdep; + ASSERT(de_refc_read(dep, -1) == -1); + ASSERT(dep->status == 0); ASSERT(is_nil(dep->cid)); ASSERT(dep->nlinks == NULL); ASSERT(dep->node_links == NULL); @@ -387,16 +382,19 @@ erts_dhandle_to_dist_entry(Eterm dhandle) } Eterm -erts_make_dhandle(Process *c_p, DistEntry *dep) +erts_build_dhandle(Eterm **hpp, ErlOffHeap* ohp, DistEntry *dep) { - Binary *bin; - Eterm *hp; - - bin = ErtsDistEntry2Bin(dep); + Binary *bin = ErtsDistEntry2Bin(dep); ASSERT(bin); ASSERT(ERTS_MAGIC_BIN_DESTRUCTOR(bin) == erts_dist_entry_destructor); - hp = HAlloc(c_p, ERTS_MAGIC_REF_THING_SIZE); - return erts_mk_magic_ref(&hp, &c_p->off_heap, bin); + return erts_mk_magic_ref(hpp, ohp, bin); +} + +Eterm +erts_make_dhandle(Process *c_p, DistEntry *dep) +{ + Eterm *hp = HAlloc(c_p, ERTS_MAGIC_REF_THING_SIZE); + return erts_build_dhandle(&hp, &c_p->off_heap, dep); } static void start_timer_delete_dist_entry(void *vdep); diff --git a/erts/emulator/beam/erl_node_tables.h b/erts/emulator/beam/erl_node_tables.h index afa83f8b46..83d0678bbc 100644 --- a/erts/emulator/beam/erl_node_tables.h +++ b/erts/emulator/beam/erl_node_tables.h @@ -210,6 +210,7 @@ int erts_lc_is_de_rlocked(DistEntry *); #endif int erts_dist_entry_destructor(Binary *bin); DistEntry *erts_dhandle_to_dist_entry(Eterm dhandle); +Eterm erts_build_dhandle(Eterm **hpp, ErlOffHeap*, DistEntry*); Eterm erts_make_dhandle(Process *c_p, DistEntry *dep); void erts_ref_dist_entry(DistEntry *dep); void erts_deref_dist_entry(DistEntry *dep); -- cgit v1.2.3