diff options
author | Maxim Fedorov <[email protected]> | 2018-08-28 16:11:09 -0700 |
---|---|---|
committer | Maxim Fedorov <[email protected]> | 2018-09-04 14:44:54 -0700 |
commit | d4057c1c1ea711aaa8a39591bf38920f93530f5c (patch) | |
tree | 3675fdf93a9359e606e32b69a4013e53e968ab13 /erts | |
parent | e3e013e4d8287c6dc8ca3992bd4559744e75f8d2 (diff) | |
download | otp-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.
Diffstat (limited to 'erts')
-rw-r--r-- | erts/emulator/beam/erl_process.c | 2 |
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; /* |