summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRickard Green <rickard@erlang.org>2021-04-20 16:46:19 +0200
committerRickard Green <rickard@erlang.org>2021-04-22 18:46:08 +0200
commit18f9f7d1439c200b5517ad9d65097553a0735a6b (patch)
tree7dc5f6b81438579b3160ed2d12475fcc94fdebe1
parent15ac634091f25df3a46c7f354711773167602994 (diff)
downloaderlang-18f9f7d1439c200b5517ad9d65097553a0735a6b.tar.gz
Ensure is_process_alive() and process_info() respect signal order
The reply signal sent as a result of a call to the is_process_alive() or the process_info() BIFs could pass before other signals sent between the involved processes. That is, the reply signals could be delivered too early.
-rw-r--r--erts/emulator/beam/erl_bif_info.c10
-rw-r--r--erts/emulator/beam/erl_proc_sig_queue.c7
-rw-r--r--erts/emulator/beam/erl_proc_sig_queue.h10
3 files changed, 22 insertions, 5 deletions
diff --git a/erts/emulator/beam/erl_bif_info.c b/erts/emulator/beam/erl_bif_info.c
index 96f399fbbe..5c58c68369 100644
--- a/erts/emulator/beam/erl_bif_info.c
+++ b/erts/emulator/beam/erl_bif_info.c
@@ -1212,7 +1212,10 @@ process_info_bif(Process *c_p, Eterm pid, Eterm opt, int always_wrap, int pi2)
goto send_signal;
}
- ERTS_BIF_PREP_RET(ret, res);
+ if (c_p == rp || !ERTS_PROC_HAS_INCOMING_SIGNALS(c_p))
+ ERTS_BIF_PREP_RET(ret, res);
+ else
+ ERTS_BIF_PREP_HANDLE_SIGNALS_RETURN(ret, c_p, res);
done:
@@ -3570,7 +3573,10 @@ BIF_RETTYPE erts_internal_is_process_alive_2(BIF_ALIST_2)
{
if (!is_internal_pid(BIF_ARG_1) || !is_internal_ordinary_ref(BIF_ARG_2))
BIF_ERROR(BIF_P, BADARG);
- erts_proc_sig_send_is_alive_request(BIF_P, BIF_ARG_1, BIF_ARG_2);
+ if (!erts_proc_sig_send_is_alive_request(BIF_P, BIF_ARG_1, BIF_ARG_2)) {
+ if (ERTS_PROC_HAS_INCOMING_SIGNALS(BIF_P))
+ ERTS_BIF_HANDLE_SIGNALS_RETURN(BIF_P, am_ok);
+ }
BIF_RET(am_ok);
}
diff --git a/erts/emulator/beam/erl_proc_sig_queue.c b/erts/emulator/beam/erl_proc_sig_queue.c
index d475a0a634..5d7e5ff999 100644
--- a/erts/emulator/beam/erl_proc_sig_queue.c
+++ b/erts/emulator/beam/erl_proc_sig_queue.c
@@ -1528,7 +1528,7 @@ erts_proc_sig_send_group_leader(Process *c_p, Eterm to, Eterm gl, Eterm ref)
group_leader_reply(c_p, c_p->common.id, ref, 0);
}
-void
+int
erts_proc_sig_send_is_alive_request(Process *c_p, Eterm to, Eterm ref)
{
ErlHeapFragment *hfrag;
@@ -1562,13 +1562,16 @@ erts_proc_sig_send_is_alive_request(Process *c_p, Eterm to, Eterm ref)
ERTS_SIG_Q_TYPE_UNDEFINED,
0);
- if (proc_queue_signal(c_p, to, (ErtsSignal *) mp, ERTS_SIG_Q_OP_IS_ALIVE))
+ if (proc_queue_signal(c_p, to, (ErtsSignal *) mp, ERTS_SIG_Q_OP_IS_ALIVE)) {
(void) maybe_elevate_sig_handling_prio(c_p, to);
+ return !0;
+ }
else {
/* It wasn't alive; reply to ourselves... */
mp->next = NULL;
mp->data.attached = ERTS_MSG_COMBINED_HFRAG;
erts_queue_message(c_p, ERTS_PROC_LOCK_MAIN, mp, msg, am_system);
+ return 0;
}
}
diff --git a/erts/emulator/beam/erl_proc_sig_queue.h b/erts/emulator/beam/erl_proc_sig_queue.h
index 6b065a7add..fa57fdf04b 100644
--- a/erts/emulator/beam/erl_proc_sig_queue.h
+++ b/erts/emulator/beam/erl_proc_sig_queue.h
@@ -180,6 +180,10 @@ void erts_proc_sig_hdbg_check_in_queue(struct process *c_p, char *what,
struct dist_entry_;
+#define ERTS_PROC_HAS_INCOMING_SIGNALS(P) \
+ (!!(erts_atomic32_read_nob(&(P)->state) \
+ & (ERTS_PSFLG_SIG_Q|ERTS_PSFLG_SIG_IN_Q)))
+
/*
* Send operations of currently supported process signals follow...
*/
@@ -506,8 +510,12 @@ erts_proc_sig_send_group_leader(Process *c_p, Eterm to, Eterm gl,
* message to the sending
* process (i.e., c_p).
*
+ * @returns A value != 0 if the request
+ * was sent; otherwise, 0. If
+ * the request was not sent the
+ * process was non-existing.
*/
-void
+int
erts_proc_sig_send_is_alive_request(Process *c_p, Eterm to,
Eterm ref);