fix(pcm): htstamp segfaults on 32-bit time64 platforms - #151
Conversation
|
Hi and thanks for the investigation,
...but, shouldn't this be fixed in the libc crate then? So that |
|
Yeah, I think this may be rust-lang/libc#3223. Looking at its timeline I'm not too hopeful though: open since 2023 and no clear activity since May 2025. This PR would be defensive workaround for as long as that takes. The remaining downside is the silent A proper fix would be a |
|
@roderickvd I would kindly ask you to at least make an attempt to fix/raise this with the libc crate people first, since that would fix things for many more people than just alsa. If that attempt is unsuccessful, let's revisit and see what the least ugly workaround in alsa would be. Thanks! |
|
@roderickvd Any news on this? Maybe a feature in alsa-sys to force 64 bit timespec if we can't make it in libc? |
|
I didn't follow up on it with libc. You are probably right that this is better fixed in alsa-sys than here. What's your view on that feature flag you're proposing vs. a build-time probe? |
|
A feature flag named, say But I'm not an expert on the topic and open to be convinced otherwise if you have a compelling reason to prefer the probe? |
|
Just brainstorming - there's no way we can detect this at runtime/ program startup? Like if there's a function in libc we can call to get the current time, wait a few 100 us and call it again and see which bytes changed values, and then go from there? |
|
@roderickvd What do you think of this: diwic/alsa-sys#18 |
|
Yes, that seems better. I'll close this one so we can continue there. |
This popped up downstream in RustAudio/cpal#1134 and fixes #150 without the need to set
RUST_LIBC_UNSTABLE_GNU_TIME_BITS=64.On 32-bit Linux with a
time64glibc,snd_pcm_status_get_htstampand friends write a 16-byte structtimespecinto the pointer passed to them. Sincelibc::timespecis only 8 bytes on these targets, the alsa function then wrote 8 bytes past it, corrupting the stack and causing a segfault. This PR passes a 16-byte buffer on 32-bit targets to reconstruct atimespecfrom it.I don't have a big-endian system to test with, but I made it endianness-aware from what I could gather.
glibc'stime64seems to place a 4-byte padding beforetv_nsecon big-endian and after it on little-endian, sotv_nsecsits at offset 8 on LE and offset 12 on BE. Otherlibcs seem to use offset 8 regardless of endianness, hence thetarget_env = "gnu"guard.On 64-bit targets,
libc::timespecis already 16 bytes, so the originalzeroed()+ direct call is left untouched.One limitation, likely significant: 32-bit systems with a
time32alsa-libwere never affected by the segfault, but will now regress to havetv_nsecsilently read as zero. While thetime64transition is effectively done on modern distros, this is almost a case of "pick your poison": segfault on 32-bit targets withtime64or return zerotv_nsecon 32-bit targets.I say almost because it probably can be fixed using a
build.rsprobe ofsizeof(time_t)in C to set acfgflag. I wasn't sure whether that's worth the added complexity here, so leaving it to your judgement.