1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
10 #include <watchdog.hxx>
12 #include <config_features.h>
14 #include <osl/conditn.hxx>
15 #include <rtl/ref.hxx>
16 #include <rtl/string.hxx>
17 #include <sal/log.hxx>
18 #include <comphelper/debuggerinfo.hxx>
19 #include <opengl/zone.hxx>
20 #include <skia/zone.hxx>
24 #if defined HAVE_VALGRIND_HEADERS
25 #include <valgrind/memcheck.h>
32 std::atomic
<bool> gbWatchdogFiring
= false;
33 osl::Condition
* gpWatchdogExit
= nullptr;
34 rtl::Reference
<WatchdogThread
> gxWatchdog
;
36 template <typename Zone
> struct WatchdogHelper
38 static inline sal_uInt64 nLastEnters
= 0;
39 static inline int nUnchanged
= 0; // how many unchanged nEnters
40 static inline bool bFired
= false;
41 static inline bool bAbortFired
= false;
42 static void setLastEnters() { nLastEnters
= Zone::enterCount(); }
47 const CrashWatchdogTimingsValues
& aTimingValues
= Zone::getCrashWatchdogTimingsValues();
49 if (nLastEnters
== Zone::enterCount())
53 Zone::checkDebug(nUnchanged
, aTimingValues
);
55 // Not making progress
56 if (nUnchanged
>= aTimingValues
.mnDisableEntries
)
60 gbWatchdogFiring
= true;
61 SAL_WARN("vcl.watchdog", "Watchdog triggered: hard disable " << Zone::name());
66 gbWatchdogFiring
= false;
71 // we can hang using VCL in the abort handling -> be impatient
74 SAL_WARN("vcl.watchdog", "Watchdog gave up: hard exiting " << Zone::name());
79 // Not making even more progress
80 if (nUnchanged
>= aTimingValues
.mnAbortAfter
)
84 SAL_WARN("vcl.watchdog", "Watchdog gave up: aborting " << Zone::name());
85 gbWatchdogFiring
= true;
88 // coverity[dead_error_line] - we might have caught SIGABRT and failed to exit yet
101 WatchdogThread::WatchdogThread()
102 : salhelper::Thread("Crash Watchdog")
106 void WatchdogThread::execute()
108 TimeValue
aQuarterSecond(0, 1000 * 1000 * 1000 * 0.25);
111 #if HAVE_FEATURE_OPENGL
112 WatchdogHelper
<OpenGLZone
>::setLastEnters();
114 #if HAVE_FEATURE_SKIA
115 WatchdogHelper
<SkiaZone
>::setLastEnters();
118 gpWatchdogExit
->wait(&aQuarterSecond
);
120 #if defined HAVE_VALGRIND_HEADERS
121 if (RUNNING_ON_VALGRIND
)
125 if (comphelper::isDebuggerAttached())
129 #if HAVE_FEATURE_OPENGL
130 WatchdogHelper
<OpenGLZone
>::check();
132 #if HAVE_FEATURE_SKIA
133 WatchdogHelper
<SkiaZone
>::check();
136 } while (!gpWatchdogExit
->check());
139 void WatchdogThread::start()
141 if (gxWatchdog
!= nullptr)
142 return; // already running
143 if (getenv("SAL_DISABLE_WATCHDOG"))
145 gpWatchdogExit
= new osl::Condition();
146 gxWatchdog
.set(new WatchdogThread());
147 gxWatchdog
->launch();
150 void WatchdogThread::stop()
152 if (gbWatchdogFiring
)
153 return; // in watchdog thread
156 gpWatchdogExit
->set();
164 delete gpWatchdogExit
;
165 gpWatchdogExit
= nullptr;
168 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */