diff options
author | Maxim Fedorov <maximfca@gmail.com> | 2020-07-28 21:50:30 -0700 |
---|---|---|
committer | Lukas Larsson <lukas@erlang.org> | 2020-08-11 11:16:02 +0200 |
commit | d1326e4ae0320da53ea8b8b4e1d22b179ed3b113 (patch) | |
tree | bbd3580d78e1d2116ba7399f861f99033a9ce3df /erts | |
parent | 7fe7fa3dde556b5b92522f8279d465bb52baf1f6 (diff) | |
download | erlang-d1326e4ae0320da53ea8b8b4e1d22b179ed3b113.tar.gz |
erl_check_io: do not discard ERTS_POLL_EV_IN from active_events
This commit fixes a race condition, which can be reproduced
with running a large amount of bidirectional TCP streams.
When the system is fully loaded, it is possible that socket migrated
to scheduler pollset still fires EPOLLIN event. In this case
active_events field of ErtsDrvEventState structure will desynchronise
from the actual state (with EPOLLIN requested via scheduler pollset).
This, in turn, leads to all ERTS_POLL_EV_IN events disregarded. All
reads from the socket will be stopped.
This can only happen for {active, N} mode of a TCP socket, where
fd migrates back and forth to/from scheduler pollset.
Diffstat (limited to 'erts')
-rw-r--r-- | erts/emulator/sys/common/erl_check_io.c | 4 |
1 files changed, 3 insertions, 1 deletions
diff --git a/erts/emulator/sys/common/erl_check_io.c b/erts/emulator/sys/common/erl_check_io.c index c77a535105..2e13b0daff 100644 --- a/erts/emulator/sys/common/erl_check_io.c +++ b/erts/emulator/sys/common/erl_check_io.c @@ -1706,8 +1706,10 @@ erts_check_io(ErtsPollThread *psi, ErtsMonotonicTime timeout_time) reactive_events = state->active_events; - if (state->flags & ERTS_EV_FLAG_IN_SCHEDULER) + if (state->flags & ERTS_EV_FLAG_IN_SCHEDULER) { reactive_events &= ~ERTS_POLL_EV_IN; + state->active_events |= ERTS_POLL_EV_IN; + } /* Reactivate the poll op if there are still active events */ if (reactive_events) { |