aboutsummaryrefslogtreecommitdiffstats
path: root/erts
diff options
context:
space:
mode:
authorMaxim Fedorov <[email protected]>2018-08-28 16:11:09 -0700
committerMaxim Fedorov <[email protected]>2018-08-31 09:37:04 -0700
commit93ad08d8c6d6a9875a10b33633aca52de5d3c59b (patch)
tree54ed7bd942fa07dc3d1de3b9d88b89f63b6264cf /erts
parentf7012b7a731924193cf05fc77b103e89bd0fcbfb (diff)
downloadotp-93ad08d8c6d6a9875a10b33633aca52de5d3c59b.tar.gz
otp-93ad08d8c6d6a9875a10b33633aca52de5d3c59b.tar.bz2
otp-93ad08d8c6d6a9875a10b33633aca52de5d3c59b.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.
Diffstat (limited to 'erts')
-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 7a9ef3c1de..d5bd17ff3e 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;
/*