bump product version to 7.6.3.2-android
[LibreOffice.git] / vcl / source / app / watchdog.cxx
blobb14611e227caafc96dd1d20bfdb419dee5308cad
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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/.
8 */
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>
22 #include <stdlib.h>
24 #if defined HAVE_VALGRIND_HEADERS
25 #include <valgrind/memcheck.h>
26 #endif
28 namespace
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(); }
41 static void check()
43 if (Zone::isInZone())
45 const CrashWatchdogTimingsValues& aTimingValues = Zone::getCrashWatchdogTimingsValues();
47 if (nLastEnters == Zone::enterCount())
48 nUnchanged++;
49 else
50 nUnchanged = 0;
51 Zone::checkDebug(nUnchanged, aTimingValues);
53 // Not making progress
54 if (nUnchanged >= aTimingValues.mnDisableEntries)
56 if (!bFired)
58 gbWatchdogFiring = true;
59 SAL_WARN("vcl.watchdog", "Watchdog triggered: hard disable " << Zone::name());
60 #ifdef DBG_UTIL
61 std::abort();
62 #else
63 Zone::hardDisable();
64 gbWatchdogFiring = false;
65 #endif
67 bFired = true;
69 // we can hang using VCL in the abort handling -> be impatient
70 if (bAbortFired)
72 SAL_WARN("vcl.watchdog", "Watchdog gave up: hard exiting " << Zone::name());
73 _Exit(1);
77 // Not making even more progress
78 if (nUnchanged >= aTimingValues.mnAbortAfter)
80 if (!bAbortFired)
82 SAL_WARN("vcl.watchdog", "Watchdog gave up: aborting " << Zone::name());
83 gbWatchdogFiring = true;
84 std::abort();
86 // coverity[dead_error_line] - we might have caught SIGABRT and failed to exit yet
87 bAbortFired = true;
90 else
92 nUnchanged = 0;
97 } // namespace
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();
111 #endif
112 #if HAVE_FEATURE_SKIA
113 WatchdogHelper<SkiaZone>::setLastEnters();
114 #endif
116 gpWatchdogExit->wait(&aQuarterSecond);
118 #if defined HAVE_VALGRIND_HEADERS
119 if (RUNNING_ON_VALGRIND)
120 continue;
121 #endif
122 #if defined DBG_UTIL
123 if (comphelper::isDebuggerAttached())
124 continue;
125 #endif
127 #if HAVE_FEATURE_OPENGL
128 WatchdogHelper<OpenGLZone>::check();
129 #endif
130 #if HAVE_FEATURE_SKIA
131 WatchdogHelper<SkiaZone>::check();
132 #endif
134 } while (!gpWatchdogExit->check());
137 void WatchdogThread::start()
139 if (gxWatchdog != nullptr)
140 return; // already running
141 if (getenv("SAL_DISABLE_WATCHDOG"))
142 return;
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
153 if (gpWatchdogExit)
154 gpWatchdogExit->set();
156 if (gxWatchdog.is())
158 gxWatchdog->join();
159 gxWatchdog.clear();
162 delete gpWatchdogExit;
163 gpWatchdogExit = nullptr;
166 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */