Skip to content

Commit

Permalink
Merge branch 'rickard/port-down-fix/24/erlangGH-8484/OTP-19123' into …
Browse files Browse the repository at this point in the history
…rickard/port-down-fix/25/erlangGH-8484/OTP-19123

* rickard/port-down-fix/24/erlangGH-8484/OTP-19123:
  [erts] Fix DOWN signal from port
  • Loading branch information
rickard-green committed Jun 4, 2024
2 parents 0418c10 + fb56a55 commit 8a7494b
Show file tree
Hide file tree
Showing 2 changed files with 70 additions and 19 deletions.
51 changes: 32 additions & 19 deletions erts/emulator/beam/erl_proc_sig_queue.c
Original file line number Diff line number Diff line change
Expand Up @@ -1279,7 +1279,7 @@ static void do_seq_trace_output(Eterm to, Eterm token, Eterm msg);

static void
send_gen_exit_signal(ErtsPTabElementCommon *sender, Eterm from_tag,
Eterm from, Eterm to,
Eterm from, Eterm from_type, Eterm to,
Sint16 op, Eterm reason, ErtsDistExternal *dist_ext,
ErlHeapFragment *dist_ext_hfrag,
Eterm ref, Eterm token, int normal_kills,
Expand Down Expand Up @@ -1308,6 +1308,7 @@ send_gen_exit_signal(ErtsPTabElementCommon *sender, Eterm from_tag,
(is_non_value(reason) && dist_ext != NULL));

ASSERT(is_immed(from_tag));
ASSERT(from_type == am_process || from_type == am_port);

hsz = sizeof(ErtsExitSignalData)/sizeof(Eterm);

Expand Down Expand Up @@ -1354,7 +1355,7 @@ send_gen_exit_signal(ErtsPTabElementCommon *sender, Eterm from_tag,
break;
}
case ERTS_SIG_Q_OP_MONITOR_DOWN: {
/* {'DOWN', Ref, process, From, Reason} */
/* {'DOWN', Ref, process | port, From, Reason} */
hsz += 6; /* 5-tuple */
break;
}
Expand Down Expand Up @@ -1393,8 +1394,8 @@ send_gen_exit_signal(ErtsPTabElementCommon *sender, Eterm from_tag,
hp += 4;
break;
case ERTS_SIG_Q_OP_MONITOR_DOWN:
/* {'DOWN', Ref, process, From, Reason} */
s_message = TUPLE5(hp, am_DOWN, s_ref, am_process, s_from, s_reason);
/* {'DOWN', Ref, process | port, From, Reason} */
s_message = TUPLE5(hp, am_DOWN, s_ref, from_type, s_from, s_reason);
hp += 6;
break;
default:
Expand Down Expand Up @@ -1999,23 +2000,26 @@ erts_proc_sig_send_exit(ErtsPTabElementCommon *sender, Eterm from, Eterm to,
Eterm reason, Eterm token,
int normal_kills)
{
Eterm from_tag;
Eterm from_tag, from_type;

ASSERT(sender == NULL || sender->id == from);

if (is_immed(from)) {
ASSERT(is_internal_pid(from) || is_internal_port(from));
from_tag = from;
from_type = is_internal_port(from) ? am_port : am_process;
}
else {
DistEntry *dep;
ASSERT(is_external_pid(from));
dep = external_pid_dist_entry(from);
from_tag = dep->sysname;
from_type = am_process;
}

send_gen_exit_signal(sender, from_tag, from, to, ERTS_SIG_Q_OP_EXIT,
reason, NULL, NULL, NIL, token, normal_kills, 0, 0);
send_gen_exit_signal(sender, from_tag, from, from_type, to,
ERTS_SIG_Q_OP_EXIT, reason, NULL, NULL, NIL, token,
normal_kills, 0, 0);
}

void
Expand All @@ -2025,8 +2029,9 @@ erts_proc_sig_send_dist_exit(DistEntry *dep,
ErlHeapFragment *hfrag,
Eterm reason, Eterm token)
{
send_gen_exit_signal(NULL, dep->sysname, from, to, ERTS_SIG_Q_OP_EXIT,
reason, dist_ext, hfrag, NIL, token, 0, 0, 0);
send_gen_exit_signal(NULL, dep->sysname, from, am_process, to,
ERTS_SIG_Q_OP_EXIT, reason, dist_ext, hfrag, NIL, token,
0, 0, 0);

}

Expand All @@ -2049,8 +2054,9 @@ erts_proc_sig_send_link_exit_noconnection(ErtsLink *lnk)
from_tag = elnk->dist->nodename;
conn_id = elnk->dist->connection_id;

send_gen_exit_signal(NULL, from_tag, from_item, to, ERTS_SIG_Q_OP_EXIT_LINKED,
am_noconnection, NULL, NULL, NIL, NIL, 0, !0, conn_id);
send_gen_exit_signal(NULL, from_tag, from_item, am_process, to,
ERTS_SIG_Q_OP_EXIT_LINKED, am_noconnection, NULL, NULL,
NIL, NIL, 0, !0, conn_id);

erts_link_release(lnk);
}
Expand All @@ -2059,7 +2065,7 @@ void
erts_proc_sig_send_link_exit(ErtsPTabElementCommon *sender, Eterm from,
ErtsLink *lnk, Eterm reason, Eterm token)
{
Eterm to;
Eterm to, from_type;

ASSERT(sender == NULL || sender->id == from);
ASSERT(lnk);
Expand All @@ -2068,8 +2074,11 @@ erts_proc_sig_send_link_exit(ErtsPTabElementCommon *sender, Eterm from,

ASSERT(is_internal_pid(from) || is_internal_port(from));

send_gen_exit_signal(sender, from, from, to, ERTS_SIG_Q_OP_EXIT_LINKED,
reason, NULL, NULL, NIL, token, 0, 0, 0);
from_type = is_internal_port(from) ? am_port : am_process;

send_gen_exit_signal(sender, from, from, from_type, to,
ERTS_SIG_Q_OP_EXIT_LINKED, reason, NULL, NULL, NIL,
token, 0, 0, 0);

erts_link_release(lnk);
}
Expand Down Expand Up @@ -2164,8 +2173,9 @@ erts_proc_sig_send_dist_link_exit(DistEntry *dep,
ErlHeapFragment *hfrag,
Eterm reason, Eterm token)
{
send_gen_exit_signal(NULL, dep->sysname, from, to, ERTS_SIG_Q_OP_EXIT_LINKED,
reason, dist_ext, hfrag, NIL, token, 0, 0, 0);
send_gen_exit_signal(NULL, dep->sysname, from, am_process, to,
ERTS_SIG_Q_OP_EXIT_LINKED, reason, dist_ext, hfrag,
NIL, token, 0, 0, 0);

}

Expand Down Expand Up @@ -2271,7 +2281,7 @@ erts_proc_sig_send_dist_monitor_down(DistEntry *dep, Eterm ref,
else
monitored = from;

send_gen_exit_signal(NULL, dep->sysname, monitored,
send_gen_exit_signal(NULL, dep->sysname, monitored, am_process,
to, ERTS_SIG_Q_OP_MONITOR_DOWN,
reason, dist_ext, hfrag, ref, NIL, 0, 0, 0);
}
Expand Down Expand Up @@ -2306,7 +2316,7 @@ erts_proc_sig_send_monitor_down(ErtsPTabElementCommon *sender, Eterm from,
}
else {
ErtsMonitorData *mdp = erts_monitor_to_data(mon);
Eterm from_tag, monitored, heap[3];
Eterm from_tag, monitored, from_type, heap[3];

if (mon->type == ERTS_MON_TYPE_SUSPEND) {
/*
Expand All @@ -2322,6 +2332,7 @@ erts_proc_sig_send_monitor_down(ErtsPTabElementCommon *sender, Eterm from,

if (!(mon->flags & ERTS_ML_FLG_NAME)) {
from_tag = monitored = mdp->origin.other.item;
from_type = is_internal_port(from_tag) ? am_port : am_process;
if (is_external_pid(from_tag)) {
DistEntry *dep = external_pid_dist_entry(from_tag);
from_tag = dep->sysname;
Expand All @@ -2336,18 +2347,20 @@ erts_proc_sig_send_monitor_down(ErtsPTabElementCommon *sender, Eterm from,
if (mdep->dist) {
node = mdep->dist->nodename;
from_tag = node;
from_type = am_process;
}
else {
node = erts_this_dist_entry->sysname;
from_tag = mdp->origin.other.item;
from_type = is_internal_port(from_tag) ? am_port : am_process;
}
ASSERT(is_internal_port(from_tag)
|| is_internal_pid(from_tag)
|| is_atom(from_tag));
monitored = TUPLE2(&heap[0], name, node);
}

send_gen_exit_signal(sender, from_tag, monitored,
send_gen_exit_signal(sender, from_tag, monitored, from_type,
to, ERTS_SIG_Q_OP_MONITOR_DOWN,
reason, NULL, NULL, mdp->ref, NIL,
0, 0, 0);
Expand Down
38 changes: 38 additions & 0 deletions erts/emulator/test/port_SUITE.erl
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@
mon_port_pid_demonitor/1,
mon_port_remote_on_remote/1,
mon_port_driver_die/1,
mon_port_down_sig/1,
mul_basic/1,
mul_slow_writes/1,
name1/1,
Expand Down Expand Up @@ -195,6 +196,7 @@ all() ->
mon_port_pid_demonitor,
mon_port_name_demonitor,
mon_port_driver_die,
mon_port_down_sig,
{group, port_exit_signal_race}].

groups() ->
Expand Down Expand Up @@ -2809,6 +2811,42 @@ mon_port_driver_die(Config) ->
end,
ok.

mon_port_down_sig(Config) ->
ct:log("By id with immediate reason"),
chk_port_down(Config, undefined, bye),
ct:log("By id with non-immediate reason"),
chk_port_down(Config, undefined, {bye, bye}),
ct:log("By name with immediate reason"),
chk_port_down(Config, a_port_test_name, bye),
ct:log("By name with non-immediate reason"),
chk_port_down(Config, another_port_test_name, {bye, bye}),
ok.

chk_port_down(Config, Name, Reason) ->
Port = create_port(Config, ["-h1", "-q"]), % will close after we send 1 byte
true = is_port(Port),
{MonWhat, DownItem} = if Name == undefined ->
{Port, Port};
true ->
true = register(Name, Port),
{Name, {Name, node()}}
end,
Mon = erlang:monitor(port, MonWhat),
unlink(Port),
receive after 100 -> ok end,
Proc = spawn(fun () ->
link(Port),
exit(Reason)
end),
receive
{'DOWN', Mon, Type, Item, ExitReason} ->
port = Type,
Reason = ExitReason,
DownItem = Item
end,
false = is_process_alive(Proc),
ok.

-ifdef(DISABLED_TESTCASE).
%% 1. Spawn a port which will sleep 3 seconds
%% 2. Monitor port
Expand Down

0 comments on commit 8a7494b

Please sign in to comment.