Hacker News new | ask | show | jobs
by wahern 3135 days ago
Fearless, indeed: https://github.com/servo/servo/issues?page=1&q=thread+race
3 comments

I clicked a few of those links and they were mostly instances of the word "race" appearing as part of, for example, "Traceable".

Somewhere on the second page I found a brief mention of a data race in rustc itself (that was fixed).

Looks pretty fearless to me!

  After some digging I found that the issue is that whenever
  src is set and then contentDocument is called right after,
  there is a race condition and contentDocument will return
  null because the Document hasn't been created in the script
  thread yet.

  -- https://github.com/servo/servo/pull/14764
I decided not to cherry pick because I figured people could look through themselves and decide. And because culprits are not always found (or at least documented) before a fix is committed. This is how thread races work in any language--they're hard to definitively pin down, not to mention reliably reproduce, but generally easy to fix (or at least make disappear) once something suspicious comes to your attention.

Concurrency is easy when you don't share mutable data. But when you do have to share mutable data--core, performance-sensitive shared data structures--Rust hardly makes doing so "fearless". What Rust does is make it difficult to _accidentally_ share mutable data.

Rust only saves you from simple races, not more complex ones. That's quite a lot already.

Most importantly, though, it preserves _memory safety_ in concurrent situations, so your stuff won't randomly crash, but properly panic.

It's no silver bullet, but it _is_ the "magic sauce" behind Stylo.

More precisely, Rust saves you from data races but not race conditions.

https://blog.regehr.org/archives/490

I’m pretty sure Rust saves you from ALL data races so long as you stay within the boundaries of safe code. Do you have anything at all to reference otherwise that says only certain data races are detected while others are not?

To my knowledge you can defeat the compile-time data race detection if you are either doing unsafe or certain scenarios with Cell/RefCell but even in that case you are guaranteed runtime detection rather than compile time detection.

These feature alone is worth its weight in gold.

Given the a "data race" is essentially defined to be the class of races that Rust's type system guards again, yeah it saves you from all of them.
Rust's definition of "data race" isn't just "what the Rust compiler rejects", it has a specific meaning:

"Safe Rust guarantees an absence of data races, which are defined as: 1. two or more threads concurrently accessing a location of memory, 2. one of them is a write, 3. one of them is unsynchronized."

https://doc.rust-lang.org/nomicon/races.html

qznc puts that better then I do. It saves you from data races, but not from race conditions.

Cell and RefCell are both not Sync (that means they can't be used from multiple threads) for a reason. RefCell does, however, allow borrow checking at runtime, for wrapping it with something that establishes Sync.

Here's a potential use-after-free, listed in my query:

  https://github.com/servo/servo/issues/14014
Of course it's using unsafe code and doing other crazy stuff--a lot of these issues are related to shared, mutable, tree structures. But that's precisely my point. When you're implementing something as sophisticated as Servo and trying to keep things performant and multi-threaded, concurrency is hardly fearless. Servo does this and they have bugs.

Indeed, being "fearless" is precisely how you end up with these bugs, in Rust or any other language. If you're fearless you're more apt to move from a big lock to a fine-grained locking mechanism. That's error prone, including in Rust.

It's like that dude in Florida whose Tesla flew under the tractor trailer. He was fearless in the same way inexperienced engineers using Rust will be when they hear "fearless concurrency". They'll push the envelope when they have no need to, because that's what inexperienced engineers do who haven't been burned, especially when they think their tools make them fire-proof.

Try opening some of those and ctrl+f to realize what was actually matched. Hint: not "thread race"
Some are, some aren't. It's difficult to pick them out because some aren't resolved, and some that are resolved were fixed with "works for me" without nailing down the culprit.

I just take issue with "fearless concurrency". All concurrency is fearless if you use a share-nothing architecture. But often times for performance you can't do that. And while Rust may be better than most languages about making it more difficult to screw up, even the Servo folks create race conditions.