mirror of
				https://github.com/rad4day/Waybar.git
				synced 2025-10-24 22:52:32 +02: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:
		| @@ -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_; }); | ||||
|   } | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Aleksei Bavshin
					Aleksei Bavshin