aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMaxim Fedorov <[email protected]>2018-08-28 16:11:09 -0700
committerMaxim Fedorov <[email protected]>2018-09-04 14:44:54 -0700
commitd4057c1c1ea711aaa8a39591bf38920f93530f5c (patch)
tree3675fdf93a9359e606e32b69a4013e53e968ab13
parente3e013e4d8287c6dc8ca3992bd4559744e75f8d2 (diff)
downloadotp-d4057c1c1ea711aaa8a39591bf38920f93530f5c.tar.gz
otp-d4057c1c1ea711aaa8a39591bf38920f93530f5c.tar.bz2
otp-d4057c1c1ea711aaa8a39591bf38920f93530f5c.zip
Fix an endless rescheduling loop when a process is executing process_info(self(), ...)
It is possible that a process has to yield before completing process_info BIF when it runs out of reductions. If this BIF is called by the process itself, it does not send a signal but executes in the context of a process. If it has to yield, it turns F_LOCAL_SIGS_ONLY flag on, which means new signals won't be fetched from the outer message queue. When the same process needs to execute dirty system code (e.g. dirty GC) it has to be run on a dirty scheduler. However signals enqueued into outer queue cause it to be rescheduled on a normal scheduler. F_LOCAL_SIGS_ONLY prevent outer queue signals delivery, creating an endless rescheduling loop. This commit disengages F_LOCAL_SIG_ONLY if process needs to execute dirty code in order to complete signal delivery and allow process to be moved to dirty run queue.
-rw-r--r--erts/emulator/beam/erl_process.c2
1 files changed, 1 insertions, 1 deletions
diff --git a/erts/emulator/beam/erl_process.c b/erts/emulator/beam/erl_process.c
index 9f3dfd6c37..0f7f1598fd 100644
--- a/erts/emulator/beam/erl_process.c
+++ b/erts/emulator/beam/erl_process.c
@@ -9641,7 +9641,7 @@ Process *erts_schedule(ErtsSchedulerData *esdp, Process *p, int calls)
if (state & ERTS_PSFLG_RUNNING_SYS) {
if (state & (ERTS_PSFLG_SIG_Q|ERTS_PSFLG_SIG_IN_Q)) {
int local_only = (!!(p->flags & F_LOCAL_SIGS_ONLY)
- & !(state & ERTS_PSFLG_SUSPENDED));
+ & !(state & (ERTS_PSFLG_SUSPENDED|ERTS_PSFLGS_DIRTY_WORK)));
if (!local_only | !!(state & ERTS_PSFLG_SIG_Q)) {
int sig_reds;
/*