summaryrefslogtreecommitdiff
path: root/erts
diff options
context:
space:
mode:
authorMaxim Fedorov <maximfca@gmail.com>2020-07-28 21:50:30 -0700
committerLukas Larsson <lukas@erlang.org>2020-08-11 11:16:02 +0200
commitd1326e4ae0320da53ea8b8b4e1d22b179ed3b113 (patch)
treebbd3580d78e1d2116ba7399f861f99033a9ce3df /erts
parent7fe7fa3dde556b5b92522f8279d465bb52baf1f6 (diff)
downloaderlang-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.c4
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) {