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>
30 volatile bool gbWatchdogFiring
= false;
31 osl::Condition
* gpWatchdogExit
= nullptr;
32 rtl::Reference
<WatchdogThread
> gxWatchdog
;
34 template <typename Zone
> struct WatchdogHelper
36 static inline sal_uInt64 nLastEnters
= 0;
37 static inline int nUnchanged
= 0; // how many unchanged nEnters
38 static inline bool bFired
= false;
39 static inline bool bAbortFired
= false;
40 static void setLastEnters() { nLastEnters
= Zone::enterCount(); }
45 const CrashWatchdogTimingsValues
& aTimingValues
= Zone::getCrashWatchdogTimingsValues();
47 if (nLastEnters
== Zone::enterCount())
51 Zone::checkDebug(nUnchanged
, aTimingValues
);
53 // Not making progress
54 if (nUnchanged
>= aTimingValues
.mnDisableEntries
)
58 gbWatchdogFiring
= true;
59 SAL_WARN("vcl.watchdog", "Watchdog triggered: hard disable " << Zone::name());
64 gbWatchdogFiring
= false;
69 // we can hang using VCL in the abort handling -> be impatient
72 SAL_WARN("vcl.watchdog", "Watchdog gave up: hard exiting " << Zone::name());
77 // Not making even more progress
78 if (nUnchanged
>= aTimingValues
.mnAbortAfter
)
82 SAL_WARN("vcl.watchdog", "Watchdog gave up: aborting " << Zone::name());
83 gbWatchdogFiring
= true;
86 // coverity[dead_error_line] - we might have caught SIGABRT and failed to exit yet
99 WatchdogThread::WatchdogThread()
100 : salhelper::Thread("Crash Watchdog")
104 void WatchdogThread::execute()
106 TimeValue
aQuarterSecond(0, 1000 * 1000 * 1000 * 0.25);
109 #if HAVE_FEATURE_OPENGL
110 WatchdogHelper
<OpenGLZone
>::setLastEnters();
112 #if HAVE_FEATURE_SKIA
113 WatchdogHelper
<SkiaZone
>::setLastEnters();
116 gpWatchdogExit
->wait(&aQuarterSecond
);
118 #if defined HAVE_VALGRIND_HEADERS
119 if (RUNNING_ON_VALGRIND
)
123 if (comphelper::isDebuggerAttached())
127 #if HAVE_FEATURE_OPENGL
128 WatchdogHelper
<OpenGLZone
>::check();
130 #if HAVE_FEATURE_SKIA
131 WatchdogHelper
<SkiaZone
>::check();
134 } while (!gpWatchdogExit
->check());
137 void WatchdogThread::start()
139 if (gxWatchdog
!= nullptr)
140 return; // already running
141 if (getenv("SAL_DISABLE_WATCHDOG"))
143 gpWatchdogExit
= new osl::Condition();
144 gxWatchdog
.set(new WatchdogThread());
145 gxWatchdog
->launch();
148 void WatchdogThread::stop()
150 if (gbWatchdogFiring
)
151 return; // in watchdog thread
154 gpWatchdogExit
->set();
162 delete gpWatchdogExit
;
163 gpWatchdogExit
= nullptr;
166 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */