diff options
author | Rickard Green <rickard@erlang.org> | 2022-08-10 13:29:59 +0200 |
---|---|---|
committer | Rickard Green <rickard@erlang.org> | 2022-08-12 18:55:48 +0200 |
commit | ad8742311cab2f56f8702fc2206d29d0ceca922e (patch) | |
tree | f3c92feb24cd8ded23cdd2f9b097b02f282241e4 | |
parent | 0863bd30aabd035c83158c78046c5ffda16127e1 (diff) | |
download | erlang-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.c | 113 | ||||
-rw-r--r-- | erts/emulator/beam/break.c | 1 | ||||
-rw-r--r-- | erts/emulator/beam/erl_bif_info.c | 7 | ||||
-rw-r--r-- | erts/emulator/beam/erl_monitor_link.c | 5 | ||||
-rw-r--r-- | erts/emulator/beam/erl_monitor_link.h | 61 | ||||
-rw-r--r-- | erts/emulator/beam/erl_proc_sig_queue.c | 40 | ||||
-rw-r--r-- | erts/emulator/beam/erl_process.c | 19 | ||||
-rw-r--r-- | erts/emulator/beam/global.h | 7 | ||||
-rw-r--r-- | erts/emulator/test/monitor_SUITE.erl | 226 |
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. + %% %% ... %% |