logoalt Hacker News

Never snooze a future

29 pointsby vinhnxlast Sunday at 11:17 AM7 commentsview on HN

Comments

yoshuawtoday at 10:29 AM

For the past seven years I've been urging people to stop using `select!` in async Rust code and use dedicated structured control flow primitives instead. Correct use of `select!` cannot be guaranteed by the compiler [1], and so it's unsurprising it leads to bugs.

For the first example the better option would be to use the `race` operation [2]. For the second it would be better to use `ConcurrentStream` [3]. Many (but not all) of the issues people have with cancellation in async Rust can be improved with the advice: "don't use select!".

[1]: https://blog.yoshuawuyts.com/futures-concurrency-3/#issues-w...

[2]: https://docs.rs/futures-concurrency/latest/futures_concurren...

[3]: https://docs.rs/futures-concurrency/latest/futures_concurren...

cousin_ittoday at 9:16 AM

Looks like the code of foo() says "take a lock then sleep for 10 millis", but actually it can take the lock and then sleep forever, depending on how it's polled. Well! This seems like a bug with the async abstraction in Rust then. Or if you don't like "bug", then "disagreement with intuition that will cause bugs forever". Goroutines in Go don't have this problem: if a goroutine says it'll take a lock and sleep for 10 millis, then that's what it'll do. The reason is because Go concurrency is preemptive, while async in Rust is cooperative.

So maybe the lesson I'd take is that if you're programming with locks (or other synchronization primitives), your concurrency model has to be preemptive. Cooperative concurrency + locks = invitation to very subtle bugs.

show 1 reply
ixxietoday at 8:29 AM

I thought this was a "carpe diem" motivational post xD

nixpulvistoday at 11:08 AM

Is the non-local reasoning here a limitation of Rust, async Rust, or the libraries built around async Rust?