mirror of
https://github.com/rad4day/Waybar.git
synced 2023-12-21 10:22:59 +01:00
fix(util): protect std::condition_variable methods from pthread_cancel
The changes in GCC 11.x made `std::condition_variable` implementation internals `noexcept`. `noexcept` is known to interact particularly bad with `pthread_cancel`, i.e. `__cxxabiv1::__force_unwind` passing through the `noexcept` call stack frame causes a `std::terminate` call and immediate termination of the program Digging through the GCC ML archives[1] lead me to the idea of patching this with a few pthread_setcancelstate's. As bad as the solution is, it seems to be the best we can do within C++17 limits and without major rework. [1]: https://gcc.gnu.org/legacy-ml/gcc/2017-08/msg00156.html
This commit is contained in:
parent
20160749e7
commit
5da268077c
@ -8,6 +8,20 @@
|
||||
|
||||
namespace waybar::util {
|
||||
|
||||
/**
|
||||
* Defer pthread_cancel until the end of a current scope.
|
||||
*
|
||||
* Required to protect a scope where it's unsafe to raise `__forced_unwind` exception.
|
||||
* An example of these is a call of a method marked as `noexcept`; an attempt to cancel within such
|
||||
* a method may result in a `std::terminate` call.
|
||||
*/
|
||||
class CancellationGuard {
|
||||
int oldstate;
|
||||
public:
|
||||
CancellationGuard() { pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &oldstate); }
|
||||
~CancellationGuard() { pthread_setcancelstate(oldstate, &oldstate); }
|
||||
};
|
||||
|
||||
class SleeperThread {
|
||||
public:
|
||||
SleeperThread() = default;
|
||||
@ -33,14 +47,16 @@ class SleeperThread {
|
||||
bool isRunning() const { return do_run_; }
|
||||
|
||||
auto sleep_for(std::chrono::system_clock::duration dur) {
|
||||
std::unique_lock lk(mutex_);
|
||||
std::unique_lock lk(mutex_);
|
||||
CancellationGuard cancel_lock;
|
||||
return condvar_.wait_for(lk, dur, [this] { return signal_ || !do_run_; });
|
||||
}
|
||||
|
||||
auto sleep_until(
|
||||
std::chrono::time_point<std::chrono::system_clock, std::chrono::system_clock::duration>
|
||||
time_point) {
|
||||
std::unique_lock lk(mutex_);
|
||||
std::unique_lock lk(mutex_);
|
||||
CancellationGuard cancel_lock;
|
||||
return condvar_.wait_until(lk, time_point, [this] { return signal_ || !do_run_; });
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user