diff options
author | Rickard Green <rickard@erlang.org> | 2021-04-20 16:46:19 +0200 |
---|---|---|
committer | Rickard Green <rickard@erlang.org> | 2021-04-22 18:46:08 +0200 |
commit | 18f9f7d1439c200b5517ad9d65097553a0735a6b (patch) | |
tree | 7dc5f6b81438579b3160ed2d12475fcc94fdebe1 | |
parent | 15ac634091f25df3a46c7f354711773167602994 (diff) | |
download | erlang-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.c | 10 | ||||
-rw-r--r-- | erts/emulator/beam/erl_proc_sig_queue.c | 7 | ||||
-rw-r--r-- | erts/emulator/beam/erl_proc_sig_queue.h | 10 |
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); |