diff options
author | Wesley Wiser <wesleywiser@microsoft.com> | 2022-11-28 13:14:06 -0500 |
---|---|---|
committer | Wesley Wiser <wesleywiser@microsoft.com> | 2022-11-28 14:31:36 -0500 |
commit | 006fc6f7975b3a6b64329847b780622aab392109 (patch) | |
tree | 156cdf7be0cfc62a499fc29c600b4e5360ee9074 /src/sys | |
parent | 33a4d495d99590d17ce4ced675bb6bf4a11d9251 (diff) | |
download | nix-006fc6f7975b3a6b64329847b780622aab392109.zip |
Update use of libc::timespec to prepare for future libc version
In a future release of the `libc` crate, `libc::timespec` will contain
private padding fields on `*-linux-musl` targets and so the struct will
no longer be able to be created using the literal initialization syntax.
Update places where `libc::timespec` is created to first zero initialize
the value and then update the `tv_sec` and `tv_nsec` fields manually.
Many of these places are in `const fn`s so a helper function
`zero_init_timespec()` is introduced to help with this as
`std::mem::MaybeUninit::zeroed()` is not a `const` function.
Some matches on `libc::timespec` are also updated to include a trailing
`..` pattern which works when `libc::timespec` has additional, private
fields as well as when it does not (like for
`x86_64-unknown-linux-gnu`).
Diffstat (limited to 'src/sys')
-rw-r--r-- | src/sys/time.rs | 68 |
1 files changed, 33 insertions, 35 deletions
diff --git a/src/sys/time.rs b/src/sys/time.rs index a7240849..0042c450 100644 --- a/src/sys/time.rs +++ b/src/sys/time.rs @@ -6,6 +6,13 @@ use std::convert::From; use std::time::Duration; use std::{cmp, fmt, ops}; +const fn zero_init_timespec() -> timespec { + // `std::mem::MaybeUninit::zeroed()` is not yet a const fn + // (https://github.com/rust-lang/rust/issues/91850) so we will instead initialize an array of + // the appropriate size to zero and then transmute it to a timespec value. + unsafe { std::mem::transmute([0u8; std::mem::size_of::<timespec>()]) } +} + #[cfg(any( all(feature = "time", any(target_os = "android", target_os = "linux")), all( @@ -20,7 +27,7 @@ use std::{cmp, fmt, ops}; ) ))] pub(crate) mod timer { - use crate::sys::time::TimeSpec; + use crate::sys::time::{zero_init_timespec, TimeSpec}; use bitflags::bitflags; #[derive(Debug, Clone, Copy)] @@ -29,14 +36,8 @@ pub(crate) mod timer { impl TimerSpec { pub const fn none() -> Self { Self(libc::itimerspec { - it_interval: libc::timespec { - tv_sec: 0, - tv_nsec: 0, - }, - it_value: libc::timespec { - tv_sec: 0, - tv_nsec: 0, - }, + it_interval: zero_init_timespec(), + it_value: zero_init_timespec(), }) } } @@ -57,10 +58,7 @@ pub(crate) mod timer { fn from(expiration: Expiration) -> TimerSpec { match expiration { Expiration::OneShot(t) => TimerSpec(libc::itimerspec { - it_interval: libc::timespec { - tv_sec: 0, - tv_nsec: 0, - }, + it_interval: zero_init_timespec(), it_value: *t.as_ref(), }), Expiration::IntervalDelayed(start, interval) => { @@ -118,6 +116,7 @@ pub(crate) mod timer { libc::timespec { tv_sec: 0, tv_nsec: 0, + .. }, it_value: ts, }) => Expiration::OneShot(ts.into()), @@ -257,18 +256,17 @@ impl PartialOrd for TimeSpec { impl TimeValLike for TimeSpec { #[inline] + #[cfg_attr(target_env = "musl", allow(deprecated))] + // https://github.com/rust-lang/libc/issues/1848 fn seconds(seconds: i64) -> TimeSpec { assert!( (TS_MIN_SECONDS..=TS_MAX_SECONDS).contains(&seconds), "TimeSpec out of bounds; seconds={}", seconds ); - #[cfg_attr(target_env = "musl", allow(deprecated))] - // https://github.com/rust-lang/libc/issues/1848 - TimeSpec(timespec { - tv_sec: seconds as time_t, - tv_nsec: 0, - }) + let mut ts = zero_init_timespec(); + ts.tv_sec = seconds as time_t; + TimeSpec(ts) } #[inline] @@ -292,18 +290,18 @@ impl TimeValLike for TimeSpec { /// Makes a new `TimeSpec` with given number of nanoseconds. #[inline] + #[cfg_attr(target_env = "musl", allow(deprecated))] + // https://github.com/rust-lang/libc/issues/1848 fn nanoseconds(nanoseconds: i64) -> TimeSpec { let (secs, nanos) = div_mod_floor_64(nanoseconds, NANOS_PER_SEC); assert!( (TS_MIN_SECONDS..=TS_MAX_SECONDS).contains(&secs), "TimeSpec out of bounds" ); - #[cfg_attr(target_env = "musl", allow(deprecated))] - // https://github.com/rust-lang/libc/issues/1848 - TimeSpec(timespec { - tv_sec: secs as time_t, - tv_nsec: nanos as timespec_tv_nsec_t, - }) + let mut ts = zero_init_timespec(); + ts.tv_sec = secs as time_t; + ts.tv_nsec = nanos as timespec_tv_nsec_t; + TimeSpec(ts) } // The cast is not unnecessary on all platforms. @@ -337,10 +335,10 @@ impl TimeSpec { /// Construct a new `TimeSpec` from its components #[cfg_attr(target_env = "musl", allow(deprecated))] // https://github.com/rust-lang/libc/issues/1848 pub const fn new(seconds: time_t, nanoseconds: timespec_tv_nsec_t) -> Self { - Self(timespec { - tv_sec: seconds, - tv_nsec: nanoseconds, - }) + let mut ts = zero_init_timespec(); + ts.tv_sec = seconds; + ts.tv_nsec = nanoseconds; + Self(ts) } fn nanos_mod_sec(&self) -> timespec_tv_nsec_t { @@ -360,13 +358,13 @@ impl TimeSpec { self.0.tv_nsec } + #[cfg_attr(target_env = "musl", allow(deprecated))] + // https://github.com/rust-lang/libc/issues/1848 pub const fn from_duration(duration: Duration) -> Self { - #[cfg_attr(target_env = "musl", allow(deprecated))] - // https://github.com/rust-lang/libc/issues/1848 - TimeSpec(timespec { - tv_sec: duration.as_secs() as time_t, - tv_nsec: duration.subsec_nanos() as timespec_tv_nsec_t, - }) + let mut ts = zero_init_timespec(); + ts.tv_sec = duration.as_secs() as time_t; + ts.tv_nsec = duration.subsec_nanos() as timespec_tv_nsec_t; + TimeSpec(ts) } pub const fn from_timespec(timespec: timespec) -> Self { |