summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRickard Green <rickard@erlang.org>2022-08-10 13:29:59 +0200
committerRickard Green <rickard@erlang.org>2022-08-12 18:55:48 +0200
commitad8742311cab2f56f8702fc2206d29d0ceca922e (patch)
treef3c92feb24cd8ded23cdd2f9b097b02f282241e4
parent0863bd30aabd035c83158c78046c5ffda16127e1 (diff)
downloaderlang-ad8742311cab2f56f8702fc2206d29d0ceca922e.tar.gz
[erts] Fix immediate noproc scenarios of erlang:monitor/3 BIF
Since the BIF constructed and sent an ordinary 'DOWN' message when detecting that the target could not be looked up, configured tag and/or alias options were lost.
-rw-r--r--erts/emulator/beam/bif.c113
-rw-r--r--erts/emulator/beam/break.c1
-rw-r--r--erts/emulator/beam/erl_bif_info.c7
-rw-r--r--erts/emulator/beam/erl_monitor_link.c5
-rw-r--r--erts/emulator/beam/erl_monitor_link.h61
-rw-r--r--erts/emulator/beam/erl_proc_sig_queue.c40
-rw-r--r--erts/emulator/beam/erl_process.c19
-rw-r--r--erts/emulator/beam/global.h7
-rw-r--r--erts/emulator/test/monitor_SUITE.erl226
9 files changed, 370 insertions, 109 deletions
diff --git a/erts/emulator/beam/bif.c b/erts/emulator/beam/bif.c
index 34ace8c61b..3fc0267f99 100644
--- a/erts/emulator/beam/bif.c
+++ b/erts/emulator/beam/bif.c
@@ -394,6 +394,14 @@ demonitor(Process *c_p, Eterm ref, Eterm *multip)
return am_true;
}
+ case ERTS_MON_TYPE_DIST_PORT: {
+ ASSERT(is_external_port(mon->other.item));
+ ASSERT(external_pid_dist_entry(mon->other.item)
+ == erts_this_dist_entry);
+ erts_monitor_release(mon);
+ return am_true;
+ }
+
case ERTS_MON_TYPE_PROC:
erts_proc_sig_send_demonitor(mon);
return am_true;
@@ -419,14 +427,12 @@ demonitor(Process *c_p, Eterm ref, Eterm *multip)
if (is_external_pid(to))
dep = external_pid_dist_entry(to);
- else {
- /* Monitoring a name at node to */
+ else /* Monitoring a name at node to */
dep = erts_sysname_to_connected_dist_entry(to);
- ASSERT(dep != erts_this_dist_entry);
- if (!dep) {
- erts_monitor_release(mon);
- return am_false;
- }
+
+ if (!dep || dep == erts_this_dist_entry) {
+ erts_monitor_release(mon);
+ return am_false;
}
code = erts_dsig_prepare(&ctx, dep, c_p, ERTS_PROC_LOCK_MAIN,
@@ -559,43 +565,6 @@ badarg:
BIF_ERROR(BIF_P, BADARG);
}
-/* Type must be atomic object! */
-void
-erts_queue_monitor_message(Process *p,
- ErtsProcLocks *p_locksp,
- Eterm ref,
- Eterm type,
- Eterm item,
- Eterm reason)
-{
- Eterm tup;
- Eterm* hp;
- Eterm reason_copy, ref_copy, item_copy;
- Uint reason_size, ref_size, item_size, heap_size;
- ErlOffHeap *ohp;
- ErtsMessage *msgp;
-
- reason_size = IS_CONST(reason) ? 0 : size_object(reason);
- item_size = IS_CONST(item) ? 0 : size_object(item);
- ref_size = size_object(ref);
-
- heap_size = 6+reason_size+ref_size+item_size;
-
- msgp = erts_alloc_message_heap(p, p_locksp, heap_size,
- &hp, &ohp);
-
- reason_copy = (IS_CONST(reason)
- ? reason
- : copy_struct(reason, reason_size, &hp, ohp));
- item_copy = (IS_CONST(item)
- ? item
- : copy_struct(item, item_size, &hp, ohp));
- ref_copy = copy_struct(ref, ref_size, &hp, ohp);
-
- tup = TUPLE5(hp, am_DOWN, ref_copy, type, item_copy, reason_copy);
- erts_queue_message(p, *p_locksp, msgp, tup, am_system);
-}
-
Uint16
erts_monitor_opts(Eterm opts, Eterm *tag)
{
@@ -649,7 +618,6 @@ erts_monitor_opts(Eterm opts, Eterm *tag)
static BIF_RETTYPE monitor(Process *c_p, Eterm type, Eterm target,
Uint16 add_oflags, Eterm tag)
{
- Eterm tmp_heap[3];
Eterm ref, id, name;
ErtsMonitorData *mdp;
BIF_RETTYPE ret_val;
@@ -677,9 +645,11 @@ static BIF_RETTYPE monitor(Process *c_p, Eterm type, Eterm target,
mdp->origin.flags |= add_oflags;
erts_monitor_tree_insert(&ERTS_P_MONITORS(c_p),
&mdp->origin);
- if (!erts_proc_sig_send_monitor(&mdp->u.target, id))
+ if (is_not_internal_pid(id)
+ || !erts_proc_sig_send_monitor(&mdp->u.target, id)) {
erts_proc_sig_send_monitor_down(&mdp->u.target,
am_noproc);
+ }
}
goto done;
@@ -689,11 +659,7 @@ static BIF_RETTYPE monitor(Process *c_p, Eterm type, Eterm target,
local_named_process:
name = target;
id = erts_whereis_name_to_id(c_p, target);
- if (is_internal_pid(id))
- goto local_process;
- target = TUPLE2(&tmp_heap[0], name,
- erts_this_dist_entry->sysname);
- goto noproc;
+ goto local_process;
}
if (is_external_pid(target)) {
@@ -701,8 +667,15 @@ static BIF_RETTYPE monitor(Process *c_p, Eterm type, Eterm target,
int code;
dep = external_pid_dist_entry(target);
- if (dep == erts_this_dist_entry)
- goto noproc;
+ if (dep == erts_this_dist_entry) {
+ mdp = erts_monitor_create(ERTS_MON_TYPE_DIST_PROC, ref,
+ c_p->common.id, target,
+ NIL, tag);
+ mdp->origin.flags |= add_oflags;
+ erts_monitor_tree_insert(&ERTS_P_MONITORS(c_p), &mdp->origin);
+ erts_proc_sig_send_monitor_down(&mdp->u.target, am_noproc);
+ goto done;
+ }
id = target;
name = NIL;
@@ -795,16 +768,19 @@ static BIF_RETTYPE monitor(Process *c_p, Eterm type, Eterm target,
local_named_port:
name = target;
id = erts_whereis_name_to_id(c_p, target);
- if (is_internal_port(id))
- goto local_port;
- target = TUPLE2(&tmp_heap[0], name,
- erts_this_dist_entry->sysname);
- goto noproc;
+ goto local_port;
}
if (is_external_port(target)) {
- if (erts_this_dist_entry == external_port_dist_entry(target))
- goto noproc;
+ if (erts_this_dist_entry == external_port_dist_entry(target)) {
+ mdp = erts_monitor_create(ERTS_MON_TYPE_DIST_PORT, ref,
+ c_p->common.id, target,
+ NIL, tag);
+ mdp->origin.flags |= add_oflags;
+ erts_monitor_tree_insert(&ERTS_P_MONITORS(c_p), &mdp->origin);
+ erts_proc_sig_send_monitor_down(&mdp->u.target, am_noproc);
+ goto done;
+ }
goto badarg;
}
@@ -843,23 +819,6 @@ static BIF_RETTYPE monitor(Process *c_p, Eterm type, Eterm target,
badarg:
ERTS_BIF_PREP_ERROR(ret_val, c_p, BADARG);
-
- if (0) {
- ErtsProcLocks locks;
-noproc:
- locks = ERTS_PROC_LOCK_MAIN;
-
- erts_queue_monitor_message(c_p,
- &locks,
- ref,
- type,
- target,
- am_noproc);
- if (locks != ERTS_PROC_LOCK_MAIN)
- erts_proc_unlock(c_p, locks & ~ERTS_PROC_LOCK_MAIN);
-
- ERTS_BIF_PREP_RET(ret_val, ref);
- }
done:
diff --git a/erts/emulator/beam/break.c b/erts/emulator/beam/break.c
index fa2f77dc7c..b1b0ed6971 100644
--- a/erts/emulator/beam/break.c
+++ b/erts/emulator/beam/break.c
@@ -186,6 +186,7 @@ static int doit_print_monitor(ErtsMonitor *mon, void *vpcontext, Sint reds)
case ERTS_MON_TYPE_PORT:
case ERTS_MON_TYPE_TIME_OFFSET:
case ERTS_MON_TYPE_DIST_PROC:
+ case ERTS_MON_TYPE_DIST_PORT:
case ERTS_MON_TYPE_RESOURCE:
case ERTS_MON_TYPE_NODE:
diff --git a/erts/emulator/beam/erl_bif_info.c b/erts/emulator/beam/erl_bif_info.c
index d5e598515c..17f55aaa81 100644
--- a/erts/emulator/beam/erl_bif_info.c
+++ b/erts/emulator/beam/erl_bif_info.c
@@ -291,6 +291,11 @@ static int do_make_one_mon_element(ErtsMonitor *mon, void * vpmlc, Sint reds)
t = AM_dist_process;
break;
}
+ case ERTS_MON_TYPE_DIST_PORT: {
+ ERTS_DECL_AM(dist_port);
+ t = AM_dist_port;
+ break;
+ }
case ERTS_MON_TYPE_RESOURCE: {
ERTS_DECL_AM(resource);
t = AM_resource;
@@ -578,6 +583,7 @@ static int collect_one_origin_monitor(ErtsMonitor *mon, void *vmicp, Sint reds)
case ERTS_MON_TYPE_PROC:
case ERTS_MON_TYPE_PORT:
case ERTS_MON_TYPE_DIST_PROC:
+ case ERTS_MON_TYPE_DIST_PORT:
case ERTS_MON_TYPE_TIME_OFFSET:
if (mon->flags & ERTS_ML_FLG_SPAWN_PENDING)
break; /* Not an active monitor... */
@@ -630,6 +636,7 @@ static int collect_one_target_monitor(ErtsMonitor *mon, void *vmicp, Sint reds)
case ERTS_MON_TYPE_PROC:
case ERTS_MON_TYPE_PORT:
case ERTS_MON_TYPE_DIST_PROC:
+ case ERTS_MON_TYPE_DIST_PORT:
micp->mi[micp->mi_i].entity.term = mon->other.item;
micp->mi[micp->mi_i].node = NIL;
diff --git a/erts/emulator/beam/erl_monitor_link.c b/erts/emulator/beam/erl_monitor_link.c
index 23fd3dd566..5746cd3e96 100644
--- a/erts/emulator/beam/erl_monitor_link.c
+++ b/erts/emulator/beam/erl_monitor_link.c
@@ -51,6 +51,7 @@ ml_get_key(ErtsMonLnkNode *mln)
case ERTS_MON_TYPE_PROC:
case ERTS_MON_TYPE_PORT:
case ERTS_MON_TYPE_DIST_PROC:
+ case ERTS_MON_TYPE_DIST_PORT:
case ERTS_MON_TYPE_TIME_OFFSET:
case ERTS_MON_TYPE_RESOURCE: {
ErtsMonitorData *mdp = erts_monitor_to_data(mln);
@@ -891,6 +892,7 @@ erts_monitor_create(Uint16 type, Eterm ref, Eterm orgn, Eterm trgt, Eterm name,
break;
}
case ERTS_MON_TYPE_DIST_PROC:
+ case ERTS_MON_TYPE_DIST_PORT:
case ERTS_MON_TYPE_RESOURCE:
case ERTS_MON_TYPE_NODE:
case ERTS_MON_TYPE_NODES: {
@@ -1203,7 +1205,8 @@ erts_monitor_size(ErtsMonitor *mon)
&& mon->type != ERTS_MON_TYPE_NODES) {
if (!is_immed(mdep->md.ref))
hsz += NC_HEAP_SIZE(mdep->md.ref);
- if (mon->type == ERTS_MON_TYPE_DIST_PROC) {
+ if (mon->type == ERTS_MON_TYPE_DIST_PROC
+ || mon->type == ERTS_MON_TYPE_DIST_PORT) {
if (!is_immed(mdep->md.origin.other.item))
hsz += NC_HEAP_SIZE(mdep->md.origin.other.item);
if (!is_immed(mdep->md.u.target.other.item))
diff --git a/erts/emulator/beam/erl_monitor_link.h b/erts/emulator/beam/erl_monitor_link.h
index 4c0a47963c..d2cd7ead4d 100644
--- a/erts/emulator/beam/erl_monitor_link.h
+++ b/erts/emulator/beam/erl_monitor_link.h
@@ -93,7 +93,8 @@
* Key: Reference
* Name: Name (atom) if by name
*
- * Valid keys are only ordinary internal references.
+ * Valid keys are only ordinary internal references or internal
+ * pid-reference.
*
* Origin part of the monitor is stored in the monitor tree of
* origin process and target part of the monitor is stored in
@@ -112,7 +113,8 @@
* Key: Reference
* Name: Name (atom) if by name
*
- * Valid keys are only ordinary internal references.
+ * Valid keys are only ordinary internal references or internal
+ * pid-reference.
*
* Origin part of the monitor is stored in the monitor tree of
* origin process/port and target part of the monitor is stored
@@ -130,7 +132,8 @@
* Shared:
* Key: Reference
*
- * Valid keys are only ordinary internal references.
+ * Valid keys are only ordinary internal references or internal
+ * pid-reference.
*
* Origin part of the monitor is stored in the monitor tree of
* origin process and target part of the monitor is stored in
@@ -153,7 +156,8 @@
* Name: Name (atom) if by name
* Dist: Pointer to dist structure
*
- * Valid keys are only ordinary internal references.
+ * Valid keys are only ordinary internal references or internal
+ * pid-reference.
*
* Origin part of the monitor is stored in the monitor tree of
* origin process and target part of the monitor is stored in
@@ -182,6 +186,30 @@
* process.
*
*
+ * --- ERTS_MON_TYPE_DIST_PORT -----------------------------------
+ *
+ * A local process (origin) monitors a port (target) on an old
+ * incarnation of the local node. Note that it is currently only
+ * for this since operations against remote ports is not
+ * supported.
+ *
+ * Origin:
+ * Other Item: Monitored port identifier
+ * Target:
+ * Other Item: Local process identifier
+ * Shared:
+ * Key: Reference
+ * Dist: NULL
+ *
+ * Valid keys are only ordinary internal references or internal
+ * pid-reference.
+ *
+ * Origin part of the monitor is stored in the monitor tree of
+ * origin process and target part is currently only used when
+ * passing monitor down signal (monitors against old incarnations
+ * will always immediately trigger monitor down noproc since the
+ * process wont be alive).
+ *
* --- ERTS_MON_TYPE_RESOURCE ------------------------------------
*
* A NIF resource (origin) monitors a process (target).
@@ -425,16 +453,17 @@
#define ERTS_ML_STATE_ALIAS_DEMONITOR (((Uint16) 2) << ERTS_ML_STATE_ALIAS_SHIFT)
#define ERTS_ML_STATE_ALIAS_ONCE (((Uint16) 3) << ERTS_ML_STATE_ALIAS_SHIFT)
-#define ERTS_MON_TYPE_MAX ((Uint16) 8)
+#define ERTS_MON_TYPE_MAX ((Uint16) 9)
#define ERTS_MON_TYPE_PROC ((Uint16) 0)
#define ERTS_MON_TYPE_PORT ((Uint16) 1)
#define ERTS_MON_TYPE_TIME_OFFSET ((Uint16) 2)
#define ERTS_MON_TYPE_DIST_PROC ((Uint16) 3)
-#define ERTS_MON_TYPE_RESOURCE ((Uint16) 4)
-#define ERTS_MON_TYPE_NODE ((Uint16) 5)
-#define ERTS_MON_TYPE_NODES ((Uint16) 6)
-#define ERTS_MON_TYPE_SUSPEND ((Uint16) 7)
+#define ERTS_MON_TYPE_DIST_PORT ((Uint16) 4)
+#define ERTS_MON_TYPE_RESOURCE ((Uint16) 5)
+#define ERTS_MON_TYPE_NODE ((Uint16) 6)
+#define ERTS_MON_TYPE_NODES ((Uint16) 7)
+#define ERTS_MON_TYPE_SUSPEND ((Uint16) 8)
#define ERTS_MON_TYPE_ALIAS ERTS_MON_TYPE_MAX
#define ERTS_MON_LNK_TYPE_MAX (ERTS_MON_TYPE_MAX + ((Uint16) 3))
@@ -1166,12 +1195,13 @@ int erts_monitor_list_foreach_delete_yielding(ErtsMonitor **list,
* Can create all types of monitors
*
* When the function is called it is assumed that:
- * - 'ref' is an internal ordinary reference if type is ERTS_MON_TYPE_PROC,
- * ERTS_MON_TYPE_PORT, ERTS_MON_TYPE_TIME_OFFSET, or ERTS_MON_TYPE_RESOURCE
+ * - 'ref' is an ordinary internal reference or internal pid-reference if type
+ * is ERTS_MON_TYPE_PROC, ERTS_MON_TYPE_PORT, ERTS_MON_TYPE_DIST_PORT,
+ * ERTS_MON_TYPE_TIME_OFFSET, or ERTS_MON_TYPE_RESOURCE
* - 'ref' is NIL if type is ERTS_MON_TYPE_NODE, ERTS_MON_TYPE_NODES, or
* ERTS_MON_TYPE_SUSPEND
- * - 'ref' is and ordinary internal reference or an external reference if
- * type is ERTS_MON_TYPE_DIST_PROC
+ * - 'ref' is and ordinary internal reference, internal pid-reference or an
+ * external reference if type is ERTS_MON_TYPE_DIST_PROC
* - 'name' is an atom or NIL if type is ERTS_MON_TYPE_PROC,
* ERTS_MON_TYPE_PORT, or ERTS_MON_TYPE_DIST_PROC
* - 'name is NIL if type is ERTS_MON_TYPE_TIME_OFFSET, ERTS_MON_TYPE_RESOURCE,
@@ -1180,8 +1210,9 @@ int erts_monitor_list_foreach_delete_yielding(ErtsMonitor **list,
*
* @param[in] type ERTS_MON_TYPE_PROC, ERTS_MON_TYPE_PORT,
* ERTS_MON_TYPE_TIME_OFFSET, ERTS_MON_TYPE_DIST_PROC,
- * ERTS_MON_TYPE_RESOURCE, ERTS_MON_TYPE_NODE,
- * ERTS_MON_TYPE_NODES, or ERTS_MON_TYPE_SUSPEND
+ * ERTS_MON_TYPE_DIST_PORT, ERTS_MON_TYPE_RESOURCE,
+ * ERTS_MON_TYPE_NODE, ERTS_MON_TYPE_NODES, or
+ * ERTS_MON_TYPE_SUSPEND
*
* @param[in] ref A reference or NIL depending on type
*
diff --git a/erts/emulator/beam/erl_proc_sig_queue.c b/erts/emulator/beam/erl_proc_sig_queue.c
index 83b6991809..bfd6d08e14 100644
--- a/erts/emulator/beam/erl_proc_sig_queue.c
+++ b/erts/emulator/beam/erl_proc_sig_queue.c
@@ -2086,15 +2086,17 @@ erts_proc_sig_send_demonitor(ErtsMonitor *mon)
Uint16 type = mon->type;
Eterm to = mon->other.item;
- ASSERT(is_internal_pid(to));
+ ASSERT(is_internal_pid(to) || to == am_undefined);
ASSERT(erts_monitor_is_origin(mon));
ASSERT(!erts_monitor_is_in_table(mon));
sig->common.tag = ERTS_PROC_SIG_MAKE_TAG(ERTS_SIG_Q_OP_DEMONITOR,
type, 0);
- if (!proc_queue_signal(NULL, to, sig, ERTS_SIG_Q_OP_DEMONITOR))
+ if (is_not_internal_pid(to)
+ || !proc_queue_signal(NULL, to, sig, ERTS_SIG_Q_OP_DEMONITOR)) {
erts_monitor_release(mon);
+ }
}
int
@@ -3660,7 +3662,7 @@ convert_to_down_message(Process *c_p,
hsz += 3; /* reg name 2-tuple */
else {
ASSERT(is_pid(mdp->origin.other.item)
- || is_internal_port(mdp->origin.other.item));
+ || is_port(mdp->origin.other.item));
hsz += NC_HEAP_SIZE(mdp->origin.other.item);
}
@@ -3705,6 +3707,22 @@ convert_to_down_message(Process *c_p,
ERL_MESSAGE_FROM(mp) = mdp->origin.other.item;
}
break;
+ case ERTS_MON_TYPE_DIST_PORT: {
+#ifdef DEBUG
+ ErtsMonitorDataExtended *mdep = (ErtsMonitorDataExtended *) mdp;
+#endif
+ ASSERT(mdp->origin.flags & ERTS_ML_FLG_EXTENDED);
+ type = am_port;
+ ASSERT(node == am_undefined);
+ ASSERT(!mdep->dist);
+ ASSERT(is_external_port(from)
+ && (external_port_dist_entry(from)
+ == erts_this_dist_entry));
+ node = erts_this_dist_entry->sysname;
+ ASSERT(is_atom(node) && node != am_undefined);
+ ERL_MESSAGE_FROM(mp) = node;
+ break;
+ }
case ERTS_MON_TYPE_PROC:
type = am_process;
if (mdp->origin.other.item == am_undefined) {
@@ -3722,8 +3740,14 @@ convert_to_down_message(Process *c_p,
ErtsMonitorDataExtended *mdep;
ASSERT(mdp->origin.flags & ERTS_ML_FLG_EXTENDED);
mdep = (ErtsMonitorDataExtended *) mdp;
- ASSERT(mdep->dist);
- node = mdep->dist->nodename;
+ if (mdep->dist)
+ node = mdep->dist->nodename;
+ else {
+ ASSERT(is_external_pid(from));
+ ASSERT(external_pid_dist_entry(from)
+ == erts_this_dist_entry);
+ node = erts_this_dist_entry->sysname;
+ }
}
ASSERT(is_atom(node) && node != am_undefined);
ERL_MESSAGE_FROM(mp) = node;
@@ -4861,6 +4885,7 @@ handle_alias_message(Process *c_p, ErtsMessage *sig, ErtsMessage ***next_nm_sig)
erts_pid_ref_delete(alias);
switch (mon->type) {
+ case ERTS_MON_TYPE_DIST_PORT:
case ERTS_MON_TYPE_ALIAS:
erts_monitor_release(mon);
break;
@@ -5071,6 +5096,7 @@ erts_proc_sig_handle_incoming(Process *c_p, erts_aint32_t *statep,
switch (type) {
case ERTS_MON_TYPE_DIST_PROC:
+ case ERTS_MON_TYPE_DIST_PORT:
case ERTS_MON_TYPE_PROC:
case ERTS_MON_TYPE_PORT:
tmon = (ErtsMonitor *) sig;
@@ -5890,6 +5916,7 @@ erts_proc_sig_handle_exit(Process *c_p, Sint *redsp,
case ERTS_MON_TYPE_PORT:
case ERTS_MON_TYPE_PROC:
case ERTS_MON_TYPE_DIST_PROC:
+ case ERTS_MON_TYPE_DIST_PORT:
case ERTS_MON_TYPE_NODE:
case ERTS_MON_TYPE_NODES:
case ERTS_MON_TYPE_SUSPEND:
@@ -6064,6 +6091,7 @@ clear_seq_trace_token(ErtsMessage *sig)
case ERTS_MON_TYPE_PORT:
case ERTS_MON_TYPE_PROC:
case ERTS_MON_TYPE_DIST_PROC:
+ case ERTS_MON_TYPE_DIST_PORT:
case ERTS_MON_TYPE_NODE:
case ERTS_MON_TYPE_NODES:
case ERTS_MON_TYPE_SUSPEND:
@@ -6143,6 +6171,7 @@ erts_proc_sig_signal_size(ErtsSignal *sig)
case ERTS_MON_TYPE_PORT:
case ERTS_MON_TYPE_PROC:
case ERTS_MON_TYPE_DIST_PROC:
+ case ERTS_MON_TYPE_DIST_PORT:
case ERTS_MON_TYPE_NODE:
case ERTS_MON_TYPE_SUSPEND:
size = erts_monitor_size((ErtsMonitor *) sig);
@@ -7457,6 +7486,7 @@ erts_proc_sig_debug_foreach_sig(Process *c_p,
case ERTS_MON_TYPE_PORT:
case ERTS_MON_TYPE_PROC:
case ERTS_MON_TYPE_DIST_PROC:
+ case ERTS_MON_TYPE_DIST_PORT:
case ERTS_MON_TYPE_NODE:
mon_func((ErtsMonitor *) sig, arg, -1);
break;
diff --git a/erts/emulator/beam/erl_process.c b/erts/emulator/beam/erl_process.c
index 776094dfbf..e2eb445184 100644
--- a/erts/emulator/beam/erl_process.c
+++ b/erts/emulator/beam/erl_process.c
@@ -13315,6 +13315,10 @@ erts_proc_exit_handle_monitor(ErtsMonitor *mon, void *vctxt, Sint reds)
erts_fire_nif_monitor(mon);
mon = NULL;
break;
+ case ERTS_MON_TYPE_DIST_PORT:
+ /* Target of a dist port monitor is never inserted... */
+ ERTS_INTERNAL_ERROR("Unexpected dist port monitor");
+ break;
case ERTS_MON_TYPE_DIST_PROC: {
ErtsMonLnkDist *dist;
DistEntry *dep;
@@ -13390,7 +13394,8 @@ erts_proc_exit_handle_monitor(ErtsMonitor *mon, void *vctxt, Sint reds)
break;
case ERTS_MON_TYPE_PORT: {
Port *prt;
- ASSERT(is_internal_port(mon->other.item));
+ ASSERT(is_internal_port(mon->other.item)
+ || mon->other.item == am_undefined);
prt = erts_port_lookup_raw(mon->other.item);
if (prt) {
if (erts_port_demonitor(c_p, prt, mon) != ERTS_PORT_OP_DROPPED)
@@ -13398,6 +13403,9 @@ erts_proc_exit_handle_monitor(ErtsMonitor *mon, void *vctxt, Sint reds)
}
break;
}
+ case ERTS_MON_TYPE_DIST_PORT:
+ /* just release it... */
+ break;
case ERTS_MON_TYPE_DIST_PROC: {
ErtsMonLnkDist *dist;
DistEntry *dep;
@@ -13412,7 +13420,14 @@ erts_proc_exit_handle_monitor(ErtsMonitor *mon, void *vctxt, Sint reds)
mdp = erts_monitor_to_data(mon);
dist = ((ErtsMonitorDataExtended *) mdp)->dist;
- ASSERT(dist);
+ if (!dist) {
+ ASSERT(is_external_pid(mon->other.item));
+ ASSERT(external_pid_dist_entry(mon->other.item)
+ == erts_this_dist_entry);
+ /* Target part is in our signal queue... */
+ mdp = NULL;
+ break;
+ }
if (mon->flags & ERTS_ML_FLG_NAME) {
watched = ((ErtsMonitorDataExtended *) mdp)->u.name;
ASSERT(is_atom(watched));
diff --git a/erts/emulator/beam/global.h b/erts/emulator/beam/global.h
index feab1ba53e..232d3df452 100644
--- a/erts/emulator/beam/global.h
+++ b/erts/emulator/beam/global.h
@@ -931,13 +931,6 @@ Eterm erts_bld_bin_list(Uint **hpp, Uint *szp, ErlOffHeap* oh, Eterm tail);
void erts_bif_info_init(void);
/* bif.c */
-
-void erts_queue_monitor_message(Process *,
- ErtsProcLocks*,
- Eterm,
- Eterm,
- Eterm,
- Eterm);
void erts_init_trap_export(Export* ep, Eterm m, Eterm f, Uint a,
Eterm (*bif)(Process*, Eterm*, ErtsCodePtr));
void erts_init_bif(void);
diff --git a/erts/emulator/test/monitor_SUITE.erl b/erts/emulator/test/monitor_SUITE.erl
index 2b3c3b9477..e99b413c2a 100644
--- a/erts/emulator/test/monitor_SUITE.erl
+++ b/erts/emulator/test/monitor_SUITE.erl
@@ -30,7 +30,7 @@
large_exit/1, list_cleanup/1, mixer/1, named_down/1, otp_5827/1,
monitor_time_offset/1, monitor_tag_storage/1,
unexpected_alias_at_demonitor_gh5310/1,
- down_on_alias_gh5310/1]).
+ down_on_alias_gh5310/1, monitor_3_noproc_gh6185/1]).
-export([y2/1, g/1, g0/0, g1/0, large_exit_sub/1]).
@@ -45,7 +45,7 @@ all() ->
list_cleanup, mixer, named_down, otp_5827,
monitor_time_offset, monitor_tag_storage,
unexpected_alias_at_demonitor_gh5310,
- down_on_alias_gh5310].
+ down_on_alias_gh5310, monitor_3_noproc_gh6185].
groups() ->
[{remove_monitor, [],
@@ -1038,6 +1038,228 @@ down_on_alias_gh5310_test(ImmedExitReason, DeMonSched, TermSched) ->
DeMonPid ! Go,
receive Done -> ok end.
+
+monitor_3_noproc_gh6185(Config) when is_list(Config) ->
+ monitor_3_noproc_gh6185_test(false, false),
+ monitor_3_noproc_gh6185_test(true, false),
+ monitor_3_noproc_gh6185_test(false, true),
+ monitor_3_noproc_gh6185_test(true, true),
+ monitor_3_noproc_gh6185_exit_test(false, false),
+ monitor_3_noproc_gh6185_exit_test(true, false),
+ monitor_3_noproc_gh6185_exit_test(false, true),
+ monitor_3_noproc_gh6185_exit_test(true, true).
+
+monitor_3_noproc_gh6185_test(AliasTest, TagTest) ->
+ NodeName = node(),
+ UN = undefined_name_gh6185,
+ UNN = {UN, NodeName},
+ undefined = whereis(UN),
+
+ {AliasOpt, CheckAlias}
+ = case AliasTest of
+ false ->
+ {[], fun (_NotAnAlias) -> ok end};
+ true ->
+ {[{alias, explicit_unalias}],
+ fun (Alias) ->
+ AMsg1 = make_ref(),
+ OMsg1 = make_ref(),
+ Alias ! AMsg1,
+ self() ! OMsg1,
+ receive OMsg1 -> ok end,
+ receive AMsg1 -> ok
+ after 0 -> ct:fail(missing_alias_message)
+ end,
+ unalias(Alias),
+ AMsg2 = make_ref(),
+ OMsg2 = make_ref(),
+ Alias ! AMsg2,
+ self() ! OMsg2,
+ receive OMsg2 -> ok end,
+ receive AMsg2 -> ct:fail(unexpected_alias_message)
+ after 0 -> ok
+ end
+ end}
+ end,
+
+ TagFun = case TagTest of
+ false ->
+ fun () ->
+ {'DOWN', []}
+ end;
+ true ->
+ fun () ->
+ Tag = make_ref(),
+ {Tag, [{tag, Tag}]}
+ end
+ end,
+
+ %% not registerd process...
+ {Tag1, TagOpt1} = TagFun(),
+ M1 = erlang:monitor(process, UN, AliasOpt ++ TagOpt1),
+ receive
+ {Tag1, M1, process, UNN, noproc} ->
+ ok;
+ ID1 when element(2, ID1) == M1 ->
+ ct:fail({invalid_down, ID1})
+ after 100 ->
+ ct:fail(missing_down)
+ end,
+ CheckAlias(M1),
+
+ {Tag2, TagOpt2} = TagFun(),
+ M2 = erlang:monitor(process, UNN, AliasOpt ++ TagOpt2),
+ receive
+ {Tag2, M2, process, UNN, noproc} ->
+ ok;
+ ID2 when element(2, ID2) == M2 ->
+ ct:fail({invalid_down, ID2})
+ after 100 ->
+ ct:fail(missing_down)
+ end,
+ CheckAlias(M2),
+
+ %% Not registered port...
+ {Tag3, TagOpt3} = TagFun(),
+ M3 = erlang:monitor(port, UN, AliasOpt ++ TagOpt3),
+ receive
+ {Tag3, M3, port, UNN, noproc} ->
+ ok;
+ ID3 when element(2, ID3) == M3 ->
+ ct:fail({invalid_down, ID3})
+ after 100 ->
+ ct:fail(missing_down)
+ end,
+ CheckAlias(M3),
+
+ {Tag4, TagOpt4} = TagFun(),
+ M4 = erlang:monitor(port, UNN, AliasOpt ++ TagOpt4),
+ receive
+ {Tag4, M4, port, UNN, noproc} ->
+ ok;
+ ID4 when element(2, ID4) == M4 ->
+ ct:fail({invalid_down, ID4})
+ after 100 ->
+ ct:fail(missing_down)
+ end,
+ CheckAlias(M4),
+
+
+ OldCreation = case erlang:system_info(creation) of
+ Creation when Creation =< 4 -> 16#ffffffff;
+ Creation -> Creation - 1
+ end,
+
+ %% Process of old incarnation...
+ Pid = erts_test_utils:mk_ext_pid({NodeName, OldCreation}, 4711, 17),
+ {Tag5, TagOpt5} = TagFun(),
+ M5 = erlang:monitor(process, Pid, AliasOpt ++ TagOpt5),
+ receive
+ {Tag5, M5, process, Pid, noproc} ->
+ ok;
+ ID5 when element(2, ID5) == M5 ->
+ ct:fail({invalid_down, ID5})
+ after 100 ->
+ ct:fail(missing_down)
+ end,
+ CheckAlias(M5),
+
+ %% Port of old incarnation...
+ Prt = erts_test_utils:mk_ext_port({NodeName, OldCreation}, 4711),
+ {Tag6, TagOpt6} = TagFun(),
+ M6 = erlang:monitor(port, Prt, AliasOpt ++ TagOpt6),
+ receive
+ {Tag6, M6, port, Prt, noproc} ->
+ ok;
+ ID6 when element(2, ID6) == M6 ->
+ ct:fail({invalid_down, ID6})
+ after 100 ->
+ ct:fail(missing_down)
+ end,
+ CheckAlias(M6),
+
+ ok.
+
+monitor_3_noproc_gh6185_exit_test(AliasTest, TagTest) ->
+ %%
+ %% Testing that we handle these quite unusual monitors correct
+ %% in case the monotoring process dies right after setting up
+ %% the monitor. We cannot check any results, but we might hit
+ %% asserts, crashes, or memory leaks if any bugs exist...
+ %%
+
+ NodeName = node(),
+ UN = undefined_name_gh6185,
+ UNN = {UN, NodeName},
+ undefined = whereis(UN),
+
+ AliasOpt = case AliasTest of
+ false -> [];
+ true -> [{alias, explicit_unalias}]
+ end,
+
+ TagOpt = case TagTest of
+ false -> [];
+ true -> [{tag, make_ref()}]
+ end,
+
+ %% not registerd process...
+ {P1, M1} = spawn_monitor(fun () ->
+ erlang:yield(),
+ _ = erlang:monitor(process, UN, AliasOpt ++ TagOpt),
+ exit(bang)
+ end),
+ receive {'DOWN', M1, process, P1, bang} -> ok end,
+ {P2, M2} = spawn_monitor(fun () ->
+ erlang:yield(),
+ _ = erlang:monitor(process, UNN, AliasOpt ++ TagOpt),
+ exit(bang)
+ end),
+ receive {'DOWN', M2, process, P2, bang} -> ok end,
+
+ %% Not registered port...
+ {P3, M3} = spawn_monitor(fun () ->
+ erlang:yield(),
+ _ = erlang:monitor(port, UN, AliasOpt ++ TagOpt),
+ exit(bang)
+ end),
+ receive {'DOWN', M3, process, P3, bang} -> ok end,
+ {P4, M4} = spawn_monitor(fun () ->
+ erlang:yield(),
+ _ = erlang:monitor(port, UNN, AliasOpt ++ TagOpt),
+ exit(bang)
+ end),
+ receive {'DOWN', M4, process, P4, bang} -> ok end,
+
+
+ OldCreation = case erlang:system_info(creation) of
+ Creation when Creation =< 4 -> 16#ffffffff;
+ Creation -> Creation - 1
+ end,
+
+ %% Process of old incarnation...
+ {P5, M5} = spawn_monitor(fun () ->
+ Pid = erts_test_utils:mk_ext_pid({NodeName,
+ OldCreation},
+ 4711, 17),
+ erlang:yield(),
+ _ = erlang:monitor(process, Pid, AliasOpt ++ TagOpt),
+ exit(bang)
+ end),
+ receive {'DOWN', M5, process, P5, bang} -> ok end,
+
+ %% Port of old incarnation...
+ {P6, M6} = spawn_monitor(fun () ->
+ Prt = erts_test_utils:mk_ext_port({NodeName,
+ OldCreation},
+ 4711),
+ erlang:yield(),
+ _ = erlang:monitor(port, Prt, AliasOpt ++ TagOpt),
+ exit(bang)
+ end),
+ receive {'DOWN', M6, process, P6, bang} -> ok end,
+ ok.
+
%%
%% ...
%%