summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRickard Green <rickard@erlang.org>2021-04-22 18:55:58 +0200
committerRickard Green <rickard@erlang.org>2021-04-22 18:55:58 +0200
commitfbf4bcb926627cb45bc368973430bf728d5302d9 (patch)
tree5ff70aa55e2f7565e057caf83b2c6866a9e07682
parent67d0dd0997c3ac162b180cf86a084b34cabb9e0b (diff)
parent18f9f7d1439c200b5517ad9d65097553a0735a6b (diff)
downloaderlang-fbf4bcb926627cb45bc368973430bf728d5302d9.tar.gz
Merge branch 'rickard/signal-order-fix/OTP-17291' into rickard/signal-order-fix/21/OTP-17291
* rickard/signal-order-fix/OTP-17291: Ensure is_process_alive() and process_info() respect signal order Ensure reply signals from ports respect signal order Ensure GC and CPC signals respect signal order
-rw-r--r--erts/emulator/beam/atom.names3
-rw-r--r--erts/emulator/beam/bif.c47
-rw-r--r--erts/emulator/beam/bif.h9
-rw-r--r--erts/emulator/beam/erl_bif_info.c10
-rw-r--r--erts/emulator/beam/erl_bif_port.c389
-rw-r--r--erts/emulator/beam/erl_proc_sig_queue.c7
-rw-r--r--erts/emulator/beam/erl_proc_sig_queue.h10
-rw-r--r--erts/emulator/beam/erl_process.c161
-rw-r--r--erts/emulator/test/code_SUITE.erl50
-rw-r--r--erts/emulator/test/gc_SUITE.erl47
-rw-r--r--erts/emulator/test/process_SUITE.erl59
-rw-r--r--erts/preloaded/ebin/erlang.beambin101968 -> 101832 bytes
-rw-r--r--erts/preloaded/ebin/erts_internal.beambin18104 -> 17916 bytes
-rw-r--r--erts/preloaded/src/erlang.erl8
-rw-r--r--erts/preloaded/src/erts_internal.erl10
15 files changed, 581 insertions, 229 deletions
diff --git a/erts/emulator/beam/atom.names b/erts/emulator/beam/atom.names
index 09ad989c4f..c861bb21ca 100644
--- a/erts/emulator/beam/atom.names
+++ b/erts/emulator/beam/atom.names
@@ -119,6 +119,7 @@ atom badarg badarith badarity badfile badfun badkey badmap badmatch badsig
atom bag
atom band
atom big
+atom bif_handle_signals_return
atom bif_return_trap
atom binary
atom binary_copy_trap
@@ -278,6 +279,7 @@ atom free
atom fullsweep_after
atom functions
atom function_clause
+atom garbage_collect
atom garbage_collecting
atom garbage_collection
atom garbage_collection_info
@@ -328,6 +330,7 @@ atom infinity
atom info
atom info_msg
atom info_trap
+atom inherit
atom init
atom initial_call
atom input
diff --git a/erts/emulator/beam/bif.c b/erts/emulator/beam/bif.c
index 8e1254fb33..e4e6d7446f 100644
--- a/erts/emulator/beam/bif.c
+++ b/erts/emulator/beam/bif.c
@@ -4851,7 +4851,50 @@ static BIF_RETTYPE bif_return_trap(BIF_ALIST_2)
BIF_RET(res);
}
+static BIF_RETTYPE
+bif_handle_signals_return(BIF_ALIST_1)
+{
+ int local_only = BIF_P->flags & F_LOCAL_SIGS_ONLY;
+ int sres, sreds, reds_left;
+ erts_aint32_t state;
+
+ reds_left = ERTS_BIF_REDS_LEFT(BIF_P);
+ sreds = reds_left;
+
+ if (!local_only) {
+ erts_proc_lock(BIF_P, ERTS_PROC_LOCK_MSGQ);
+ erts_proc_sig_fetch(BIF_P);
+ erts_proc_unlock(BIF_P, ERTS_PROC_LOCK_MSGQ);
+ }
+
+ state = erts_atomic32_read_nob(&BIF_P->state);
+ sres = erts_proc_sig_handle_incoming(BIF_P, &state, &sreds,
+ sreds, !0);
+
+ BUMP_REDS(BIF_P, (int) sreds);
+ reds_left -= sreds;
+
+ if (state & ERTS_PSFLG_EXITING) {
+ BIF_P->flags &= ~F_LOCAL_SIGS_ONLY;
+ ERTS_BIF_EXITED(BIF_P);
+ }
+ if (!sres | (reds_left <= 0)) {
+ /*
+ * More signals to handle or out of reds; need
+ * to yield and continue. Prevent fetching of
+ * more signals by setting local-sigs-only flag.
+ */
+ BIF_P->flags |= F_LOCAL_SIGS_ONLY;
+ ERTS_BIF_YIELD1(&erts_bif_handle_signals_return_export,
+ BIF_P, BIF_ARG_1);
+ }
+
+ BIF_P->flags &= ~F_LOCAL_SIGS_ONLY;
+ BIF_RET(BIF_ARG_1);
+}
+
Export bif_return_trap_export;
+Export erts_bif_handle_signals_return_export;
void erts_init_trap_export(Export* ep, Eterm m, Eterm f, Uint a,
Eterm (*bif)(BIF_ALIST))
@@ -4878,6 +4921,10 @@ void erts_init_bif(void)
am_erlang, am_bif_return_trap, 2,
&bif_return_trap);
+ erts_init_trap_export(&erts_bif_handle_signals_return_export,
+ am_erlang, am_bif_handle_signals_return, 1,
+ &bif_handle_signals_return);
+
erts_await_result = erts_export_put(am_erts_internal,
am_await_result,
1);
diff --git a/erts/emulator/beam/bif.h b/erts/emulator/beam/bif.h
index cf9f61c0b8..bad047b92f 100644
--- a/erts/emulator/beam/bif.h
+++ b/erts/emulator/beam/bif.h
@@ -462,6 +462,15 @@ do { \
BIF_TRAP4((TRP), (P), (A0), (A1), (A2), (A3)); \
} while (0)
+extern Export erts_bif_handle_signals_return_export;
+
+#define ERTS_BIF_HANDLE_SIGNALS_RETURN(P, VAL) \
+ BIF_TRAP1(&erts_bif_handle_signals_return_export, (P), (VAL))
+
+#define ERTS_BIF_PREP_HANDLE_SIGNALS_RETURN(Ret, P, Val) \
+ ERTS_BIF_PREP_TRAP1((Ret), &erts_bif_handle_signals_return_export, \
+ (P), (Val))
+
#define ERTS_BIF_PREP_EXITED(RET, PROC) \
do { \
KILL_CATCHES((PROC)); \
diff --git a/erts/emulator/beam/erl_bif_info.c b/erts/emulator/beam/erl_bif_info.c
index 51af067908..b6d504daa9 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:
@@ -3592,7 +3595,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_bif_port.c b/erts/emulator/beam/erl_bif_port.c
index ed825d3dda..40a2fb96d6 100644
--- a/erts/emulator/beam/erl_bif_port.c
+++ b/erts/emulator/beam/erl_bif_port.c
@@ -167,7 +167,7 @@ BIF_RETTYPE erts_internal_port_command_3(BIF_ALIST_3)
BIF_RETTYPE res;
Port *prt;
int flags = 0;
- Eterm ref;
+ erts_aint32_t state;
if (is_not_nil(BIF_ARG_3)) {
Eterm l = BIF_ARG_3;
@@ -188,51 +188,59 @@ BIF_RETTYPE erts_internal_port_command_3(BIF_ALIST_3)
prt = sig_lookup_port(BIF_P, BIF_ARG_1);
if (!prt)
- BIF_RET(am_badarg);
-
- if (flags & ERTS_PORT_SIG_FLG_FORCE) {
- if (!(prt->drv_ptr->flags & ERL_DRV_FLAG_SOFT_BUSY))
- BIF_RET(am_notsup);
+ ERTS_BIF_PREP_RET(res, am_badarg);
+ else if ((flags & ERTS_PORT_SIG_FLG_FORCE)
+ && !(prt->drv_ptr->flags & ERL_DRV_FLAG_SOFT_BUSY)) {
+ ERTS_BIF_PREP_RET(res, am_notsup);
}
-
+ else {
+ Eterm ref;
#ifdef DEBUG
- ref = NIL;
+ ref = NIL;
#endif
- switch (erts_port_output(BIF_P, flags, prt, prt->common.id, BIF_ARG_2, &ref)) {
- case ERTS_PORT_OP_BADARG:
- case ERTS_PORT_OP_DROPPED:
- ERTS_BIF_PREP_RET(res, am_badarg);
- break;
- case ERTS_PORT_OP_BUSY:
- ASSERT(!(flags & ERTS_PORT_SIG_FLG_FORCE));
- if (flags & ERTS_PORT_SIG_FLG_NOSUSPEND)
- ERTS_BIF_PREP_RET(res, am_false);
- else {
- erts_suspend(BIF_P, ERTS_PROC_LOCK_MAIN, prt);
- ERTS_BIF_PREP_YIELD3(res, bif_export[BIF_erts_internal_port_command_3],
- BIF_P, BIF_ARG_1, BIF_ARG_2, BIF_ARG_3);
- }
- break;
- case ERTS_PORT_OP_BUSY_SCHEDULED:
- ASSERT(!(flags & ERTS_PORT_SIG_FLG_FORCE));
- /* Fall through... */
- case ERTS_PORT_OP_SCHEDULED:
- ASSERT(is_internal_ordinary_ref(ref));
- ERTS_BIF_PREP_RET(res, ref);
- break;
- case ERTS_PORT_OP_DONE:
- ERTS_BIF_PREP_RET(res, am_true);
- break;
- default:
- ERTS_INTERNAL_ERROR("Unexpected erts_port_output() result");
- break;
+ switch (erts_port_output(BIF_P, flags, prt, prt->common.id,
+ BIF_ARG_2, &ref)) {
+ case ERTS_PORT_OP_BADARG:
+ case ERTS_PORT_OP_DROPPED:
+ ERTS_BIF_PREP_RET(res, am_badarg);
+ break;
+ case ERTS_PORT_OP_BUSY:
+ ASSERT(!(flags & ERTS_PORT_SIG_FLG_FORCE));
+ if (flags & ERTS_PORT_SIG_FLG_NOSUSPEND)
+ ERTS_BIF_PREP_RET(res, am_false);
+ else {
+ erts_suspend(BIF_P, ERTS_PROC_LOCK_MAIN, prt);
+ ERTS_BIF_PREP_YIELD3(res, bif_export[BIF_erts_internal_port_command_3],
+ BIF_P, BIF_ARG_1, BIF_ARG_2, BIF_ARG_3);
+ }
+ break;
+ case ERTS_PORT_OP_BUSY_SCHEDULED:
+ ASSERT(!(flags & ERTS_PORT_SIG_FLG_FORCE));
+ /* Fall through... */
+ case ERTS_PORT_OP_SCHEDULED:
+ ASSERT(is_internal_ordinary_ref(ref));
+ BIF_RET(ref);
+ case ERTS_PORT_OP_DONE:
+ ERTS_BIF_PREP_RET(res, am_true);
+ break;
+ default:
+ ERTS_INTERNAL_ERROR("Unexpected erts_port_output() result");
+ ERTS_BIF_PREP_RET(res, am_internal_error);
+ break;
+ }
}
- if (ERTS_PROC_IS_EXITING(BIF_P)) {
+ state = erts_atomic32_read_acqb(&BIF_P->state);
+ if (state & ERTS_PSFLG_EXITING) {
KILL_CATCHES(BIF_P); /* Must exit */
ERTS_BIF_PREP_ERROR(res, BIF_P, EXC_ERROR);
}
+ else {
+ /* Ensure signal order is preserved... */
+ if (state & (ERTS_PSFLG_SIG_Q|ERTS_PSFLG_SIG_IN_Q))
+ ERTS_BIF_PREP_HANDLE_SIGNALS_RETURN(res, BIF_P, res);
+ }
return res;
}
@@ -242,41 +250,46 @@ BIF_RETTYPE erts_internal_port_call_3(BIF_ALIST_3)
Port* prt;
Eterm retval;
Uint uint_op;
- unsigned int op;
erts_aint32_t state;
prt = sig_lookup_port(BIF_P, BIF_ARG_1);
if (!prt)
- BIF_RET(am_badarg);
-
- if (!term_to_Uint(BIF_ARG_2, &uint_op))
- BIF_RET(am_badarg);
-
- if (uint_op > (Uint) UINT_MAX)
- BIF_RET(am_badarg);
-
- op = (unsigned int) uint_op;
-
- switch (erts_port_call(BIF_P, prt, op, BIF_ARG_3, &retval)) {
- case ERTS_PORT_OP_DROPPED:
- case ERTS_PORT_OP_BADARG:
retval = am_badarg;
- break;
- case ERTS_PORT_OP_SCHEDULED:
- ASSERT(is_internal_ordinary_ref(retval));
- break;
- case ERTS_PORT_OP_DONE:
- ASSERT(is_not_internal_ref(retval));
- break;
- default:
- ERTS_INTERNAL_ERROR("Unexpected erts_port_call() result");
- retval = am_internal_error;
- break;
+ else if (!term_to_Uint(BIF_ARG_2, &uint_op))
+ retval = am_badarg;
+ else if (uint_op > (Uint) UINT_MAX)
+ retval = am_badarg;
+ else {
+ unsigned int op = (unsigned int) uint_op;
+
+ switch (erts_port_call(BIF_P, prt, op, BIF_ARG_3, &retval)) {
+ case ERTS_PORT_OP_DROPPED:
+ case ERTS_PORT_OP_BADARG:
+ retval = am_badarg;
+ break;
+ case ERTS_PORT_OP_SCHEDULED:
+ ASSERT(is_internal_ordinary_ref(retval));
+ /* Signal order preserved by reply... */
+ BIF_RET(retval);
+ break;
+ case ERTS_PORT_OP_DONE:
+ ASSERT(is_not_internal_ref(retval));
+ break;
+ default:
+ ERTS_INTERNAL_ERROR("Unexpected erts_port_call() result");
+ retval = am_internal_error;
+ break;
+ }
}
state = erts_atomic32_read_acqb(&BIF_P->state);
if (state & ERTS_PSFLG_EXITING)
ERTS_BIF_EXITED(BIF_P);
+ else {
+ /* Ensure signal order is preserved... */
+ if (state & (ERTS_PSFLG_SIG_Q|ERTS_PSFLG_SIG_IN_Q))
+ ERTS_BIF_HANDLE_SIGNALS_RETURN(BIF_P, retval);
+ }
BIF_RET(retval);
}
@@ -286,41 +299,45 @@ BIF_RETTYPE erts_internal_port_control_3(BIF_ALIST_3)
Port* prt;
Eterm retval;
Uint uint_op;
- unsigned int op;
erts_aint32_t state;
prt = sig_lookup_port(BIF_P, BIF_ARG_1);
if (!prt)
- BIF_RET(am_badarg);
-
- if (!term_to_Uint(BIF_ARG_2, &uint_op))
- BIF_RET(am_badarg);
-
- if (uint_op > (Uint) UINT_MAX)
- BIF_RET(am_badarg);
-
- op = (unsigned int) uint_op;
-
- switch (erts_port_control(BIF_P, prt, op, BIF_ARG_3, &retval)) {
- case ERTS_PORT_OP_BADARG:
- case ERTS_PORT_OP_DROPPED:
retval = am_badarg;
- break;
- case ERTS_PORT_OP_SCHEDULED:
- ASSERT(is_internal_ordinary_ref(retval));
- break;
- case ERTS_PORT_OP_DONE:
- ASSERT(is_not_internal_ref(retval));
- break;
- default:
- ERTS_INTERNAL_ERROR("Unexpected erts_port_control() result");
- retval = am_internal_error;
- break;
+ else if (!term_to_Uint(BIF_ARG_2, &uint_op))
+ retval = am_badarg;
+ else if (uint_op > (Uint) UINT_MAX)
+ retval = am_badarg;
+ else {
+ unsigned int op = (unsigned int) uint_op;
+
+ switch (erts_port_control(BIF_P, prt, op, BIF_ARG_3, &retval)) {
+ case ERTS_PORT_OP_BADARG:
+ case ERTS_PORT_OP_DROPPED:
+ retval = am_badarg;
+ break;
+ case ERTS_PORT_OP_SCHEDULED:
+ ASSERT(is_internal_ordinary_ref(retval));
+ /* Signal order preserved by reply... */
+ BIF_RET(retval);
+ case ERTS_PORT_OP_DONE:
+ ASSERT(is_not_internal_ref(retval));
+ break;
+ default:
+ ERTS_INTERNAL_ERROR("Unexpected erts_port_control() result");
+ retval = am_internal_error;
+ break;
+ }
}
state = erts_atomic32_read_acqb(&BIF_P->state);
if (state & ERTS_PSFLG_EXITING)
ERTS_BIF_EXITED(BIF_P);
+ else {
+ /* Ensure signal order is preserved... */
+ if (state & (ERTS_PSFLG_SIG_Q|ERTS_PSFLG_SIG_IN_Q))
+ ERTS_BIF_HANDLE_SIGNALS_RETURN(BIF_P, retval);
+ }
BIF_RET(retval);
}
@@ -331,30 +348,44 @@ BIF_RETTYPE erts_internal_port_control_3(BIF_ALIST_3)
*/
BIF_RETTYPE erts_internal_port_close_1(BIF_ALIST_1)
{
- Eterm ref;
+ Eterm retval;
Port *prt;
+ prt = sig_lookup_port(BIF_P, BIF_ARG_1);
+ if (!prt)
+ retval = am_badarg;
+ else {
+
#ifdef DEBUG
- ref = NIL;
+ retval = NIL;
#endif
- prt = sig_lookup_port(BIF_P, BIF_ARG_1);
- if (!prt)
- BIF_RET(am_badarg);
-
- switch (erts_port_exit(BIF_P, 0, prt, BIF_P->common.id, am_normal, &ref)) {
- case ERTS_PORT_OP_BADARG:
- case ERTS_PORT_OP_DROPPED:
- BIF_RET(am_badarg);
- case ERTS_PORT_OP_SCHEDULED:
- ASSERT(is_internal_ordinary_ref(ref));
- BIF_RET(ref);
- case ERTS_PORT_OP_DONE:
- BIF_RET(am_true);
- default:
- ERTS_INTERNAL_ERROR("Unexpected erts_port_exit() result");
- BIF_RET(am_internal_error);
+ switch (erts_port_exit(BIF_P, 0, prt, BIF_P->common.id,
+ am_normal, &retval)) {
+ case ERTS_PORT_OP_BADARG:
+ case ERTS_PORT_OP_DROPPED:
+ retval = am_badarg;
+ break;
+ case ERTS_PORT_OP_SCHEDULED:
+ ASSERT(is_internal_ordinary_ref(retval));
+ /* Signal order preserved by reply... */
+ BIF_RET(retval);
+ break;
+ case ERTS_PORT_OP_DONE:
+ retval = am_true;
+ break;
+ default:
+ ERTS_INTERNAL_ERROR("Unexpected erts_port_exit() result");
+ retval = am_internal_error;
+ break;
+ }
}
+
+ /* Ensure signal order is preserved... */
+ if (ERTS_PROC_HAS_INCOMING_SIGNALS(BIF_P))
+ ERTS_BIF_HANDLE_SIGNALS_RETURN(BIF_P, retval);
+
+ BIF_RET(retval);
}
/*
@@ -363,32 +394,42 @@ BIF_RETTYPE erts_internal_port_close_1(BIF_ALIST_1)
*/
BIF_RETTYPE erts_internal_port_connect_2(BIF_ALIST_2)
{
- Eterm ref;
+ Eterm retval;
Port* prt;
prt = sig_lookup_port(BIF_P, BIF_ARG_1);
if (!prt)
- BIF_RET(am_badarg);
-
+ retval = am_badarg;
+ else {
#ifdef DEBUG
- ref = NIL;
+ retval = NIL;
#endif
- switch (erts_port_connect(BIF_P, 0, prt, BIF_P->common.id, BIF_ARG_2, &ref)) {
- case ERTS_PORT_OP_BADARG:
- case ERTS_PORT_OP_DROPPED:
- BIF_RET(am_badarg);
- case ERTS_PORT_OP_SCHEDULED:
- ASSERT(is_internal_ordinary_ref(ref));
- BIF_RET(ref);
- break;
- case ERTS_PORT_OP_DONE:
- BIF_RET(am_true);
- break;
- default:
- ERTS_INTERNAL_ERROR("Unexpected erts_port_connect() result");
- BIF_RET(am_internal_error);
+ switch (erts_port_connect(BIF_P, 0, prt, BIF_P->common.id,
+ BIF_ARG_2, &retval)) {
+ case ERTS_PORT_OP_BADARG:
+ case ERTS_PORT_OP_DROPPED:
+ retval = am_badarg;
+ break;
+ case ERTS_PORT_OP_SCHEDULED:
+ ASSERT(is_internal_ordinary_ref(retval));
+ /* Signal order preserved by reply... */
+ BIF_RET(retval);
+ case ERTS_PORT_OP_DONE:
+ retval = am_true;
+ break;
+ default:
+ ERTS_INTERNAL_ERROR("Unexpected erts_port_connect() result");
+ retval = am_internal_error;
+ break;
+ }
}
+
+ /* Ensure signal order is preserved... */
+ if (ERTS_PROC_HAS_INCOMING_SIGNALS(BIF_P))
+ ERTS_BIF_HANDLE_SIGNALS_RETURN(BIF_P, retval);
+
+ BIF_RET(retval);
}
BIF_RETTYPE erts_internal_port_info_1(BIF_ALIST_1)
@@ -399,33 +440,44 @@ BIF_RETTYPE erts_internal_port_info_1(BIF_ALIST_1)
if (is_internal_port(BIF_ARG_1) || is_atom(BIF_ARG_1)) {
prt = sig_lookup_port(BIF_P, BIF_ARG_1);
if (!prt)
- BIF_RET(am_undefined);
+ retval = am_undefined;
+ else {
+ switch (erts_port_info(BIF_P, prt, THE_NON_VALUE, &retval)) {
+ case ERTS_PORT_OP_BADARG:
+ retval = am_badarg;
+ break;
+ case ERTS_PORT_OP_DROPPED:
+ retval = am_undefined;
+ break;
+ case ERTS_PORT_OP_SCHEDULED:
+ ASSERT(is_internal_ordinary_ref(retval));
+ /* Signal order preserved by reply... */
+ BIF_RET(retval);
+ case ERTS_PORT_OP_DONE:
+ ASSERT(is_not_internal_ref(retval));
+ break;
+ default:
+ ERTS_INTERNAL_ERROR("Unexpected erts_port_info() result");
+ retval = am_internal_error;
+ break;
+ }
+ }
}
else if (is_external_port(BIF_ARG_1)) {
if (external_port_dist_entry(BIF_ARG_1) == erts_this_dist_entry)
- BIF_RET(am_undefined);
+ retval = am_undefined;
else
- BIF_RET(am_badarg);
+ retval = am_badarg;
}
else {
- BIF_RET(am_badarg);
- }
-
- switch (erts_port_info(BIF_P, prt, THE_NON_VALUE, &retval)) {
- case ERTS_PORT_OP_BADARG:
- BIF_RET(am_badarg);
- case ERTS_PORT_OP_DROPPED:
- BIF_RET(am_undefined);
- case ERTS_PORT_OP_SCHEDULED:
- ASSERT(is_internal_ordinary_ref(retval));
- BIF_RET(retval);
- case ERTS_PORT_OP_DONE:
- ASSERT(is_not_internal_ref(retval));
- BIF_RET(retval);
- default:
- ERTS_INTERNAL_ERROR("Unexpected erts_port_info() result");
- BIF_RET(am_internal_error);
+ retval = am_badarg;
}
+
+ /* Ensure signal order is preserved... */
+ if (ERTS_PROC_HAS_INCOMING_SIGNALS(BIF_P))
+ ERTS_BIF_HANDLE_SIGNALS_RETURN(BIF_P, retval);
+
+ BIF_RET(retval);
}
@@ -437,33 +489,44 @@ BIF_RETTYPE erts_internal_port_info_2(BIF_ALIST_2)
if (is_internal_port(BIF_ARG_1) || is_atom(BIF_ARG_1)) {
prt = sig_lookup_port(BIF_P, BIF_ARG_1);
if (!prt)
- BIF_RET(am_undefined);
+ retval = am_undefined;
+ else {
+ switch (erts_port_info(BIF_P, prt, BIF_ARG_2, &retval)) {
+ case ERTS_PORT_OP_BADARG:
+ retval = am_badarg;
+ break;
+ case ERTS_PORT_OP_DROPPED:
+ retval = am_undefined;
+ break;
+ case ERTS_PORT_OP_SCHEDULED:
+ ASSERT(is_internal_ordinary_ref(retval));
+ /* Signal order preserved by reply... */
+ BIF_RET(retval);
+ case ERTS_PORT_OP_DONE:
+ ASSERT(is_not_internal_ref(retval));
+ break;
+ default:
+ ERTS_INTERNAL_ERROR("Unexpected erts_port_info() result");
+ retval = am_internal_error;
+ break;
+ }
+ }
}
else if (is_external_port(BIF_ARG_1)) {
if (external_port_dist_entry(BIF_ARG_1) == erts_this_dist_entry)
- BIF_RET(am_undefined);
+ retval = am_undefined;
else
- BIF_RET(am_badarg);
+ retval = am_badarg;
}
else {
- BIF_RET(am_badarg);
- }
-
- switch (erts_port_info(BIF_P, prt, BIF_ARG_2, &retval)) {
- case ERTS_PORT_OP_BADARG:
- BIF_RET(am_badarg);
- case ERTS_PORT_OP_DROPPED:
- BIF_RET(am_undefined);
- case ERTS_PORT_OP_SCHEDULED:
- ASSERT(is_internal_ordinary_ref(retval));
- BIF_RET(retval);
- case ERTS_PORT_OP_DONE:
- ASSERT(is_not_internal_ref(retval));
- BIF_RET(retval);
- default:
- ERTS_INTERNAL_ERROR("Unexpected erts_port_info() result");
- BIF_RET(am_internal_error);
+ retval = am_badarg;
}
+
+ /* Ensure signal order is preserved... */
+ if (ERTS_PROC_HAS_INCOMING_SIGNALS(BIF_P))
+ ERTS_BIF_HANDLE_SIGNALS_RETURN(BIF_P, retval);
+
+ BIF_RET(retval);
}
/*
diff --git a/erts/emulator/beam/erl_proc_sig_queue.c b/erts/emulator/beam/erl_proc_sig_queue.c
index ea8282de1a..902867f2d3 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);
diff --git a/erts/emulator/beam/erl_process.c b/erts/emulator/beam/erl_process.c
index 3ab4fa9abf..ec7082f8ec 100644
--- a/erts/emulator/beam/erl_process.c
+++ b/erts/emulator/beam/erl_process.c
@@ -450,7 +450,8 @@ typedef enum {
ERTS_PSTT_COHMQ, /* Change off heap message queue */
ERTS_PSTT_FTMQ, /* Flush trace msg queue */
ERTS_PSTT_ETS_FREE_FIXATION,
- ERTS_PSTT_PRIO_SIG /* Elevate prio on signal management */
+ ERTS_PSTT_PRIO_SIG, /* Elevate prio on signal management */
+ ERTS_PSTT_TEST
} ErtsProcSysTaskType;
#define ERTS_MAX_PROC_SYS_TASK_ARGS 2
@@ -459,6 +460,7 @@ struct ErtsProcSysTask_ {
ErtsProcSysTask *next;
ErtsProcSysTask *prev;
ErtsProcSysTaskType type;
+ Eterm prio;
Eterm requester;
Eterm reply_tag;
Eterm req_id;
@@ -10473,6 +10475,9 @@ execute_sys_tasks(Process *c_p, erts_aint32_t *statep, int in_reds)
}
break;
}
+ case ERTS_PSTT_TEST:
+ st_res = am_true;
+ break;
default:
ERTS_INTERNAL_ERROR("Invalid process sys task type");
st_res = am_false;
@@ -10530,6 +10535,7 @@ cleanup_sys_tasks(Process *c_p, erts_aint32_t in_state, int in_reds)
case ERTS_PSTT_CPC:
case ERTS_PSTT_COHMQ:
case ERTS_PSTT_ETS_FREE_FIXATION:
+ case ERTS_PSTT_TEST:
st_res = am_false;
break;
case ERTS_PSTT_CLA:
@@ -10671,7 +10677,7 @@ erts_execute_dirty_system_task(Process *c_p)
static BIF_RETTYPE
dispatch_system_task(Process *c_p, erts_aint_t fail_state,
ErtsProcSysTask *st, Eterm target,
- Eterm prio, Eterm operation)
+ Eterm operation)
{
Process *rp;
ErtsProcLocks rp_locks = 0;
@@ -10683,9 +10689,19 @@ dispatch_system_task(Process *c_p, erts_aint_t fail_state,
switch (st->type) {
case ERTS_PSTT_CPC:
- rp = erts_dirty_process_signal_handler;
ASSERT(fail_state & (ERTS_PSFLG_DIRTY_RUNNING
| ERTS_PSFLG_DIRTY_RUNNING_SYS));
+ switch (st->prio) {
+ case am_max:
+ rp = erts_dirty_process_signal_handler_max;
+ break;
+ case am_high:
+ rp = erts_dirty_process_signal_handler_high;
+ break;
+ default:
+ rp = erts_dirty_process_signal_handler;
+ break;
+ }
if (c_p == rp) {
ERTS_BIF_PREP_RET(ret, am_dirty_execution);
return ret;
@@ -10705,7 +10721,7 @@ dispatch_system_task(Process *c_p, erts_aint_t fail_state,
ASSERT(is_immed(st->requester));
ASSERT(is_immed(target));
- ASSERT(is_immed(prio));
+ ASSERT(is_immed(st->prio));
osz = size_object(operation);
hsz = 5 /* 4-tuple */ + osz;
@@ -10713,7 +10729,7 @@ dispatch_system_task(Process *c_p, erts_aint_t fail_state,
mp = erts_alloc_message_heap(rp, &rp_locks, hsz, &hp, &ohp);
msg = copy_struct(operation, osz, &hp, ohp);
- msg = TUPLE4(hp, st->requester, target, prio, msg);
+ msg = TUPLE4(hp, st->requester, target, st->prio, msg);
erts_queue_message(rp, rp_locks, mp, msg, am_system);
@@ -10723,16 +10739,19 @@ dispatch_system_task(Process *c_p, erts_aint_t fail_state,
return ret;
}
+static Eterm
+sched_sig_sys_task(Process *c_p, void *vst, int *redsp, ErlHeapFragment **bp);
static BIF_RETTYPE
request_system_task(Process *c_p, Eterm requester, Eterm target,
- Eterm priority, Eterm operation)
+ Eterm priority_req, Eterm operation)
{
BIF_RETTYPE ret;
Process *rp = erts_proc_lookup_raw(target);
ErtsProcSysTask *st = NULL;
erts_aint32_t prio, fail_state = ERTS_PSFLG_EXITING;
- Eterm noproc_res, req_type;
+ Eterm noproc_res, req_type, priority = priority_req;
+ int signal = 0;
if (!rp && !is_internal_pid(target)) {
if (!is_external_pid(target))
@@ -10741,12 +10760,27 @@ request_system_task(Process *c_p, Eterm requester, Eterm target,
goto badarg;
}
- switch (priority) {
+ switch (priority_req) {
case am_max: prio = PRIORITY_MAX; break;
case am_high: prio = PRIORITY_HIGH; break;
case am_normal: prio = PRIORITY_NORMAL; break;
case am_low: prio = PRIORITY_LOW; break;
- default: goto badarg;
+ case am_inherit: {
+ erts_aint32_t state = erts_atomic32_read_nob(&c_p->state);
+ prio = ERTS_PSFLGS_GET_USR_PRIO(state);
+ switch (prio) {
+ case PRIORITY_MAX: priority = am_max; break;
+ case PRIORITY_HIGH: priority = am_high; break;
+ case PRIORITY_NORMAL: priority = am_normal; break;
+ case PRIORITY_LOW: priority = am_low; break;
+ default:
+ ERTS_INTERNAL_ERROR("Unexpected prio");
+ break;
+ }
+ break;
+ }
+ default:
+ goto badarg;
}
if (is_not_tuple(operation))
@@ -10792,6 +10826,7 @@ request_system_task(Process *c_p, Eterm requester, Eterm target,
hp = &st->heap[0];
st->requester = requester;
+ st->prio = priority;
st->reply_tag = req_type;
st->req_id_sz = req_id_sz;
st->req_id = req_id_sz == 0 ? req_id : copy_struct(req_id,
@@ -10807,9 +10842,13 @@ request_system_task(Process *c_p, Eterm requester, Eterm target,
ASSERT(&st->heap[0] + tot_sz == hp);
}
+ ERTS_BIF_PREP_RET(ret, am_ok);
+
switch (req_type) {
case am_garbage_collect:
+ if (c_p->common.id == requester)
+ signal = !0;
switch (st->arg[0]) {
case am_minor: st->type = ERTS_PSTT_GC_MINOR; break;
case am_major: st->type = ERTS_PSTT_GC_MAJOR; break;
@@ -10821,6 +10860,8 @@ request_system_task(Process *c_p, Eterm requester, Eterm target,
break;
case am_check_process_code:
+ if (c_p->common.id == requester)
+ signal = !0;
if (is_not_atom(st->arg[0]))
goto badarg;
noproc_res = am_false;
@@ -10847,30 +10888,60 @@ request_system_task(Process *c_p, Eterm requester, Eterm target,
break;
default:
+ if (ERTS_IS_ATOM_STR("system_task_test", req_type)) {
+ st->type = ERTS_PSTT_TEST;
+ noproc_res = am_false;
+ if (!rp)
+ goto noproc;
+ break;
+ }
goto badarg;
}
+ ASSERT(rp);
+
+ if (signal) {
+ erts_aint32_t state;
+ if (priority_req != am_inherit)
+ goto badarg;
+ state = erts_atomic32_read_acqb(&rp->state);
+ if (state & fail_state & ERTS_PSFLG_EXITING)
+ goto noproc;
+ if (state & (ERTS_PSFLG_SIG_Q | ERTS_PSFLG_SIG_IN_Q)) {
+ /*
+ * Send rpc request signal without reply,
+ * and reply from the system task...
+ */
+ Eterm res = erts_proc_sig_send_rpc_request(c_p,
+ target,
+ 0, /* no reply */
+ sched_sig_sys_task,
+ (void *) st);
+ if (is_non_value(res))
+ goto noproc;
+ return ret; /* signal sent... */
+ }
+ /*
+ * schedule system task directly since we wont violate
+ * signal order...
+ */
+ }
if (!schedule_process_sys_task(rp, prio, st, &fail_state)) {
- Eterm failure;
if (fail_state & (ERTS_PSFLG_EXITING|ERTS_PSFLG_FREE)) {
noproc:
- failure = noproc_res;
+ notify_sys_task_executed(c_p, st, noproc_res, 1);
}
else if (fail_state & (ERTS_PSFLG_DIRTY_RUNNING
| ERTS_PSFLG_DIRTY_RUNNING_SYS)) {
ret = dispatch_system_task(c_p, fail_state, st,
- target, priority, operation);
+ target, operation);
goto cleanup_return;
}
else {
ERTS_INTERNAL_ERROR("Unknown failure schedule_process_sys_task()");
- failure = am_internal_error;
}
- notify_sys_task_executed(c_p, st, failure, 1);
}
- ERTS_BIF_PREP_RET(ret, am_ok);
-
return ret;
badarg:
@@ -10887,6 +10958,64 @@ cleanup_return:
return ret;
}
+static Eterm
+sched_sig_sys_task(Process *c_p, void *vst, int *redsp, ErlHeapFragment **bp)
+{
+ ErtsProcSysTask *st = (ErtsProcSysTask *) vst;
+ erts_aint32_t prio, fail_state = ERTS_PSFLG_EXITING;
+ Eterm priority = st->prio;
+
+ switch (priority) {
+ case am_max: prio = PRIORITY_MAX; break;
+ case am_high: prio = PRIORITY_HIGH; break;
+ case am_normal: prio = PRIORITY_NORMAL; break;
+ case am_low: prio = PRIORITY_LOW; break;
+ default:
+ ERTS_INTERNAL_ERROR("Invalid prio");
+ prio = -1;
+ break;
+ }
+
+ switch (st->reply_tag) {
+ case am_garbage_collect:
+ break;
+ case am_check_process_code:
+ fail_state |= ERTS_PSFLG_DIRTY_RUNNING;
+ break;
+ default:
+ ERTS_INTERNAL_ERROR("system task not supported as signal");
+ break;
+ }
+ if (!schedule_process_sys_task(c_p, prio, st, &fail_state)) {
+ if (fail_state & (ERTS_PSFLG_EXITING|ERTS_PSFLG_FREE))
+ notify_sys_task_executed(c_p, st, am_false, 1);
+ else if (fail_state & ERTS_PSFLG_DIRTY_RUNNING) {
+ int i, arity = 2;
+ Eterm heap[1 + 2 + ERTS_MAX_PROC_SYS_TASK_ARGS];
+ heap[1] = st->reply_tag;
+ heap[2] = st->req_id;
+ for (i = 0;
+ i < ERTS_MAX_PROC_SYS_TASK_ARGS && is_value(st->arg[i]);
+ i++) {
+ arity++;
+ heap[3 + i] = st->arg[i];
+ }
+ heap[0] = make_arityval(arity);
+ (void) dispatch_system_task(c_p, fail_state, st,
+ c_p->common.id, make_tuple(&heap[0]));
+ erts_cleanup_offheap(&st->off_heap);
+ erts_free(ERTS_ALC_T_PROC_SYS_TSK, st);
+ }
+ else {
+ ERTS_INTERNAL_ERROR("Unknown failure schedule_process_sys_task()");
+ }
+ }
+
+ *redsp = 1;
+
+ return THE_NON_VALUE;
+}
+
BIF_RETTYPE
erts_internal_request_system_task_3(BIF_ALIST_3)
{
diff --git a/erts/emulator/test/code_SUITE.erl b/erts/emulator/test/code_SUITE.erl
index f4ef4a15d8..a36015381c 100644
--- a/erts/emulator/test/code_SUITE.erl
+++ b/erts/emulator/test/code_SUITE.erl
@@ -28,7 +28,9 @@
fake_literals/1,
false_dependency/1,coverage/1,fun_confusion/1,
t_copy_literals/1, t_copy_literals_frags/1,
- erl_544/1, max_heap_size/1]).
+ erl_544/1, max_heap_size/1,
+ check_process_code_signal_order/1,
+ check_process_code_dirty_exec_proc/1]).
-define(line_trace, 1).
-include_lib("common_test/include/ct.hrl").
@@ -43,7 +45,8 @@ all() ->
constant_pools, constant_refc_binaries, fake_literals,
false_dependency,
coverage, fun_confusion, t_copy_literals, t_copy_literals_frags,
- erl_544, max_heap_size].
+ erl_544, max_heap_size, check_process_code_signal_order,
+ check_process_code_dirty_exec_proc].
init_per_suite(Config) ->
erts_debug:set_internal_state(available_internal_state, true),
@@ -1040,6 +1043,49 @@ max_heap_size_proc(Mod) ->
_ -> Value
end.
+check_process_code_signal_order(Config) when is_list(Config) ->
+ process_flag(scheduler, 1),
+ process_flag(priority, high),
+ {module,versions} = erlang:load_module(versions, compile_version(1, Config)),
+ Pid = spawn_opt(versions, loop, [], [{scheduler, 1}]),
+ true = erlang:delete_module(versions),
+ true = erlang:check_process_code(Pid, versions),
+ Ref = make_ref(),
+ spam_signals(Pid, 10000),
+ %% EXIT signal *should* arrive...
+ exit(Pid, kill),
+ %% ... before CPC signal...
+ async = erlang:check_process_code(Pid, versions, [{async, Ref}]),
+ %% ... which means that the result of the check_process_code *should* be 'false'...
+ false = busy_wait_cpc_res(Ref),
+ ok.
+
+busy_wait_cpc_res(Ref) ->
+ receive
+ {check_process_code, Ref, Res} ->
+ Res
+ after 0 ->
+ busy_wait_cpc_res(Ref)
+ end.
+
+spam_signals(P, N) when N =< 0 ->
+ ok;
+spam_signals(P, N) ->
+ link(P),
+ unlink(P),
+ spam_signals(P, N-2).
+
+check_process_code_dirty_exec_proc(Config) when is_list(Config) ->
+ Pid = spawn(fun () ->
+ erts_debug:dirty_io(wait, 10000)
+ end),
+ receive after 100 -> ok end,
+ false = erlang:check_process_code(Pid, non_existing_module),
+ {status, running} = process_info(Pid, status),
+ exit(Pid, kill),
+ false = is_process_alive(Pid),
+ ok.
+
%% Utilities.
make_sub_binary(Bin) when is_binary(Bin) ->
diff --git a/erts/emulator/test/gc_SUITE.erl b/erts/emulator/test/gc_SUITE.erl
index f3942ef416..810409175e 100644
--- a/erts/emulator/test/gc_SUITE.erl
+++ b/erts/emulator/test/gc_SUITE.erl
@@ -33,7 +33,9 @@
grow_stack_heap/1,
max_heap_size/1,
minor_major_gc_option_async/1,
- minor_major_gc_option_self/1
+ minor_major_gc_option_self/1,
+ gc_signal_order/1,
+ gc_dirty_exec_proc/1
]).
suite() ->
@@ -42,7 +44,7 @@ suite() ->
all() ->
[grow_heap, grow_stack, grow_stack_heap, max_heap_size,
minor_major_gc_option_self,
- minor_major_gc_option_async].
+ minor_major_gc_option_async, gc_signal_order, gc_dirty_exec_proc].
%% Produce a growing list of elements,
@@ -248,6 +250,43 @@ minor_major_gc_option_async(_Config) ->
end
end, [gc_minor_start, gc_minor_end]).
+gc_signal_order(Config) when is_list(Config) ->
+ process_flag(scheduler, 1),
+ process_flag(priority, high),
+ Ref = make_ref(),
+ Pid = spawn_opt(fun () -> receive after infinity -> ok end end,[{scheduler, 1}]),
+ spam_signals(Pid, 10000),
+ %% EXIT signal *should* arrive...
+ exit(Pid, kill),
+ %% ... before GC signal...
+ async = garbage_collect(Pid, [{async, Ref}]),
+ %% ... which means that the result of the gc *should* be 'false'...
+ false = busy_wait_gc_res(Ref),
+ ok.
+
+busy_wait_gc_res(Ref) ->
+ receive
+ {garbage_collect, Ref, Res} ->
+ Res
+ after 0 ->
+ busy_wait_gc_res(Ref)
+ end.
+
+spam_signals(P, N) when N =< 0 ->
+ ok;
+spam_signals(P, N) ->
+ link(P),
+ unlink(P),
+ spam_signals(P, N-2).
+
+gc_dirty_exec_proc(Config) when is_list(Config) ->
+ check_gc_tracing_around(
+ fun(Pid, _Ref) ->
+ Pid ! {dirty_exec, 1000},
+ receive after 100 -> ok end,
+ true = erlang:garbage_collect(Pid, [{type, major}])
+ end, [gc_major_start, gc_major_end]).
+
%% Traces garbage collection around the given operation, and fails the test if
%% it results in any unexpected messages or if the expected trace tags are not
%% received.
@@ -257,7 +296,9 @@ check_gc_tracing_around(Fun, ExpectedTraceTags) ->
fun Endless() ->
receive
{gc, Ref, Type} ->
- erlang:garbage_collect(self(), [{type, Type}])
+ erlang:garbage_collect(self(), [{type, Type}]);
+ {dirty_exec, Time} ->
+ erts_debug:dirty_io(wait, 1000)
after 100 ->
ok
end,
diff --git a/erts/emulator/test/process_SUITE.erl b/erts/emulator/test/process_SUITE.erl
index 58a4dad8e0..aee64c2adb 100644
--- a/erts/emulator/test/process_SUITE.erl
+++ b/erts/emulator/test/process_SUITE.erl
@@ -2557,6 +2557,8 @@ do_otp_7738_test(Type) ->
gor(Reds, Stop) ->
receive
+ drop_me ->
+ gor(Reds+1, Stop);
{From, reds} ->
From ! {reds, Reds, self()},
gor(Reds+1, Stop);
@@ -2569,7 +2571,11 @@ gor(Reds, Stop) ->
garb_other_running(Config) when is_list(Config) ->
Stop = make_ref(),
{Pid, Mon} = spawn_monitor(fun () -> gor(0, Stop) end),
- Reds = lists:foldl(fun (_, OldReds) ->
+ Reds = lists:foldl(fun (N, OldReds) ->
+ case N rem 2 of
+ 0 -> Pid ! drop_me;
+ _ -> ok
+ end,
erlang:garbage_collect(Pid),
receive after 1 -> ok end,
Pid ! {self(), reds},
@@ -2644,18 +2650,18 @@ no_priority_inversion2(Config) when is_list(Config) ->
tok_loop()
end,
[{priority, low}, monitor, link]),
- RL = request_gc(PL, low),
- RN = request_gc(PL, normal),
- RH = request_gc(PL, high),
+ RL = request_test(PL, low),
+ RN = request_test(PL, normal),
+ RH = request_test(PL, high),
receive
- {garbage_collect, _, _} ->
- ct:fail(unexpected_gc)
+ {system_task_test, _, _} ->
+ ct:fail(unexpected_system_task_completed)
after 1000 ->
ok
end,
- RM = request_gc(PL, max),
+ RM = request_test(PL, max),
receive
- {garbage_collect, RM, true} ->
+ {system_task_test, RM, true} ->
ok
end,
lists:foreach(fun ({P, _}) ->
@@ -2669,15 +2675,15 @@ no_priority_inversion2(Config) when is_list(Config) ->
end
end, MTLs),
receive
- {garbage_collect, RH, true} ->
+ {system_task_test, RH, true} ->
ok
end,
receive
- {garbage_collect, RN, true} ->
+ {system_task_test, RN, true} ->
ok
end,
receive
- {garbage_collect, RL, true} ->
+ {system_task_test, RL, true} ->
ok
end,
unlink(PL),
@@ -2689,18 +2695,18 @@ no_priority_inversion2(Config) when is_list(Config) ->
process_flag(priority, Prio),
ok.
-request_gc(Pid, Prio) ->
+request_test(Pid, Prio) ->
Ref = make_ref(),
- erts_internal:request_system_task(Pid, Prio, {garbage_collect, Ref, major}),
+ erts_internal:request_system_task(Pid, Prio, {system_task_test, Ref}),
Ref.
system_task_blast(Config) when is_list(Config) ->
Me = self(),
GCReq = fun () ->
- RL = gc_req(Me, 100),
+ RL = test_req(Me, 100),
lists:foreach(fun (R) ->
receive
- {garbage_collect, R, true} ->
+ {system_task_test, R, true} ->
ok
end
end, RL),
@@ -2715,14 +2721,14 @@ system_task_blast(Config) when is_list(Config) ->
end, HTLs),
ok.
-gc_req(_Pid, 0) ->
+test_req(_Pid, 0) ->
[];
-gc_req(Pid, N) ->
- R0 = request_gc(Pid, low),
- R1 = request_gc(Pid, normal),
- R2 = request_gc(Pid, high),
- R3 = request_gc(Pid, max),
- [R0, R1, R2, R3 | gc_req(Pid, N-1)].
+test_req(Pid, N) ->
+ R0 = request_test(Pid, low),
+ R1 = request_test(Pid, normal),
+ R2 = request_test(Pid, high),
+ R3 = request_test(Pid, max),
+ [R0, R1, R2, R3 | test_req(Pid, N-1)].
system_task_on_suspended(Config) when is_list(Config) ->
{P, M} = spawn_monitor(fun () ->
@@ -2887,17 +2893,16 @@ otp_16642(Config) when is_list(Config) ->
erts_internal:request_system_task(
Pid,
Prio,
- {check_process_code,
- {Prio, N},
- '__non_existing_module__'})
+ {system_task_test,
+ {Prio, N}})
end,
lists:seq(Start, Stop))
end,
MkResList = fun (Prio, Start, Stop) ->
lists:map(fun (N) ->
- {check_process_code,
+ {system_task_test,
{Prio, N},
- false}
+ true}
end,
lists:seq(Start, Stop))
end,
diff --git a/erts/preloaded/ebin/erlang.beam b/erts/preloaded/ebin/erlang.beam
index ee96878ff7..563eb8744a 100644
--- a/erts/preloaded/ebin/erlang.beam
+++ b/erts/preloaded/ebin/erlang.beam
Binary files differ
diff --git a/erts/preloaded/ebin/erts_internal.beam b/erts/preloaded/ebin/erts_internal.beam
index f8256ee801..38cf2378ab 100644
--- a/erts/preloaded/ebin/erts_internal.beam
+++ b/erts/preloaded/ebin/erts_internal.beam
Binary files differ
diff --git a/erts/preloaded/src/erlang.erl b/erts/preloaded/src/erlang.erl
index 5730e999cb..4bb3b84223 100644
--- a/erts/preloaded/src/erlang.erl
+++ b/erts/preloaded/src/erlang.erl
@@ -931,21 +931,17 @@ garbage_collect(Pid, OptionList) ->
GcOpts = get_gc_opts(OptionList, #gcopt{}),
case GcOpts#gcopt.async of
{async, ReqId} ->
- {priority, Prio} = erlang:process_info(erlang:self(),
- priority),
erts_internal:request_system_task(
- Pid, Prio, {garbage_collect, ReqId, GcOpts#gcopt.type}),
+ Pid, inherit, {garbage_collect, ReqId, GcOpts#gcopt.type}),
async;
sync ->
case Pid == erlang:self() of
true ->
erts_internal:garbage_collect(GcOpts#gcopt.type);
false ->
- {priority, Prio} = erlang:process_info(erlang:self(),
- priority),
ReqId = erlang:make_ref(),
erts_internal:request_system_task(
- Pid, Prio,
+ Pid, inherit,
{garbage_collect, ReqId, GcOpts#gcopt.type}),
receive
{garbage_collect, ReqId, GCResult} ->
diff --git a/erts/preloaded/src/erts_internal.erl b/erts/preloaded/src/erts_internal.erl
index f9f1eb95e5..482fb5c907 100644
--- a/erts/preloaded/src/erts_internal.erl
+++ b/erts/preloaded/src/erts_internal.erl
@@ -242,7 +242,7 @@ port_info(_Result, _Item) ->
erlang:nif_error(undefined).
-spec request_system_task(Pid, Prio, Request) -> 'ok' when
- Prio :: 'max' | 'high' | 'normal' | 'low',
+ Prio :: 'max' | 'high' | 'normal' | 'low' | 'inherit',
Type :: 'major' | 'minor',
Request :: {'garbage_collect', term(), Type}
| {'check_process_code', term(), module()}
@@ -284,10 +284,8 @@ check_process_code(Pid, Module, OptionList) ->
Async = get_cpc_opts(OptionList, sync),
case Async of
{async, ReqId} ->
- {priority, Prio} = erlang:process_info(erlang:self(),
- priority),
erts_internal:request_system_task(Pid,
- Prio,
+ inherit,
{check_process_code,
ReqId,
Module}),
@@ -297,11 +295,9 @@ check_process_code(Pid, Module, OptionList) ->
true ->
erts_internal:check_process_code(Module);
false ->
- {priority, Prio} = erlang:process_info(erlang:self(),
- priority),
ReqId = erlang:make_ref(),
erts_internal:request_system_task(Pid,
- Prio,
+ inherit,
{check_process_code,
ReqId,
Module}),