mirror of
https://github.com/hyprwm/Hyprland
synced 2024-11-26 08:05:58 +01:00
internal: add a watchdog
a watchdog will abort processing a signal if a timeout specified via debug:watchdog_timeout is reached.
This commit is contained in:
parent
3f09b14381
commit
9cc614d096
6 changed files with 99 additions and 1 deletions
|
@ -34,6 +34,13 @@ void handleUnrecoverableSignal(int sig) {
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void handleUserSignal(int sig) {
|
||||||
|
if (sig == SIGUSR1) {
|
||||||
|
// means we have to unwind a timed out event
|
||||||
|
throw std::exception();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
CCompositor::CCompositor() {
|
CCompositor::CCompositor() {
|
||||||
m_iHyprlandPID = getpid();
|
m_iHyprlandPID = getpid();
|
||||||
|
|
||||||
|
@ -70,6 +77,8 @@ CCompositor::CCompositor() {
|
||||||
setRandomSplash();
|
setRandomSplash();
|
||||||
|
|
||||||
Debug::log(LOG, "\nCurrent splash: {}\n\n", m_szCurrentSplash);
|
Debug::log(LOG, "\nCurrent splash: {}\n\n", m_szCurrentSplash);
|
||||||
|
|
||||||
|
g_pWatchdog = std::make_unique<CWatchdog>();
|
||||||
}
|
}
|
||||||
|
|
||||||
CCompositor::~CCompositor() {
|
CCompositor::~CCompositor() {
|
||||||
|
@ -92,6 +101,7 @@ CCompositor::~CCompositor() {
|
||||||
g_pAnimationManager.reset();
|
g_pAnimationManager.reset();
|
||||||
g_pKeybindManager.reset();
|
g_pKeybindManager.reset();
|
||||||
g_pHookSystem.reset();
|
g_pHookSystem.reset();
|
||||||
|
g_pWatchdog.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CCompositor::setRandomSplash() {
|
void CCompositor::setRandomSplash() {
|
||||||
|
@ -112,6 +122,7 @@ void CCompositor::initServer() {
|
||||||
wl_event_loop_add_signal(m_sWLEventLoop, SIGTERM, handleCritSignal, nullptr);
|
wl_event_loop_add_signal(m_sWLEventLoop, SIGTERM, handleCritSignal, nullptr);
|
||||||
signal(SIGSEGV, handleUnrecoverableSignal);
|
signal(SIGSEGV, handleUnrecoverableSignal);
|
||||||
signal(SIGABRT, handleUnrecoverableSignal);
|
signal(SIGABRT, handleUnrecoverableSignal);
|
||||||
|
signal(SIGUSR1, handleUserSignal);
|
||||||
//wl_event_loop_add_signal(m_sWLEventLoop, SIGINT, handleCritSignal, nullptr);
|
//wl_event_loop_add_signal(m_sWLEventLoop, SIGINT, handleCritSignal, nullptr);
|
||||||
|
|
||||||
initManagers(STAGE_PRIORITY);
|
initManagers(STAGE_PRIORITY);
|
||||||
|
|
|
@ -27,6 +27,7 @@
|
||||||
#include "render/OpenGL.hpp"
|
#include "render/OpenGL.hpp"
|
||||||
#include "hyprerror/HyprError.hpp"
|
#include "hyprerror/HyprError.hpp"
|
||||||
#include "plugins/PluginSystem.hpp"
|
#include "plugins/PluginSystem.hpp"
|
||||||
|
#include "helpers/Watchdog.hpp"
|
||||||
|
|
||||||
enum eManagersInitStage
|
enum eManagersInitStage
|
||||||
{
|
{
|
||||||
|
|
|
@ -134,6 +134,7 @@ void CConfigManager::setDefaultVars() {
|
||||||
configValues["debug:damage_tracking"].intValue = DAMAGE_TRACKING_FULL;
|
configValues["debug:damage_tracking"].intValue = DAMAGE_TRACKING_FULL;
|
||||||
configValues["debug:manual_crash"].intValue = 0;
|
configValues["debug:manual_crash"].intValue = 0;
|
||||||
configValues["debug:suppress_errors"].intValue = 0;
|
configValues["debug:suppress_errors"].intValue = 0;
|
||||||
|
configValues["debug:watchdog_timeout"].intValue = 5;
|
||||||
|
|
||||||
configValues["decoration:rounding"].intValue = 0;
|
configValues["decoration:rounding"].intValue = 0;
|
||||||
configValues["decoration:blur:enabled"].intValue = 1;
|
configValues["decoration:blur:enabled"].intValue = 1;
|
||||||
|
|
|
@ -6,7 +6,13 @@
|
||||||
void handleWrapped(wl_listener* listener, void* data) {
|
void handleWrapped(wl_listener* listener, void* data) {
|
||||||
CHyprWLListener::SWrapper* pWrap = wl_container_of(listener, pWrap, m_sListener);
|
CHyprWLListener::SWrapper* pWrap = wl_container_of(listener, pWrap, m_sListener);
|
||||||
|
|
||||||
pWrap->m_pSelf->emit(data);
|
g_pWatchdog->startWatching();
|
||||||
|
|
||||||
|
try {
|
||||||
|
pWrap->m_pSelf->emit(data);
|
||||||
|
} catch (std::exception& e) { Debug::log(ERR, "Listener {} timed out and was killed by Watchdog!!!", (uintptr_t)listener); }
|
||||||
|
|
||||||
|
g_pWatchdog->endWatching();
|
||||||
}
|
}
|
||||||
|
|
||||||
CHyprWLListener::CHyprWLListener(wl_signal* pSignal, std::function<void(void*, void*)> callback, void* pOwner) {
|
CHyprWLListener::CHyprWLListener(wl_signal* pSignal, std::function<void(void*, void*)> callback, void* pOwner) {
|
||||||
|
|
49
src/helpers/Watchdog.cpp
Normal file
49
src/helpers/Watchdog.cpp
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
#include "Watchdog.hpp"
|
||||||
|
#include <signal.h>
|
||||||
|
#include "config/ConfigManager.hpp"
|
||||||
|
|
||||||
|
CWatchdog::CWatchdog() {
|
||||||
|
m_iMainThreadPID = pthread_self();
|
||||||
|
|
||||||
|
m_pWatchdog = std::make_unique<std::thread>([this] {
|
||||||
|
static auto* const PTIMEOUT = &g_pConfigManager->getConfigValuePtr("debug:watchdog_timeout")->intValue;
|
||||||
|
|
||||||
|
while (1337) {
|
||||||
|
std::unique_lock lk(m_mWatchdogMutex);
|
||||||
|
|
||||||
|
if (!m_bWillWatch)
|
||||||
|
m_cvWatchdogCondition.wait(lk, [this] { return m_bNotified; });
|
||||||
|
else {
|
||||||
|
if (m_cvWatchdogCondition.wait_for(lk, std::chrono::milliseconds((int)(*PTIMEOUT * 1000.0)), [this] { return m_bNotified; }) == false)
|
||||||
|
pthread_kill(m_iMainThreadPID, SIGUSR1);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_bWatching = false;
|
||||||
|
m_bNotified = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
m_pWatchdog->detach();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CWatchdog::startWatching() {
|
||||||
|
static auto* const PTIMEOUT = &g_pConfigManager->getConfigValuePtr("debug:watchdog_timeout")->intValue;
|
||||||
|
|
||||||
|
if (*PTIMEOUT == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_tTriggered = std::chrono::high_resolution_clock::now();
|
||||||
|
m_bWillWatch = true;
|
||||||
|
m_bWatching = true;
|
||||||
|
|
||||||
|
m_bNotified = true;
|
||||||
|
m_cvWatchdogCondition.notify_all();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CWatchdog::endWatching() {
|
||||||
|
m_bWatching = false;
|
||||||
|
m_bWillWatch = false;
|
||||||
|
|
||||||
|
m_bNotified = true;
|
||||||
|
m_cvWatchdogCondition.notify_all();
|
||||||
|
}
|
30
src/helpers/Watchdog.hpp
Normal file
30
src/helpers/Watchdog.hpp
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include <chrono>
|
||||||
|
#include <thread>
|
||||||
|
#include <condition_variable>
|
||||||
|
|
||||||
|
class CWatchdog {
|
||||||
|
public:
|
||||||
|
// must be called from the main thread
|
||||||
|
CWatchdog();
|
||||||
|
|
||||||
|
void startWatching();
|
||||||
|
void endWatching();
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::chrono::high_resolution_clock::time_point m_tTriggered;
|
||||||
|
|
||||||
|
pthread_t m_iMainThreadPID = 0;
|
||||||
|
|
||||||
|
bool m_bWatching = false;
|
||||||
|
bool m_bWillWatch = false;
|
||||||
|
|
||||||
|
std::unique_ptr<std::thread> m_pWatchdog;
|
||||||
|
std::mutex m_mWatchdogMutex;
|
||||||
|
bool m_bNotified = false;
|
||||||
|
std::condition_variable m_cvWatchdogCondition;
|
||||||
|
};
|
||||||
|
|
||||||
|
inline std::unique_ptr<CWatchdog> g_pWatchdog;
|
Loading…
Reference in a new issue