diff --git a/src/sys/unix/selector/epoll.rs b/src/sys/unix/selector/epoll.rs index 4728717e5..74770f161 100644 --- a/src/sys/unix/selector/epoll.rs +++ b/src/sys/unix/selector/epoll.rs @@ -46,8 +46,16 @@ impl Selector { } pub fn select(&self, events: &mut Events, timeout: Option) -> io::Result<()> { + // A bug in kernels < 2.6.37 makes timeouts larger than LONG_MAX / CONFIG_HZ + // (approx. 30 minutes with CONFIG_HZ=1200) effectively infinite on 32 bits + // architectures. The magic number is the same constant used by libuv. + #[cfg(target_pointer_width = "32")] + const MAX_SAFE_TIMEOUT: u128 = 1789569; + #[cfg(not(target_pointer_width = "32"))] + const MAX_SAFE_TIMEOUT: u128 = libc::c_int::max_value() as u128; + let timeout = timeout - .map(|to| cmp::min(to.as_millis(), libc::c_int::max_value() as u128) as libc::c_int) + .map(|to| cmp::min(to.as_millis(), MAX_SAFE_TIMEOUT) as libc::c_int) .unwrap_or(-1); events.clear();