aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSverker Eriksson <[email protected]>2017-09-20 15:06:07 +0200
committerSverker Eriksson <[email protected]>2017-11-15 20:13:03 +0100
commit771abbd23709b5a03416278595588931889ab7c5 (patch)
tree75dc9fd1f206cdd95430a3832295bb9cc81298d3
parent08040e5c5cd329395d9d756f1fdf8d66ffbbe705 (diff)
downloadotp-771abbd23709b5a03416278595588931889ab7c5.tar.gz
otp-771abbd23709b5a03416278595588931889ab7c5.tar.bz2
otp-771abbd23709b5a03416278595588931889ab7c5.zip
erts: Keep magic ref to DistEntry in net_kernel
to make sure it's kept alive.
-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
-rw-r--r--lib/kernel/src/net_kernel.erl17
5 files changed, 57 insertions, 37 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);
diff --git a/lib/kernel/src/net_kernel.erl b/lib/kernel/src/net_kernel.erl
index f929e4bf11..eee915b15b 100644
--- a/lib/kernel/src/net_kernel.erl
+++ b/lib/kernel/src/net_kernel.erl
@@ -435,10 +435,10 @@ handle_connect(ConnLookup, Type, Node, ConnId, From , State) ->
-define(ERTS_DIST_CON_ID_MASK, 16#ffffff). % also in external.h
-verify_new_conn_id([], ConnId)
- when (ConnId band (bnot ?ERTS_DIST_CON_ID_MASK)) =:= 0 ->
+verify_new_conn_id([], {Nr,_DHandle})
+ when (Nr band (bnot ?ERTS_DIST_CON_ID_MASK)) =:= 0 ->
true;
-verify_new_conn_id([#connection{conn_id = Old}], New)
+verify_new_conn_id([#connection{conn_id = {Old,_}}], {New,_})
when New =:= ((Old+1) band ?ERTS_DIST_CON_ID_MASK) ->
true;
verify_new_conn_id(_, _) ->
@@ -460,7 +460,7 @@ handle_call({auto_connect, Type, Node, WaitForBarred}, From, State) ->
verbose({auto_connect, Type, Node, WaitForBarred}, 1, State),
R = case (catch erlang:new_connection_id(Node)) of
- ConnId when is_integer(ConnId) ->
+ {Nr,_DHandle}=ConnId when is_integer(Nr) ->
handle_auto_connect(Type, Node, ConnId, WaitForBarred, From, State);
_Error ->
@@ -481,7 +481,7 @@ handle_call({connect, Type, Node}, From, State) ->
verbose({connect, Type, Node}, 1, State),
ConnLookup = ets:lookup(sys_dist, Node),
R = case (catch erlang:new_connection_id(Node)) of
- ConnId when is_integer(ConnId) ->
+ {Nr,_DHandle}=ConnId when is_integer(Nr) ->
handle_connect(ConnLookup, Type, Node, ConnId, From, State);
_Error ->
@@ -699,8 +699,9 @@ terminate(_Reason, State) ->
%%
%% Asynchronous auto connect request
%%
-handle_info({auto_connect,Node,ConnId}, State) ->
- verbose({auto_connect, Node, ConnId}, 1, State),
+handle_info({auto_connect,Node, Nr, DHandle}, State) ->
+ verbose({auto_connect, Node, Nr, DHandle}, 1, State),
+ ConnId = {Nr, DHandle},
NewState =
case handle_auto_connect(normal, Node, ConnId, false, noreply, State) of
{noreply, S} -> %% Pending connection
@@ -796,7 +797,7 @@ handle_info({AcceptPid, {accept_pending,MyNode,Node,Address,Type}}, State) ->
{noreply, State};
_ ->
ConnId = case (catch erlang:new_connection_id(Node)) of
- CI when is_integer(CI) -> CI
+ {Nr,_DHandle}=CI when is_integer(Nr) -> CI
%% SVERK What to do?
end,
ets:insert(sys_dist, #connection{node = Node,