Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

musl: Change time_t definition on 32-bit targets according to "time64" #1848

Open
JohnTitor opened this issue Jul 28, 2020 · 17 comments · Fixed by shadowsocks/shadowsocks-rust#312 · May be fixed by #3068 or #3791
Open

musl: Change time_t definition on 32-bit targets according to "time64" #1848

JohnTitor opened this issue Jul 28, 2020 · 17 comments · Fixed by shadowsocks/shadowsocks-rust#312 · May be fixed by #3068 or #3791

Comments

@JohnTitor
Copy link
Member

time_t is defined as c_long on musl:

pub type time_t = c_long;

and c_long is i32 on 32-bit targets:
pub type c_long = i32;

But the time_t definition has been changed to 64-bit by bminor/musl@3814333, since musl 1.2.0.
We will change our type to i64 on 32-bit targets as well at some point but we should announce it before changing.
cc #1846

@mahkoh
Copy link

mahkoh commented Aug 1, 2020

Isn't this broken either way as soon as C libraries are involved or am I missing something?

As documented in time64.html, C code compiled against >=1.2 assumes time_t = i64 whereas code compiled against <1.2 assumes time_t = i32 on 32 bit systems. If you use a C library that uses time_t in its interface (e.g. openssl), the time_t used by rust code must have the same size as in the musl headers.

@abcfy2
Copy link

abcfy2 commented Oct 11, 2020

Any updates? I'm facing the same issue when building openssl:

   Compiling shadowsocks-rust v1.8.19 (/project)
