4 ms·
In 2022 a POSIX OS with a broken pthread_cond_t implementation is a broken OS, full stop. This is the POSIX API for implementing sleeping synchronization mecha
by pengaru 4y ago
In 2022 a POSIX OS with a broken pthread_cond_t implementation is a broken OS, full stop. This is the POSIX API for implementing sleeping synchronization mechanisms in threaded programs.
The glibc project should be incredibly embarrassed by this, assuming there's anyone even still paying attention there.
- nix23 4y agoWell it's gnu/linux, a multiuser unix that is not usable as a multiuser system (read the sdf.org story). It's a cheap hw-framework to run more or less reliable...but no problem we have kubernetes and containers to cover/perfume the stinking parts.
- Jasper_ 4y agoIsn't a semaphore usually a better choice than a condition variable / event, because you can still race if you try and wake the condition variable multiple times? e.g. https://devblogs.microsoft.com/oldnewthing/20060622-00/?p=30773 https://devblogs.microsoft.com/oldnewthing/20060622-00/?p=30... Why pthreads included condition variables but not semaphores, I don't know. Maybe because POSIX already had them?
- pengaru 4y agoNot sure I follow, there are semaphores (sem_init(3)) and you get them via -pthread on my glibc system. These are the semaphores I'm familiar with, which are plain counting semaphores you can also implement trivially using condition variables. The condition variable is a lower-level concept which pairs an OS-level signaling object and a mutex, it places no limits on what the condition may be, unlike a counting semaphore. Personally I find it more odd that they'd bother with sem_t when they already have pthread_cond_t. Perhaps there's an optimization opportunity in sem_t when the condition is specialized to involving just an integer counter, justifying the specialized interface? WRT waking the condition variable multiple times, properly handling spurious wakeups is kind of central to the proper use of them. That's why the condition test is always part of a loop, e.g.: pthread_mutex_lock(&lock); while (!condition_satisfied(shared_state)) pthread_cond_wait(&cond, &lock); { do things with condition satisfied and lock held } I always found condition variables to be nicely composable and ergonomic when writing pthread programs in C. But they come up short when you start wanting a file descriptor event to trigger the condition wakeup. In that case you end up doing silly things like spawning a thread just for the purpose of monitoring for fd events and turning them into a pthread_cond_signal() on the appropriate pthread_cond_t. AIUI the Windows WaitForMultipleObjects() interface does this better, so I hear, but I've never really dealt with Windows.
- Jasper_ 4y agoWaitForMultipleObjects is closer to a version of poll, that can also work on condition variables. I wish Linux had a WaitForMultipleObjects equivalent, eventfd is really not it.
- gpderetta 4y agoBut WFMO can't wait on CONDITION_VARIABLE on windows either. It can wait on events whose linux equivalent is eventfd. Unfortunately it is hard to implement select/wfmo for fast-pathed edge triggred primitives because of the race that can cause lost wakeups. Futex had a futexfd feature for polling but it was impossible to use correctly and was removed.
- comex 4y agoPOSIX semaphores were created as part of the older 'real-time extensions' aka POSIX.1b, whereas the pthread API was created slightly later as POSIX.1c. (Source: man pages, plus [1] for a list of standards.) [1] https://man7.org/linux/man-pages/man7/standards.7.html https://man7.org/linux/man-pages/man7/standards.7.html
- comex 4y agoWhether it's a justified choice or not, for whatever reason, POSIX semaphores are very rarely used. macOS does not even support them (except for the named ones used for IPC). So pthread_cond_t is certainly 'the' API in terms of actual usage. (Personally, I like events, but sometimes I want ones that don't reset - as in, the event is only ever flipped once in its lifetime, from "not ready" to "ready", but any number of consumers can check if it's ready or wait for it to be ready. These can't be directly implemented with POSIX semaphores. But then, I didn't know until just now that fast POSIX semaphore implementations even existed – there's my Apple bias.)
- Jasper_ 4y agoWe use POSIX semaphores in our engine. macOS has their own semaphores in libdispatch
- gpderetta 4y agoCond vars are fiendishly hard to implement correctly. Demanding an implementation to be bug free, fully featured and scale on a variety of loads is ridiculous.
- pengaru 4y ago> Cond vars are fiendishly hard to implement correctly. Demanding an implementation to be bug free, fully featured and scale on a variety of loads is ridiculous. No. What's ridiculous is neglecting to fix a known correctness bug in a core synchronization primitive causing random deadlocks for over two years.
- gpderetta 4y agoIf you think it is easy to fix, I'm sure the glibc maintainers will accept a patch from you, because OP patch breaks other software.
- pengaru 4y agoThey don't need a patch from me, they need the will to DTRT and at least revert the commit [0] that broke things. Glibc has had a functioning pthread_cond_t that didn't randomly deadlock/lose wakeups, this isn't some impossible to implement feature. That commit claims to fix ordering guarantees required by the clarified spec, but in doing so has introduced real deadlock bugs. The linked discussion at [1] is telling. It seems glibc's nptl is prioritizing playing games with optimizations over correctness, even before [0] landed. To suggest all that's required is someone showing up with a patch is to completely ignore the fact that there's zero shortage of correct pthread_cond_t implementations all over the place. This is a maintenance failure, not a lack of code. [0] https://github.com/bminor/glibc/commit/ed19993b5b0d05d62cc883571519a67dae481a14 https://github.com/bminor/glibc/commit/ed19993b5b0d05d62cc88... [1] https://austingroupbugs.net/view.php?id=609 https://austingroupbugs.net/view.php?id=609
- gpderetta 4y agoReverting that commit will break other stuff that depends on the posix behavior, not sure how's that better. I also very much do not think that there are plenty of correct pthread_cond_t, far from it. It is possible that the musl one might be close to drop in replacement (although IIRC, musl at some point had a different thread cancellation implementation than glibc).