LibreOffice Module vcl (master) 1
watchdog.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
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 */
9
10#include <watchdog.hxx>
11
12#include <config_features.h>
13
14#include <osl/conditn.hxx>
15#include <rtl/ref.hxx>
16#include <rtl/string.hxx>
17#include <sal/log.hxx>
19#include <opengl/zone.hxx>
20#include <skia/zone.hxx>
21
22#include <stdlib.h>
23
24#if defined HAVE_VALGRIND_HEADERS
25#include <valgrind/memcheck.h>
26#endif
27
28namespace
29{
30volatile bool gbWatchdogFiring = false;
31osl::Condition* gpWatchdogExit = nullptr;
33
34template <typename Zone> struct WatchdogHelper
35{
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()
42 {
43 if (Zone::isInZone())
44 {
45 const CrashWatchdogTimingsValues& aTimingValues = Zone::getCrashWatchdogTimingsValues();
46
47 if (nLastEnters == Zone::enterCount())
48 nUnchanged++;
49 else
50 nUnchanged = 0;
51 Zone::checkDebug(nUnchanged, aTimingValues);
52
53 // Not making progress
54 if (nUnchanged >= aTimingValues.mnDisableEntries)
55 {
56 if (!bFired)
57 {
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
66 }
67 bFired = true;
68
69 // we can hang using VCL in the abort handling -> be impatient
70 if (bAbortFired)
71 {
72 SAL_WARN("vcl.watchdog", "Watchdog gave up: hard exiting " << Zone::name());
73 _Exit(1);
74 }
75 }
76
77 // Not making even more progress
78 if (nUnchanged >= aTimingValues.mnAbortAfter)
79 {
80 if (!bAbortFired)
81 {
82 SAL_WARN("vcl.watchdog", "Watchdog gave up: aborting " << Zone::name());
83 gbWatchdogFiring = true;
84 std::abort();
85 }
86 // coverity[dead_error_line] - we might have caught SIGABRT and failed to exit yet
87 bAbortFired = true;
88 }
89 }
90 else
91 {
92 nUnchanged = 0;
93 }
94 }
95};
96
97} // namespace
98
100 : salhelper::Thread("Crash Watchdog")
101{
102}
103
105{
106 TimeValue aQuarterSecond(0, 1000 * 1000 * 1000 * 0.25);
107 do
108 {
109#if HAVE_FEATURE_OPENGL
110 WatchdogHelper<OpenGLZone>::setLastEnters();
111#endif
112#if HAVE_FEATURE_SKIA
113 WatchdogHelper<SkiaZone>::setLastEnters();
114#endif
115
116 gpWatchdogExit->wait(&aQuarterSecond);
117
118#if defined HAVE_VALGRIND_HEADERS
119 if (RUNNING_ON_VALGRIND)
120 continue;
121#endif
122#if defined DBG_UTIL
124 continue;
125#endif
126
127#if HAVE_FEATURE_OPENGL
128 WatchdogHelper<OpenGLZone>::check();
129#endif
130#if HAVE_FEATURE_SKIA
131 WatchdogHelper<SkiaZone>::check();
132#endif
133
134 } while (!gpWatchdogExit->check());
135}
136
138{
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();
146}
147
149{
150 if (gbWatchdogFiring)
151 return; // in watchdog thread
152
153 if (gpWatchdogExit)
154 gpWatchdogExit->set();
155
156 if (gxWatchdog.is())
157 {
158 gxWatchdog->join();
159 gxWatchdog.clear();
160 }
161
162 delete gpWatchdogExit;
163 gpWatchdogExit = nullptr;
164}
165
166/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
virtual void execute() override
Definition: watchdog.cxx:104
static void start()
Definition: watchdog.cxx:137
static void stop()
Definition: watchdog.cxx:148
#define SAL_WARN(area, stream)
bool isDebuggerAttached()
DESKTOP_DEPLOYMENTMISC_DLLPUBLIC css::uno::Sequence< css::uno::Reference< css::xml::dom::XElement > > check(dp_misc::DescriptionInfoset const &infoset)