Live data from Hacker News

Discovering a JDK Race Condition, and Debugging It in 30 Minutes with Fray

aoli.al

41–50 of 54 posts

Re: Discovering a JDK Race Condition, and Debugging It in 30 Minutes with Fray

#41
post #38

Earlier quoted context omitted.

I agree that messy reality can intervene, in the medium term (for about a decade) we'll need to handle leap seconds But we can do a lot without challenging the messy reality. 61 second minutes are (regrettably) a thing in some time systems, but negative 1 million second minutes are not a thing, there's no need for this to be a signed integer!

The struct is also used for date/time arithmetic and the standard library explicitly supports out-of-range values for this reason.

I have no doubt that C "explicitly supports" this, but it's a bad idea.

The C standard library has the excuse that most of it is very old. We should do better.

Re: Discovering a JDK Race Condition, and Debugging It in 30 Minutes with Fray

#42
post #36

Earlier quoted context omitted.

void setDate(int month, int day) { if (notValidDate(month, date)) { throw; } this.month = month; // atomic this.day = day // atomic } Yet the whole function is not "atomic"/transactional/consistent, and two threads running simultaneously may surface the above error. Of course it can ensure that it is consistent, C code can also just ensure that it is memory safe. This is just not an inherent property, and in general…

But you were critiquing Rust's model, yet you've written C++ here. I agree it's perfectly easy to write the bug in C++. In Rust this improved type doesn't have the defect, to call Rust's analogue of your setDate function you must have the exclusive mutable reference, which means there's no concurrency problem. You have to do a whole lot of extra work to write the bug and why would you, just write what you meant and i…

It's called pseudo-code, and some extra attempt on your part to deliberately miss the point.

Give it another go at understanding what I'm saying, cheers!

Re: Discovering a JDK Race Condition, and Debugging It in 30 Minutes with Fray

#43
post #38

Earlier quoted context omitted.

The struct is also used for date/time arithmetic and the standard library explicitly supports out-of-range values for this reason.

I have no doubt that C "explicitly supports" this, but it's a bad idea. The C standard library has the excuse that most of it is very old. We should do better.

Better for whom? If you want a dead-simple time type, use time_t.

There are plenty of improvements needed in the C time APIs, like sub-second precision, thread safety, and timezone awareness. What benefit is there to making the struct fields unsigned beyond some arbitrary purity test? This is still C, there are still plenty of ways to make invalid values. And it is nice to be able to subtract as well as add.

Heck, there's no way to encode the full Gregorian Calendar rules in the type system of any language I've ever used, so every choice is going to be a compromise. February 29 Not-A-Leap-Year and April 31 are still invalid dates even if you can outlaw January 0 and March 32.

Making all the fields in struct tm signed ints is clearly there to allow them to be manipulated and consistently so, since other types would obviously be better for size if nothing else.

Re: Discovering a JDK Race Condition, and Debugging It in 30 Minutes with Fray

#44
post #21
post #19

Earlier quoted context omitted.

Race conditions are generally solved with algorithms, not the language. For example, defining a total ordering on locks and only acquiring locks in that order to prevent deadlock. I guess there there are language features like co-routines/co-operative multi-tasking that make certain algorithms possible, but nothing about Java prevents implementing sound concurrency algorithms in general.

> Race conditions are generally solved with algorithms, not the language. For example, defining a total ordering on locks You wouldn't make that claim if your language didn't have locks.

Not sure what you mean!? Locks, at their core, are not implemented by languages. They’re feature of a task runtime e.g. Postgres advisory locks or kernel locks in a Posix OS.

Re: Discovering a JDK Race Condition, and Debugging It in 30 Minutes with Fray

#45
post #31
post #24

Earlier quoted context omitted.

I've read a few postmortems about STM. I have to take them with a grain of salt because I usually read those reports right after doing a bunch of STM programming, and right before doing a bunch more STM programming. Reports of its death have been greatly exaggerated. Here it is in 2006 featuring the same Tim from your article: https://www.youtube.com/watch?v=tve57vilywc I didn't start using it in anger till 2013-2014…

`atomic` is their choice of syntax for an STM transaction in their experimental C# runtime, it's not an atomic statement. Please take the time to actually read the article, because you have obviously just skimmed over it. This was not written by some nobody, he does know what he talks about.

Argue the point, not the person.

Look ma, no skimming: https://news.ycombinator.com/item?id=37647230

Re: Discovering a JDK Race Condition, and Debugging It in 30 Minutes with Fray

#46
post #45
post #31

Earlier quoted context omitted.

`atomic` is their choice of syntax for an STM transaction in their experimental C# runtime, it's not an atomic statement. Please take the time to actually read the article, because you have obviously just skimmed over it. This was not written by some nobody, he does know what he talks about.

Argue the point, not the person. Look ma, no skimming: https://news.ycombinator.com/item?id=37647230

There is not much to argue, when your point is based on a misunderstanding.

> You nest transactional statements, not the calls to atomic. The happy-path for an atomic is that it will commit; it should be obvious a priori that something that commits cannot be in the codepath that can be rolled back.

This makes absolutely no sense with my above correction.

Re: Discovering a JDK Race Condition, and Debugging It in 30 Minutes with Fray

#47
post #27
post #21

Earlier quoted context omitted.

> Race conditions are generally solved with algorithms, not the language. For example, defining a total ordering on locks You wouldn't make that claim if your language didn't have locks.

Exactly, this thread is full of ignorant comments. I was talking about a certain class of race conditions that can be completely prevented in some languages, like Rust (through its aliasing rules that just make it impossible to mutate things from different threads simultaneously, among other things) and languages like Pony, for example, as the language uses the Actor model for concurrency, which means it has no locks…

In Java, racing a field is safe - you can only ever observe the value as one that was explicitly set by a thread, no tearing can happen. Safe data races can happen in Java, but you sometimes do want that (e.g. efficient concurrent algorithms), and avoiding it is not particularly hard (synchronized blocks are not the state of the art, but does make it easy to solve a problem).

Pony and Rust are both very interesting languages, but it is absolutely trivial to re-introduce locks with actors, even just accidentally, and then you are back at square 1. This is what you have to understand, their fundamental model has a one-to-one mapping to "traditional" multi-threading with locks. The same way you can't avoid the Turing model's gotchas, actors and stuff won't fundamentally change the landscape either.

Re: Discovering a JDK Race Condition, and Debugging It in 30 Minutes with Fray

#48
post #47
post #27

Earlier quoted context omitted.

Exactly, this thread is full of ignorant comments. I was talking about a certain class of race conditions that can be completely prevented in some languages, like Rust (through its aliasing rules that just make it impossible to mutate things from different threads simultaneously, among other things) and languages like Pony, for example, as the language uses the Actor model for concurrency, which means it has no locks…

In Java, racing a field is safe - you can only ever observe the value as one that was explicitly set by a thread, no tearing can happen. Safe data races can happen in Java, but you sometimes do want that (e.g. efficient concurrent algorithms), and avoiding it is not particularly hard (synchronized blocks are not the state of the art, but does make it easy to solve a problem). Pony and Rust are both very interesting l…

> avoiding it is not particularly hard (synchronized blocks are not the state of the art, but does make it easy to solve a problem).

Please have a read of https://joeduffyblog.com/2010/01/03/a-brief-retrospective-on... (and don't just skim it.)

(This was not written by some nobody, he does know what he talks about.)

  Contrast this elegant simplicity with the many pitfalls of locks:

  Data races. Like forgetting to hold a lock when accessing a certain piece of data. And other flavors of data races, such as holding the wrong lock when accessing a certain piece of data. Not only do these issues not exist, but the solution is not to add countless annotations associating locks with the data they protect; instead, you declare the scope of atomicity, and the rest is automatic.

  Reentrancy. Locks don’t compose. Reentrancy and true recursive acquires are blurred together. If a locked region expects reentrancy, usually due to planned recursion, life is good; if it doesn’t, life is bad. This often manifests as virtual calls that reenter the calling subsystem while invariants remain broken due to a partial state transition. At that point, you’re hosed.

  Performance. The tension between fine-grained locking (better scalability) versus coarse-grained locking (simplicity and superior performance due to fewer lock acquire/release calls) is ever-present. This tension tugs on the cords of correctness, because if a lock is not held for long enough, other threads may be able to access data while invariants are still broken. Scalability pulls you to engage in a delicate tip-toe right up to the edge of the cliff.

  Deadlocks. This one needs no explanation.

Re: Discovering a JDK Race Condition, and Debugging It in 30 Minutes with Fray

#49
post #48
post #47

Earlier quoted context omitted.

In Java, racing a field is safe - you can only ever observe the value as one that was explicitly set by a thread, no tearing can happen. Safe data races can happen in Java, but you sometimes do want that (e.g. efficient concurrent algorithms), and avoiding it is not particularly hard (synchronized blocks are not the state of the art, but does make it easy to solve a problem). Pony and Rust are both very interesting l…

> avoiding it is not particularly hard (synchronized blocks are not the state of the art, but does make it easy to solve a problem). Please have a read of https://joeduffyblog.com/2010/01/03/a-brief-retrospective-on... (and don't just skim it.) (This was not written by some nobody, he does know what he talks about.) Contrast this elegant simplicity with the many pitfalls of locks: Data races. Like forgetting to hold…

Nice "gotcha".

But STM doesn't solve e.g. deadlocks - there are automatisms that can detect them and choose a different retry mechanism to deal with them (see the linked article), but my general point you really want to ignore is that none of these are silver bullets.

Concurrency is hard.

Re: Discovering a JDK Race Condition, and Debugging It in 30 Minutes with Fray

#50
This actually intersects with two of my current interests. We have, in production, rarely been seeing ThreadPoolExecutor hangs (JDK17) during shutdown. After a lot of debugging, I've been suspecting more and more that it may be an actual JDK issue. But, this type of issue is extremely hard to reason about in production, and I've never successfully reproduced it locally. (It's not clear to me that it's the same issue as in the post, since it's not a scheduled executor.)

Separately, we're looking at using fray for concurrency property testing, as a way to reliably catch concurrency issues in a distributed system by simulating it within a single JVM.

Post reply on HN