error: linking with `arm-linux-musleabi-gcc` failed: exit code: 1
  |
  = note: "arm-linux-musleabi-gcc" "-Wl,--as-needed" "-Wl,-z,noexecstack" "-Wl,--eh-frame-hdr" "-nostartfiles" "/rust/lib/rustlib/arm-unknown-linux-musleabi/lib/self-contained/crt1.o" "/rust/lib/rustlib/arm-unknown-linux-musleabi/lib/self-contained/crti.o" "-L" "/rust/lib/rustlib/arm-unknown-linux-musleabi/lib" "-L" "/rust/lib/rustlib/arm-unknown-linux-musleabi/lib/self-contained" "/target/arm-unknown-linux-musleabi/release/deps/ssurl-b511399b1b3e9edd.ssurl.1o5mikv8-cgu.0.rcgu.o" "-o" "/target/arm-unknown-linux-musleabi/release/deps/ssurl-b511399b1b3e9edd" "-Wl,--gc-sections" "-static" "-no-pie" "-Wl,-zrelro" "-Wl,-znow" "-Wl,-O1" "-nodefaultlibs" "-L" "/target/arm-unknown-linux-musleabi/release/deps" "-L" "/target/release/deps" "-L" "/target/arm-unknown-linux-musleabi/release/build/libsodium-sys-af7e3974b41e2f39/out/installed/lib" "-L" "/target/arm-unknown-linux-musleabi/release/build/openssl-sys-ddefbd6d719725b9/out/openssl-build/install/lib" "-L" "/target/arm-unknown-linux-musleabi/release/build/ring-c1bb5f055649313e/out" "-L" "/rust/lib/rustlib/arm-unknown-linux-musleabi/lib" "-Wl,-Bstatic" "/tmp/rustc2sPxVB/libring-7676a44ad52e73ec.rlib" "/tmp/rustc2sPxVB/liblibsodium_sys-8f2b5176646fe1cb.rlib" "/tmp/rustc2sPxVB/libopenssl_sys-0f67a64037e617dd.rlib" "-Wl,--start-group" "/tmp/rustc2sPxVB/libunwind-bb2d2101beb6f64d.rlib" "/tmp/rustc2sPxVB/liblibc-ae22292566331366.rlib" "-Wl,--end-group" "/rust/lib/rustlib/arm-unknown-linux-musleabi/lib/libcompiler_builtins-1aed8fa9822aaf63.rlib" "-Wl,-Bdynamic" "/rust/lib/rustlib/arm-unknown-linux-musleabi/lib/self-contained/crtn.o"
  = note: /usr/local/bin/../lib/gcc/arm-linux-musleabi/9.2.0/../../../../arm-linux-musleabi/bin/ld: /tmp/rustc2sPxVB/libopenssl_sys-0f67a64037e617dd.rlib(drbg_lib.o): in function `RAND_DRBG_instantiate':
          drbg_lib.c:(.text.RAND_DRBG_instantiate+0x180): undefined reference to `__time64'
          /usr/local/bin/../lib/gcc/arm-linux-musleabi/9.2.0/../../../../arm-linux-musleabi/bin/ld: /tmp/rustc2sPxVB/libopenssl_sys-0f67a64037e617dd.rlib(drbg_lib.o): in function `RAND_DRBG_reseed':
          drbg_lib.c:(.text.RAND_DRBG_reseed+0x154): undefined reference to `__time64'
          /usr/local/bin/../lib/gcc/arm-linux-musleabi/9.2.0/../../../../arm-linux-musleabi/bin/ld: /tmp/rustc2sPxVB/libopenssl_sys-0f67a64037e617dd.rlib(drbg_lib.o): in function `RAND_DRBG_generate':
          drbg_lib.c:(.text.RAND_DRBG_generate+0x164): undefined reference to `__time64'
          /usr/local/bin/../lib/gcc/arm-linux-musleabi/9.2.0/../../../../arm-linux-musleabi/bin/ld: /tmp/rustc2sPxVB/libopenssl_sys-0f67a64037e617dd.rlib(rand_unix.o): in function `check_random_device':
          rand_unix.c:(.text.check_random_device+0x28): undefined reference to `__fstat_time64'
          /usr/local/bin/../lib/gcc/arm-linux-musleabi/9.2.0/../../../../arm-linux-musleabi/bin/ld: /tmp/rustc2sPxVB/libopenssl_sys-0f67a64037e617dd.rlib(rand_unix.o): in function `wait_random_seeded':
          rand_unix.c:(.text.wait_random_seeded+0x184): undefined reference to `__select_time64'
          /usr/local/bin/../lib/gcc/arm-linux-musleabi/9.2.0/../../../../arm-linux-musleabi/bin/ld: /tmp/rustc2sPxVB/libopenssl_sys-0f67a64037e617dd.rlib(rand_unix.o): in function `rand_pool_acquire_entropy':
          rand_unix.c:(.text.rand_pool_acquire_entropy+0x134): undefined reference to `__fstat_time64'
          /usr/local/bin/../lib/gcc/arm-linux-musleabi/9.2.0/../../../../arm-linux-musleabi/bin/ld: /tmp/rustc2sPxVB/libopenssl_sys-0f67a64037e617dd.rlib(rand_unix.o): in function `rand_pool_add_nonce_data':
          rand_unix.c:(.text.rand_pool_add_nonce_data+0x44): undefined reference to `__clock_gettime64'
          /usr/local/bin/../lib/gcc/arm-linux-musleabi/9.2.0/../../../../arm-linux-musleabi/bin/ld: rand_unix.c:(.text.rand_pool_add_nonce_data+0x88): undefined reference to `__gettimeofday_time64'
          /usr/local/bin/../lib/gcc/arm-linux-musleabi/9.2.0/../../../../arm-linux-musleabi/bin/ld: rand_unix.c:(.text.rand_pool_add_nonce_data+0xb0): undefined reference to `__time64'
          /usr/local/bin/../lib/gcc/arm-linux-musleabi/9.2.0/../../../../arm-linux-musleabi/bin/ld: /tmp/rustc2sPxVB/libopenssl_sys-0f67a64037e617dd.rlib(rand_unix.o): in function `rand_pool_add_additional_data':
          rand_unix.c:(.text.rand_pool_add_additional_data+0x74): undefined reference to `__clock_gettime64'
          /usr/local/bin/../lib/gcc/arm-linux-musleabi/9.2.0/../../../../arm-linux-musleabi/bin/ld: rand_unix.c:(.text.rand_pool_add_additional_data+0x9c): undefined reference to `__gettimeofday_time64'
          /usr/local/bin/../lib/gcc/arm-linux-musleabi/9.2.0/../../../../arm-linux-musleabi/bin/ld: rand_unix.c:(.text.rand_pool_add_additional_data+0xc4): undefined reference to `__time64'
          /usr/local/bin/../lib/gcc/arm-linux-musleabi/9.2.0/../../../../arm-linux-musleabi/bin/ld: /tmp/rustc2sPxVB/libopenssl_sys-0f67a64037e617dd.rlib(conf_def.o): in function `def_load_bio':
          conf_def.c:(.text.def_load_bio+0x5dc): undefined reference to `__stat_time64'
          collect2: error: ld returned 1 exit status

@nagisa
Copy link
Member

nagisa commented Oct 29, 2020

