diff options
-rw-r--r-- | erts/emulator/beam/atom.names | 3 | ||||
-rw-r--r-- | erts/emulator/beam/bif.c | 47 | ||||
-rw-r--r-- | erts/emulator/beam/bif.h | 9 | ||||
-rw-r--r-- | erts/emulator/beam/erl_bif_info.c | 10 | ||||
-rw-r--r-- | erts/emulator/beam/erl_bif_port.c | 391 | ||||
-rw-r--r-- | erts/emulator/beam/erl_proc_sig_queue.c | 7 | ||||
-rw-r--r-- | erts/emulator/beam/erl_proc_sig_queue.h | 10 | ||||
-rw-r--r-- | erts/emulator/beam/erl_process.c | 161 | ||||
-rw-r--r-- | erts/emulator/test/code_SUITE.erl | 50 | ||||
-rw-r--r-- | erts/emulator/test/gc_SUITE.erl | 47 | ||||
-rw-r--r-- | erts/emulator/test/process_SUITE.erl | 59 | ||||
-rw-r--r-- | erts/preloaded/ebin/erlang.beam | bin | 108992 -> 108792 bytes | |||
-rw-r--r-- | erts/preloaded/ebin/erts_internal.beam | bin | 22896 -> 22728 bytes | |||
-rw-r--r-- | erts/preloaded/src/erlang.erl | 8 | ||||
-rw-r--r-- | erts/preloaded/src/erts_internal.erl | 10 |
15 files changed, 583 insertions, 229 deletions
diff --git a/erts/emulator/beam/atom.names b/erts/emulator/beam/atom.names index 31acd46260..65f78f5541 100644 --- a/erts/emulator/beam/atom.names +++ b/erts/emulator/beam/atom.names @@ -121,6 +121,7 @@ atom badopt atom bag atom band atom big +atom bif_handle_signals_return atom bif_return_trap atom binary atom binary_copy_trap @@ -287,6 +288,7 @@ atom free atom fullsweep_after atom functions atom function_clause +atom garbage_collect atom garbage_collecting atom garbage_collection atom garbage_collection_info @@ -340,6 +342,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 4e71600fa8..eefb722c56 100644 --- a/erts/emulator/beam/bif.c +++ b/erts/emulator/beam/bif.c @@ -5089,7 +5089,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->sig_qs.flags & FS_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->sig_qs.flags &= ~FS_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->sig_qs.flags |= FS_LOCAL_SIGS_ONLY; + ERTS_BIF_YIELD1(&erts_bif_handle_signals_return_export, + BIF_P, BIF_ARG_1); + } + + BIF_P->sig_qs.flags &= ~FS_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)) @@ -5133,6 +5176,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 1086fdd057..41c0fb82fa 100644 --- a/erts/emulator/beam/erl_bif_info.c +++ b/erts/emulator/beam/erl_bif_info.c @@ -1254,7 +1254,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: @@ -3691,7 +3694,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 604fc25b6e..0c32b99fc1 100644 --- a/erts/emulator/beam/erl_bif_port.c +++ b/erts/emulator/beam/erl_bif_port.c @@ -164,7 +164,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; @@ -185,51 +185,61 @@ 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_trap_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_trap_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)); + /* Signal order preserved by reply... */ + BIF_RET(ref); + break; + 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; } @@ -239,41 +249,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); } @@ -283,41 +298,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); } @@ -328,30 +347,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); } /* @@ -360,32 +393,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) @@ -396,33 +439,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); } @@ -434,33 +488,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 7d4820f1db..ad5610d817 100644 --- a/erts/emulator/beam/erl_proc_sig_queue.c +++ b/erts/emulator/beam/erl_proc_sig_queue.c @@ -1778,7 +1778,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; @@ -1812,13 +1812,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 bbff433711..0b21751e04 100644 --- a/erts/emulator/beam/erl_proc_sig_queue.h +++ b/erts/emulator/beam/erl_proc_sig_queue.h @@ -188,6 +188,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... */ @@ -664,8 +668,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 55d0690d0d..65a6e1c6ad 100644 --- a/erts/emulator/beam/erl_process.c +++ b/erts/emulator/beam/erl_process.c @@ -449,7 +449,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 @@ -458,6 +459,7 @@ struct ErtsProcSysTask_ { ErtsProcSysTask *next; ErtsProcSysTask *prev; ErtsProcSysTaskType type; + Eterm prio; Eterm requester; Eterm reply_tag; Eterm req_id; @@ -10457,6 +10459,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; @@ -10514,6 +10519,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: @@ -10683,7 +10689,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; @@ -10695,8 +10701,18 @@ 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); + 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; @@ -10716,7 +10732,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; @@ -10724,7 +10740,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); @@ -10734,16 +10750,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)) @@ -10752,12 +10771,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)) @@ -10803,6 +10837,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, @@ -10818,9 +10853,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; @@ -10832,6 +10871,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; @@ -10861,29 +10902,59 @@ 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) { 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: @@ -10900,6 +10971,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 5fbb5d5a9c..4fd554d982 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), @@ -1050,6 +1053,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 5619807791..cef80b34ce 100644 --- a/erts/emulator/test/process_SUITE.erl +++ b/erts/emulator/test/process_SUITE.erl @@ -3558,6 +3558,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); @@ -3570,7 +3572,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}, @@ -3645,18 +3651,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, _}) -> @@ -3670,15 +3676,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), @@ -3690,18 +3696,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), @@ -3716,14 +3722,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 () -> @@ -3888,17 +3894,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 Binary files differindex 61e841b703..927d9841e9 100644 --- a/erts/preloaded/ebin/erlang.beam +++ b/erts/preloaded/ebin/erlang.beam diff --git a/erts/preloaded/ebin/erts_internal.beam b/erts/preloaded/ebin/erts_internal.beam Binary files differindex f7650c1564..a76d3a0220 100644 --- a/erts/preloaded/ebin/erts_internal.beam +++ b/erts/preloaded/ebin/erts_internal.beam diff --git a/erts/preloaded/src/erlang.erl b/erts/preloaded/src/erlang.erl index c8c3b36c8d..d9ba8328dd 100644 --- a/erts/preloaded/src/erlang.erl +++ b/erts/preloaded/src/erlang.erl @@ -980,21 +980,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 aa3b6b753c..908e6e5e5c 100644 --- a/erts/preloaded/src/erts_internal.erl +++ b/erts/preloaded/src/erts_internal.erl @@ -252,7 +252,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()} @@ -294,10 +294,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}), @@ -307,11 +305,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}), |