← Back to context

Comment by johncolanduoni

2 days ago

It 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.

> 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.

  • I'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.

    • > I'd argue, that while null ref and those classes of bugs may decrease, logic errors will increase.

      To some extent that argument only makes sense; if you can find a way to greatly reduce the incidence of non-logic bugs while not addressing other bugs then of course logic bugs would make up a greater proportion of what remains.

      I think it's also worth considering the fact that while Rust doesn't guarantee that it'll catch all logic bugs, it (like other languages with more "advanced" type systems) gives you tools to construct systems that can catch certain kinds of logic bugs. For example, you can write lock types in a way that guarantees at compile time that you'll take locks in the correct order, avoiding deadlocks [0]. Another example is the typestate pattern [1], which can encode state machine transitions in the type system to ensure that invalid transitions and/or operations on invalid states are caught at compile time.

      These, in turn, can lead to higher-order benefits as offloading some checks to the compiler means you can devote more attention to things the compiler can't check (though to be fair this does seem to be more variable among different programmers).

      > Rust is not an extraordinary readable language in my opinion, especially in the kernel where the kernel has its own data structures.

      The above notwithstanding, I'd imagine it's possible to think up scenarios where Rust would make some logic bugs more visible and others less so; only time will tell which prevails in the Linux kernel, though based on what we know now I don't think there's strong support for the notion that logic bugs in Rust are a substantially more common than they have been in C, let alone because of readability issues.

      Of course there's the fact that readability is very much a personal thing and is a multidimensional metric to boot (e.g., a property that makes code readable in one context may simultaneously make code less readable in another). I don't think there would be a universal answer here.

      [0]: https://lwn.net/Articles/995814/

      [1]: https://cliffle.com/blog/rust-typestate/

    • > Zig is much more suitable, because it actually addresses the readability aspect

      How? It doesn't look very different from Rust. In terms of readability Swift does stand out among LLVM frontends, don't know if it is or can be used for systems programming though.

      6 replies →

    • I would argue logic errors would decrease because you aren't spending as much time worrying about and fixing null ref and other errors.

      1 reply →

    • Rust is a lot more explicit. I suspect logic bugs will be much less common. It's far easier to model complexity in Rust.

    • I would expect the opposite. C requires you to deal with extreme design complexity in large systems because the language offers nothing to help.

  • The default Mutex struct in Rust makes it impossible to modify the data it protects without holding the lock.

    "Each mutex has a type parameter which represents the data that it is protecting. The data can only be accessed through the RAII guards returned from lock and try_lock, which guarantees that the data is only ever accessed when the mutex is locked."

    Even if used with more complex operations, the RAII approach means that the example you provided is much less likely to happen.

I don’t think that the parent comment is saying all of the bugs would have been prevented by using Rust.

But in the listed categories, I’m equally skeptical that none of them would have benefited from Rust even a bit.

  • That’s not my point - just that “state machine races” is a too-broad category to say much about how Rust would or wouldn’t help.