The added deprecation notice is now making the libstd build to fail, as it depends on said type.

This means that libstd is either stuck on 0.2.79 for indeterminate amount of time or we need to figure out a way to support either version of musl or give users ability to specify the version of musl they target?

@JohnTitor
Copy link
Member Author

This means that libstd is either stuck on 0.2.79 for indeterminate amount of time or we need to figure out a way to support either version of musl or give users ability to specify the version of musl they target?

It's related to #1412 but we don't have any policy for supported platforms. Yes, both ways are better than just changing the type (also cc #547).

@JohnTitor
Copy link
Member Author

So, we currently detect FreeBSD version, like:

libc/build.rs

Lines 122 to 145 in 4c0a7e5

fn which_freebsd() -> Option<i32> {
let output = std::process::Command::new("freebsd-version").output().ok();
if output.is_none() {
return None;
}
let output = output.unwrap();
if !output.status.success() {
return None;
}
let stdout = String::from_utf8(output.stdout).ok();
if stdout.is_none() {
return None;
}
let stdout = stdout.unwrap();
match &stdout {
s if s.starts_with("10") => Some(10),
s if s.starts_with("11") => Some(11),
s if s.starts_with("12") => Some(12),
s if s.starts_with("13") => Some(13),
_ => None,
}
}

I wonder we could also detect musl version and separate time_t definition.

tamird added a commit to amanda-tait/nix that referenced this issue Nov 10, 2020
See rust-lang/libc#1848 in which this type is
changing from i32 to i64; the change is being announced via this
deprecation.
tamird added a commit to amanda-tait/nix that referenced this issue Nov 11, 2020
See rust-lang/libc#1848 in which this type is
changing from i32 to i64; the change is being announced via this
deprecation.
tamird added a commit to amanda-tait/nix that referenced this issue Nov 11, 2020
See rust-lang/libc#1848 in which this type is
changing from i32 to i64; the change is being announced via this
deprecation.
asomers pushed a commit to asomers/nix that referenced this issue Nov 29, 2020
See rust-lang/libc#1848 in which this type is
changing from i32 to i64; the change is being announced via this
deprecation.
Tim-Zhang added a commit to Tim-Zhang/vsock-rs that referenced this issue Jan 28, 2021
See rust-lang/libc#1848 in which this type is
changing from i32 to i64; the change is being announced via this
deprecation.

Signed-off-by: Tim Zhang <[email protected]>
@ericonr
Copy link

ericonr commented Feb 10, 2021

I wonder we could also detect musl version and separate time_t definition.

How do you deal with the cross compilation case?

@arndb
Copy link

arndb commented Feb 10, 2021

Note that this is not really musl specific, the change to 64-bit time_t needs to happen on all 32-bit implementations in order to have code working beyond year 2038. glibc on riscv uses 64-bit time_t, and patches for glibc and uclibc to convert all other architectures to make this a compile-time decision are in progress.

likebreath pushed a commit to cloud-hypervisor/cloud-hypervisor that referenced this issue Aug 23, 2021
The type is to change from 32-bit to 64-bit. See
rust-lang/libc#1848.

The change is announced via a deprecation warning. Cloud Hypervisor's
code does not need changing. Simply suppress these warnings.

Signed-off-by: Wei Liu <[email protected]>
@pkgw
Copy link

pkgw commented Jun 23, 2022

It feels so silly to ask this, but ... what is the actual course of action here if I have FFI code that triggers this deprecation notice? Try to ensure that time_t doesn't appear in the FFI layer, i.e. add casts on the C side as appropriate to change time_t into int64_t/i64?

pkgw added a commit to matz-e/tectonic that referenced this issue Jun 23, 2022
As per rust-lang/libc#1848, we can't safely do this since the definition
of time_t depends on which version of Musl you're using on 32-bit
systems (the "time64" update for Musl 1.2), and this actually started
biting us on the arm-unknown-linux-musleabihf cross build.
Unfortunately, ISO C makes virtually no guarantees about what time_t is,
so I don't see a practical way to handle the different possibilities
robustly. We'll just cast from i64 or u64 to time_t in C and hope for
the best.
@rawler
Copy link

rawler commented Sep 27, 2022

Echoing @pkgw here. What is the right course of action here? libc::time_t is deprecated on musl. Should I use some other type-alias? Hard-coding i64 is likely to also break on some targets, right? Should I use libc::time_t but suppress the warning?

@arndb
Copy link

arndb commented Sep 27, 2022

Any use of time_t/timeval/timespec that does not match the libc-defined type will cause data corruption. On both musl and libc you can encounter both 32-bit and 64-bit types. With musl, this is purely dependent on the version of the library, i.e. musl-1.2 only allows compiling with a 64-bit time_t, while glibc allows both, depending on whether the _TIME_BITS macro was set to '64' when building the C code one is linking against, same as the _FILE_OFFSET_BITS macro for off_t and other types.

The only portable way to do this is to avoid any use of time_t, struct timeval, struct timespec, ino_t, blkcnt_t, as well as any types derived from these, such as struct stat, struct dirent, or struct rlimit when interfacing with C/C++ code.

@wesleywiser wesleywiser linked a pull request Jan 13, 2023 that will close this issue
@syrel
Copy link

syrel commented Jan 17, 2023

emscripten changed time_t to 64bit in July 2022, see emscripten-core/emscripten#17393.
Probably could be another reason to reconsider this issue.

algitbot pushed a commit to alpinelinux/aports that referenced this issue Feb 3, 2023
this version is broken on 32-bit arches due to libc crate incompatibility
with musl's new ABI for time_t, see: rust-lang/libc#1848
bell-sw pushed a commit to bell-sw/alpaquita-aports that referenced this issue Apr 6, 2023
[ commit 5858e10e41fed33d2673a1a3724f96a7b18bc3cd ]

this version is broken on 32-bit arches due to libc crate incompatibility
with musl's new ABI for time_t, see: rust-lang/libc#1848
dbeltra added a commit to plancksecurity/foundation-planckCoreSequoiaBackend that referenced this issue Nov 28, 2023
- time_t -> u64:  see [1]
- removing dynamic library as cdylib is unsupported

(this is an update of 501cca6 so it can be merged)

[1] rust-lang/libc#1848
mislavn added a commit to mislavn/libpnet that referenced this issue Jun 7, 2024
rust-lang/libc#1848

This is a work in progress to resolve the time_t definition change in
musl 1.2.0, where on 32 bit systems the definition has been changed from
32 bits to 64 bits.

Signed-off-by: Mislav Novakovic <[email protected]>
ghost pushed a commit to plancksecurity/foundation-planckCoreSequoiaBackend that referenced this issue Jun 25, 2024
- time_t -> u64:  see [1]
- removing dynamic library as cdylib is unsupported

(this is an update of 501cca6 so it can be merged)

[1] rust-lang/libc#1848
@myl7 myl7 linked a pull request Aug 5, 2024 that will close this issue
@tgross35 tgross35 added this to the 1.0 milestone Aug 29, 2024
@detly
Copy link

detly commented Oct 9, 2024

The only portable way to do this is to avoid any use of time_t, struct timeval, struct timespec, ino_t, blkcnt_t, as well as any types derived from these, such as struct stat, struct dirent, or struct rlimit when interfacing with C/C++ code.

Is this advice for libc itself (or anyone planning to work on libc), or for downstream developers? Because there are plenty of C APIs that use these types, so any wrapper crates will have to use those types to interface with them. For eg. rusb wraps libusb, which uses timeval in eg. libusb_wait_for_event() and others.

So, rusb seems to have no way to avoid using timeval, and users of rusb who might know the details of their target platform can't control the size mismatch.

@arndb
Copy link

arndb commented Oct 9, 2024

In a specific package like rusb, the most reliable way to address this is to ensure that the underlying C library exports both time32 and time64 symbols in the way that glibc does. This way rusb can always use the time64 interface, while C based applications can pick the symbol based on their configuration.

Having a generic solution is much harder since a glibc based system may have a mix of time32 and time64 libraries installed, making it impossible to know which types are used in a particular library. As 32-bit Linux distros are increasingly going away or migrating to time64, I see two options, neither of which is a complete fix:

a) have some build-time feature detection to probe the defaults of the compiler, making the time_t/timespec/timeval/off_t/ino_t/... types depend on the __USE_TIME_BITS64 macro defined by the C libraries that are configured for time64. This is a lot of extra work but remains unreliable because the default flags used by the compiler may not reflect what a given library API was built with.

b) Drop time32 support on 32-bit Linux/glibc rust altogether and assume that the system libraries are all built for time64, same as with musl. This fixes the glibc systems that are currently broken but in turn breaks the ones that happen to work by chance today because they have not been converted yet or never will.

@safinaskar
Copy link

Possible solution: rust-lang/rfcs#3716 ("[RFC] Target Modifiers")

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment