]> git.lizzy.rs Git - rust.git/commitdiff
Check conversion from Duration to timespec in futex_wait.
authorMara Bos <m-ou.se@m-ou.se>
Sat, 19 Sep 2020 22:17:05 +0000 (00:17 +0200)
committerMara Bos <m-ou.se@m-ou.se>
Sun, 27 Sep 2020 09:56:43 +0000 (11:56 +0200)
library/std/src/sys/unix/futex.rs

index 6af06aa5f7ee475067826e0e2cfc638fa710e090..e6f0c48c59b1b354db0ba6aa0b68ffc23e861810 100644 (file)
@@ -1,27 +1,26 @@
 #![cfg(any(target_os = "linux", target_os = "android"))]
 
+use crate::convert::TryInto;
+use crate::ptr::null;
 use crate::sync::atomic::AtomicI32;
 use crate::time::Duration;
 
 pub fn futex_wait(futex: &AtomicI32, expected: i32, timeout: Option<Duration>) {
-    let timespec;
-    let timespec_ptr = match timeout {
-        Some(timeout) => {
-            timespec = libc::timespec {
-                tv_sec: timeout.as_secs() as _,
-                tv_nsec: timeout.subsec_nanos() as _,
-            };
-            &timespec as *const libc::timespec
-        }
-        None => crate::ptr::null(),
-    };
+    let timespec = timeout.and_then(|d| {
+        Some(libc::timespec {
+            // Sleep forever if the timeout is longer than fits in a timespec.
+            tv_sec: d.as_secs().try_into().ok()?,
+            // This conversion never truncates, as subsec_nanos is always <1e9.
+            tv_nsec: d.subsec_nanos() as _,
+        })
+    });
     unsafe {
         libc::syscall(
             libc::SYS_futex,
             futex as *const AtomicI32,
             libc::FUTEX_WAIT | libc::FUTEX_PRIVATE_FLAG,
             expected,
-            timespec_ptr,
+            timespec.as_ref().map_or(null(), |d| d as *const libc::timespec),
         );
     }
 }