7 ms·
Before the "rewrite it in Rust" comments take over the thread: It is worth noting that the class of bugs described here (logic errors in highly concurrent stat
by Fiveplus 9mo ago
Before the "rewrite it in Rust" comments take over the thread:
It is worth noting that the class of bugs described here (logic errors in highly concurrent state machines, incorrect hardware assumptions) wouldn't necessarily be caught by the borrow checker. Rust is fantastic for memory safety, but it will not stop you from misunderstanding the spec of a network card or writing a race condition in unsafe logic that interacts with DMA.
That said, if we eliminated the 70% of bugs that are memory safety issues, the SNR ratio for finding these deep logic bugs would improve dramatically. We spend so much time tracing segfaults that we miss the subtle corruption bugs.
- anon-3988 9mo ago> It is worth noting that the class of bugs described here (logic errors in highly concurrent state machines, incorrect hardware assumptions) wouldn't necessarily be caught by the borrow checker. Rust is fantastic for memory safety, but it will not stop you from misunderstanding the spec of a network card or writing a race condition in unsafe logic that interacts with DMA. Rust is not just about memory safety. It also have algebraic data types, RAII, among other things, which will greatly help in catching this kind of silly logic bugs.
- JuniperMesos 9mo agoYeah, Rust gives you much better tools to write highly concurrent state machines than C does, and most of those tools are in the type system and not the borrow checker per se. This is exactly what the Typestate pattern (https://docs.rust-embedded.org/book/static-guarantees/typestate-programming.html https://docs.rust-embedded.org/book/static-guarantees/typest...) is good at modeling.
- aw1621107 9mo ago> It is worth noting that the class of bugs described here (logic errors in highly concurrent state machines, incorrect hardware assumptions) While the bugs you describe are indeed things that aren't directly addressed by Rust's borrow checker, I think the article covers more ground than your comment implies. For example, a significant portion (most?) of the article is simply analyzing the gathered data, like grouping bugs by subsystem: Subsystem Bug Count Avg Lifetime drivers/can 446 4.2 years networking/sctp 279 4.0 years networking/ipv4 1,661 3.6 years usb 2,505 3.5 years tty 1,033 3.5 years netfilter 1,181 2.9 years networking 6,079 2.9 years memory 2,459 1.8 years gpu 5,212 1.4 years bpf 959 1.1 years Or by type: Bug Type Count Avg Lifetime Median race-condition 1,188 5.1 years 2.6 years integer-overflow 298 3.9 years 2.2 years use-after-free 2,963 3.2 years 1.4 years memory-leak 2,846 3.1 years 1.4 years buffer-overflow 399 3.1 years 1.5 years refcount 2,209 2.8 years 1.3 years null-deref 4,931 2.2 years 0.7 years deadlock 1,683 2.2 years 0.8 years And the section describing common patterns for long-lived bugs (10+ years) lists the following: > 1. Reference counting errors > 2. Missing NULL checks after dereference > 3. Integer overflow in size calculations > 4. Race conditions in state machines All of which cover more ground than listed in your comment. Furthermore, the 19-year-old bug case study is a refcounting error not related to highly concurrent state machines or hardware assumptions.
- johncolanduoni 9mo agoIt depends what they mean by some of these: are the state machine race conditions logic races (which Rust won’t trivially solve) or data races? If they are data races, are they the kind of ones that Rust will catch (missing atomics/synchronization) or the ones it won’t (bad atomic orderings, etc.). It’s also worth noting that Rust doesn’t prevent integer overflow, and it doesn’t panic on it by default in release builds. Instead, the safety model assumes you’ll catch the overflowed number when you use it to index something (a constant source of bugs in unsafe code). I’m bullish about Rust in the kernel, but it will not solve all of the kinds of race conditions you see in that kind of context.
- aw1621107 9mo ago> are the state machine race conditions logic races (which Rust won’t trivially solve) or data races? If they are data races, are they the kind of ones that Rust will catch (missing atomics/synchronization) or the ones it won’t (bad atomic orderings, etc.). The example given looks like a generalized example: spin_lock(&lock); if (state == READY) { spin_unlock(&lock); // window here where another thread can change state do_operation(); // assumes state is still READY } So I don't think you can draw strong conclusions from it. > I’m bullish about Rust in the kernel, but it will not solve all of the kinds of race conditions you see in that kind of context. Sure, all I'm trying to say is that "the class of bugs described here" covers more than what was listed in the parentheses.
- rjzzleep 9mo agoI'd argue, that while null ref and those classes of bugs may decrease, logic errors will increase. Rust is not an extraordinary readable language in my opinion, especially in the kernel where the kernel has its own data structures. IMHO Apple did it right in their kernel stack, they have a restricted subset of C++ that you can write drivers with. Which is also why in my opinion Zig is much more suitable, because it actually addresses the readability aspect without bring huge complexity with it.
- johncolanduoni 9mo agoThis is I think an under-appreciated aspect, both for detractors and boosters. I take a lot more “risks” with Rust, in terms of not thinking deeply about “normal” memory safety and prioritizing structuring my code to make the logic more obviously correct. In C++, modeling things so that the memory safety is super-straightforward is paramount - you’ll almost never see me store a std::string_view anywhere for example. In Rust I just put &str wherever I please, if I make a mistake I’ll know when I compile.
- the8472 9mo agoThe concurrent state machine example looks like a locking error? If the assumption is that it shouldn't change in the meantime, doesn't it mean the lock should continue to be held? In that case rust locks can help, because they can embed the data, which means you can't even touch it if it's not held.
- paulddraper 9mo agoRust would prevent a number of bugs, as it can model state machine guarantees as well. Rewriting it all in Rust is extremely expensive, so it won't be done (soon).
- wiz21c 9mo agoExpensive because of: 1/ a re-write is never easy 2/ rust is specifically tough (because it catches error and forces you to think about it for real, because it makes some contruct (linked list) really hard to implement) for kernel/close to kernel code ?
- IshKebab 9mo agoBoth I'd say. Rust imposes more constraints on the structure of code than most languages. The borrow checker really likes ownership trees whereas most languages allow any ownership graph no matter how spaghetti it is. As far as I know that's why Microsoft rewrote Typescript in Go instead of Rust.
- wiz21c 9mo agoI've been using rust for several years now and I like the way you explain the essence of the issue: tree instead of spaghetti :-) However: https://www.reddit.com/r/typescript/comments/wbkfsh/which_programming_language_is_typescript_developed/ https://www.reddit.com/r/typescript/comments/wbkfsh/which_pr... so looks like it's not written in go :-)
- IshKebab 9mo ago> so looks like it's not written in go :-) That post is three years old, before the rewrite.
- wiz21c 9mo agoI missed that. For the curious: https://www.reddit.com/r/golang/comments/1j8shzb/microsoft_rewriting_typescript_in_go/ https://www.reddit.com/r/golang/comments/1j8shzb/microsoft_r... When asked why go and not rust, they said: "The existing (javascript) code base makes certain assumptions -- specifically, it assumes that there is automatic garbage collection -- and that pretty much limited our choices. That heavily ruled out Rust. I mean, in Rust you have memory management, but it's not automatic; you can get reference counting or whatever you could, but then, in addition to that, there's the borrow checker and the rather stringent constraints it puts on you around ownership of data structures. In particular, it effectively outlaws cyclic data structures, and all of our data structures are heavily cyclic. " sharp!
- IshKebab 9mo agoRust has other features that help prevent logic errors. It's not just C plus a borrow checker.
- keybored 9mo agoNo other top-level comments have since mentioned Rust[1] and TFA mentions neither Rust nor topics like memory safety. It’s just plain bugs. The Rust phantom zealotry is unfortunately real. [1] Aha, but the chilling effect of dismissing RIR comments before they are even posted...
- staticassertion 9mo agoYes, I saw this last night and was confused because only one comment mentioned Rust, and it was deleted I think. I nearly replied "you're about to prompt 1,000 rust replies with this" and here's what I woke up to lol
- kubb 9mo agoIt’s hilarious that you feel the need to preemptively take control of the narrative in anticipation of the Rust people that you fear so much. Is this an irrational fear, I wonder? Reminds me of methods used in the political discourse.
- irishcoffee 9mo ago> It’s hilarious that you feel the need to preemptively take control of the narrative in anticipation of the Rust people that you fear so much. > Is this an irrational fear, I wonder? Reminds me of methods used in the political discourse. In a sad sort of way, I think its hilarious that hn users have been so completely conditioned to expect rust evangelism any time a topic like this comes up that they wanted to get ahead of it. Not sure who it says more about, but it sure does say a whole lot.
- kubb 9mo agoI don’t think evangelism is necessary anymore. Rust adoption is now a matter of time.
- Ferret7446 9mo agoRust feels a lot like Ruby (fancy/weird with a fanatical user base). Fil-C is a far more practical route to memory safety (a la Python in this analogy).
- Bridged7756 9mo agoPeople who make that kind of remarks should be called out and shunned. The Rust community is tired of discrimination and being the butt of jokes. All the other inferior languages prey on its minority status, despite Rust being able to solve all their problems. I take offense to these remarks, I don't want my kids to grow up as Rustaceans in such a caustic society.
- ramon156 9mo agoYou're fighting air
- mgaunard 9mo agoI don't think 70% of bugs are memory safety issues. In my experience it's closer to 5%.
- nibman 9mo ago[dead]
- redeeman 9mo agoprobably quite a bit less than 5%, however, they tend to be quite serious when they happen
- mgaunard 9mo agoOnly serious if you care about protecting from malicious actors running code on the same host.
- redeeman 9mo agoyou dont? I would imagine people that runs for example a browser would have quite an interest in that
- mgaunard 9mo agoBrowsers are sandboxed, and working on the web browsers themselves is a very small niche, as is working on kernels. Software increasingly runs either on dedicated infrastructure or virtual ones; in those cases there isn't really a case where you need to worry about software running on the same host trying to access the data. Sure, it's useful to have some restrictions in place to track what needs access to what resource, but in practice they can always be circumvented for debugging or convenience of development.
- yencabulator 9mo agoBrowsers are sandboxed by the kernel, and we're talking about bugs in the kernel here...
- nibman 9mo ago[dead]
- pjc50 9mo ago> race condition in unsafe logic that interacts with DMA It's worth noting that if you write memory safe code but mis-program a DMA transfer, or trigger a bug in a PCIe device, it's possible for the hardware to give you memory-safety problems by splatting invalid data over a region that's supposed to contain something else.
- DobarDabar 9mo ago[dead]
- lynx97 9mo agoThanks for raising this. It feels like evangelists paint a picture of Rust basically being magic which squashes all bugs. My personal experience is rather different. When I gave Rust a whirl a few years ago, I happened to play with mio for some reason I can't remember yet. Had some basic PoC code which didn't work as expected. So while not being a Rust expert, I am still too much fan of the scratch your own itch philosophy, so I started to read the mio source code. And after 5 minutes, I found the logic bug. Submitted a PR and moved on. But what stayed with me was this insight that if someone like me can casually find and fix a Rust library bug, propaganda is probably doing more work then expected. The Rust craze feels a bit like Java. Just because a language baby-sits the developer doesn't automatically mean better quality. At the end of the day, the dev needs to juggle the development process. Sure, tools are useful, but overstating safety is likely a route better avoided.
- john01dav 9mo agoRust has more features than just the borrow checker. For example, it has a a more featured type system than C or C++, which a good developer can use to detect some logic mistakes at compile time. This doesn't eliminate bugs, but it can catch some very early.
- wordisside 9mo ago[dead]
- aw1621107 9mo ago> But unsafe Rust, which is generally more often used in low-level code, is more difficult than C and C++. I think "is" is a bit too strong. "Can be", sure, but I'm rather skeptical that all uses of unsafe Rust will be more difficult than writing equivalent C/C++ code.
- wordisside 9mo ago[flagged]
- marcosdumay 9mo agoEh... Removing concurrence bugs is one of the main selling points for Rust. And algebraic types are a really boost for situations where you have lots of assumptions.
- BobbyTables2 9mo agoI’ve seen too many embedded drivers written by well known companies not use spinlocks for data shared with an ISR. At one point, I found serious bugs (crashing our product) that had existed for over 15 years. (And that was 10 years ago). Rust may not be perfect but it gives me hope that some classes of stupidity will be either be avoided or made visible (like every function being unsafe because the author was a complete idiot).
- eru 9mo ago> It is worth noting that the class of bugs described here (logic errors in highly concurrent state machines, incorrect hardware assumptions) wouldn't necessarily be caught by the borrow checker. You are right about that, but even just using sum types eliminates a lot of logic errors, too.