summaryrefslogtreecommitdiff
path: root/erts
diff options
context:
space:
mode:
authorSverker Eriksson <sverker@erlang.org>2017-09-20 15:06:07 +0200
committerSverker Eriksson <sverker@erlang.org>2017-11-15 20:13:03 +0100
commit771abbd23709b5a03416278595588931889ab7c5 (patch)
tree75dc9fd1f206cdd95430a3832295bb9cc81298d3 /erts
parent08040e5c5cd329395d9d756f1fdf8d66ffbbe705 (diff)
downloaderlang-771abbd23709b5a03416278595588931889ab7c5.tar.gz
erts: Keep magic ref to DistEntry in net_kernel
to make sure it's kept alive.
Diffstat (limited to 'erts')
-rw-r--r--erts/emulator/beam/dist.c22
-rw-r--r--erts/emulator/beam/dist.h24
-rw-r--r--erts/emulator/beam/erl_node_tables.c30
-rw-r--r--erts/emulator/beam/erl_node_tables.h1
4 files changed, 48 insertions, 29 deletions
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);