summaryrefslogtreecommitdiff
path: root/erts/emulator/sys/common/erl_poll.c
diff options
context:
space:
mode:
authorRickard Green <rickard@erlang.org>2021-11-02 23:30:27 +0100
committerRickard Green <rickard@erlang.org>2021-11-03 15:04:54 +0100
commit98dec6cf320edb46a58fcc64eda4f644e75be755 (patch)
tree010f9d9bc6e95e47fef0b6ee3403242aee4d65a0 /erts/emulator/sys/common/erl_poll.c
parent6d5a5f31c36bbdaad21585d25974177bd1b75e66 (diff)
downloaderlang-98dec6cf320edb46a58fcc64eda4f644e75be755.tar.gz
Limit timeout value in calls to select()
We previously did not limit the timeout value when calling select() which could cause select() to fail when passed a huge timeout value causing a runtime system crash. We currently only use select() on Darwin which accepts a timeout value of up to 100 million seconds. However, according to posix, select() implementations are only required to provide 31 days as max timeout value. We therefore limit the timeout value to 31 days.
Diffstat (limited to 'erts/emulator/sys/common/erl_poll.c')
-rw-r--r--erts/emulator/sys/common/erl_poll.c17
1 files changed, 17 insertions, 0 deletions
diff --git a/erts/emulator/sys/common/erl_poll.c b/erts/emulator/sys/common/erl_poll.c
index e669572499..a2a39de5ac 100644
--- a/erts/emulator/sys/common/erl_poll.c
+++ b/erts/emulator/sys/common/erl_poll.c
@@ -71,6 +71,12 @@
# define _DARWIN_UNLIMITED_SELECT
#endif
+/*
+ * According to posix, select() implementations should
+ * support a max timeout value of at least 31 days.
+ */
+#define ERTS_SELECT_MAX_TV_SEC__ (31*24*60*60-1)
+
#ifndef WANT_NONBLOCKING
# define WANT_NONBLOCKING
#endif
@@ -1735,6 +1741,17 @@ get_timeout_timeval(ErtsPollSet *ps,
}
else {
ErtsMonotonicTime sec = timeout/(1000*1000);
+ if (sec >= ERTS_SELECT_MAX_TV_SEC__) {
+ tvp->tv_sec = ERTS_SELECT_MAX_TV_SEC__;
+ tvp->tv_usec = 0;
+ /*
+ * If we actually should time out on
+ * this (huge) timeout, the select() call
+ * will be restarted with a newly calculated
+ * timeout after verifying the timeout...
+ */
+ return 1;
+ }
tvp->tv_sec = sec;
tvp->tv_usec = timeout - sec*(1000*1000);