diff options
author | Rickard Green <rickard@erlang.org> | 2021-09-13 11:52:33 +0200 |
---|---|---|
committer | Rickard Green <rickard@erlang.org> | 2021-09-13 11:52:33 +0200 |
commit | 521b36bc96c3231bff72368ff06c09955eb45a5f (patch) | |
tree | 9a260a2f86cdeaf99ff6141d2302f52b53a79f5a | |
parent | 483f1b680e27874421c6eab759b7e359face914d (diff) | |
parent | 23149c55ed29cd00c260b21c1c74adc33e1b6918 (diff) | |
download | erlang-521b36bc96c3231bff72368ff06c09955eb45a5f.tar.gz |
Merge branch 'rickard/pi-status/OTP-17628' into maint
* rickard/pi-status/OTP-17628:
Fix process_info(_, status) from other process with other prio
-rw-r--r-- | erts/emulator/beam/erl_bif_info.c | 23 | ||||
-rw-r--r-- | erts/emulator/beam/erl_process.c | 52 | ||||
-rw-r--r-- | erts/emulator/beam/erl_process.h | 1 | ||||
-rw-r--r-- | erts/emulator/test/process_SUITE.erl | 22 |
4 files changed, 87 insertions, 11 deletions
diff --git a/erts/emulator/beam/erl_bif_info.c b/erts/emulator/beam/erl_bif_info.c index cb1af1f008..8466f88fd5 100644 --- a/erts/emulator/beam/erl_bif_info.c +++ b/erts/emulator/beam/erl_bif_info.c @@ -1436,17 +1436,22 @@ process_info_aux(Process *c_p, if (res == am_running && (state & ERTS_PSFLG_RUNNING_SYS)) { ASSERT(c_p == rp); ASSERT(flags & ERTS_PI_FLAG_REQUEST_FOR_OTHER); - if (!(state & (ERTS_PSFLG_SYS_TASKS - | ERTS_PSFLG_ACTIVE + if (!(state & (ERTS_PSFLG_ACTIVE | ERTS_PSFLG_SIG_Q | ERTS_PSFLG_SIG_IN_Q))) { - /* - * We are servicing a process-info request from - * another process. If that other process could - * have inspected our state itself, we would have - * been in the 'waiting' state. - */ - res = am_waiting; + int sys_tasks = 0; + if (state & ERTS_PSFLG_SYS_TASKS) + sys_tasks = erts_have_non_prio_elev_sys_tasks(rp, + rp_locks); + if (!sys_tasks) { + /* + * We are servicing a process-info request from + * another process. If that other process could + * have inspected our state itself, we would have + * been in the 'waiting' state. + */ + res = am_waiting; + } } } break; diff --git a/erts/emulator/beam/erl_process.c b/erts/emulator/beam/erl_process.c index 61f3c6b088..eacbb90770 100644 --- a/erts/emulator/beam/erl_process.c +++ b/erts/emulator/beam/erl_process.c @@ -6945,6 +6945,58 @@ erts_proc_sys_schedule(Process *p, erts_aint32_t state, erts_aint32_t enable_fla return active_sys_enqueue(p, NULL, 0, enable_flag, state, &fail_state); } +int +erts_have_non_prio_elev_sys_tasks(Process *c_p, ErtsProcLocks locks) +{ + ErtsProcSysTaskQs *qs; + int res = 0; + + if (!(locks & ERTS_PROC_LOCK_STATUS)) + erts_proc_lock(c_p, ERTS_PROC_LOCK_STATUS); + + qs = c_p->sys_task_qs; + if (qs) { + int qmask = qs->qmask; + ASSERT(qmask); + while (qmask) { + ErtsProcSysTask *st, *first_st; + switch (qmask & -qmask) { + case MAX_BIT: + qmask &= ~MAX_BIT; + st = first_st = qs->q[PRIORITY_MAX]; + break; + case HIGH_BIT: + qmask &= ~HIGH_BIT; + st = first_st = qs->q[PRIORITY_HIGH]; + break; + case NORMAL_BIT: + case LOW_BIT: + st = first_st = qs->q[PRIORITY_NORMAL]; + qmask &= ~(NORMAL_BIT|LOW_BIT); + break; + default: + st = first_st = NULL; + break; + } + ASSERT(st); + do { + if (st->type != ERTS_PSTT_PRIO_SIG) { + res = !0; + goto done; + } + st = st->next; + } while (st != first_st); + } + } + +done: + + if (!(locks & ERTS_PROC_LOCK_STATUS)) + erts_proc_unlock(c_p, ERTS_PROC_LOCK_STATUS); + + return res; +} + static int schedule_process_sys_task(Process *p, erts_aint32_t prio, ErtsProcSysTask *st, erts_aint32_t *fail_state_p) diff --git a/erts/emulator/beam/erl_process.h b/erts/emulator/beam/erl_process.h index 4777d9d1ce..6fa91a5049 100644 --- a/erts/emulator/beam/erl_process.h +++ b/erts/emulator/beam/erl_process.h @@ -2059,6 +2059,7 @@ ErtsSchedulerData *erts_get_scheduler_data(void); void erts_schedule_process(Process *, erts_aint32_t, ErtsProcLocks); erts_aint32_t erts_proc_sys_schedule(Process *p, erts_aint32_t state, erts_aint32_t enable_flag); +int erts_have_non_prio_elev_sys_tasks(Process *c_p, ErtsProcLocks locks); ERTS_GLB_INLINE void erts_proc_notify_new_message(Process *p, ErtsProcLocks locks); ERTS_GLB_INLINE void erts_schedule_dirty_sys_execution(Process *c_p); diff --git a/erts/emulator/test/process_SUITE.erl b/erts/emulator/test/process_SUITE.erl index d45d608309..d484eb8e42 100644 --- a/erts/emulator/test/process_SUITE.erl +++ b/erts/emulator/test/process_SUITE.erl @@ -38,6 +38,7 @@ exit_and_timeout/1, exit_twice/1, t_process_info/1, process_info_other/1, process_info_other_msg/1, process_info_other_dist_msg/1, + process_info_other_status/1, process_info_2_list/1, process_info_lock_reschedule/1, process_info_lock_reschedule2/1, process_info_lock_reschedule3/1, @@ -97,7 +98,8 @@ all() -> [spawn_with_binaries, t_exit_1, {group, t_exit_2}, trap_exit_badarg, trap_exit_badarg_in_bif, t_process_info, process_info_other, process_info_other_msg, - process_info_other_dist_msg, process_info_2_list, + process_info_other_dist_msg, process_info_other_status, + process_info_2_list, process_info_lock_reschedule, process_info_lock_reschedule2, process_info_lock_reschedule3, @@ -696,7 +698,23 @@ process_info_other_dist_msg(Config) when is_list(Config) -> Pid ! stop, stop_node(Node), ok. - + +process_info_other_status(Config) when is_list(Config) -> + %% OTP-17628: status was erroneously reported as 'running', + %% when it should be 'waiting', when the priority of the + %% caller exceeded the priority of the processes being + %% checked (due to prio elevation). + Self = self(), + Other = spawn_link(fun () -> other_process(Self) end), + receive {go_ahead, Other} -> ok end, + receive after 100 -> ok end, + {status, waiting} = process_info(Other, status), + process_flag(priority, high), + {status, waiting} = process_info(Other, status), + process_flag(priority, max), + {status, waiting} = process_info(Other, status), + Other ! stop, + ok. other_process(Parent) -> self() ! {my,own,message}, |