summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xdesktop/scripts/soffice.sh2
-rw-r--r--desktop/source/app/opencl.cxx2
-rw-r--r--include/comphelper/crashzone.hxx72
-rw-r--r--include/opencl/OpenCLZone.hxx42
-rw-r--r--include/sal/log-areas.dox1
-rw-r--r--opencl/source/OpenCLZone.cxx10
-rw-r--r--vcl/Library_vcl.mk1
-rw-r--r--vcl/README.vars2
-rw-r--r--vcl/inc/opengl/watchdog.hxx67
-rw-r--r--vcl/inc/opengl/zone.hxx39
-rw-r--r--vcl/inc/watchdog.hxx32
-rw-r--r--vcl/source/app/svmain.cxx8
-rw-r--r--vcl/source/app/watchdog.cxx144
-rw-r--r--vcl/source/opengl/OpenGLHelper.cxx160
14 files changed, 318 insertions, 264 deletions
diff --git a/desktop/scripts/soffice.sh b/desktop/scripts/soffice.sh
index 415ea047361d..5538c968ee18 100755
--- a/desktop/scripts/soffice.sh
+++ b/desktop/scripts/soffice.sh
@@ -130,7 +130,7 @@ for arg in "$@" $EXTRAOPT ; do
unset MALLOC_CHECK_ MALLOC_PERTURB_ G_SLICE
export SAL_DISABLE_FLOATGRAB=1
export OOO_DISABLE_RECOVERY=1
- export SAL_DISABLE_GL_WATCHDOG=1
+ export SAL_DISABLE_WATCHDOG=1
export LD_BIND_NOW=1
;;
esac
diff --git a/desktop/source/app/opencl.cxx b/desktop/source/app/opencl.cxx
index 4cbea032a15c..a1fe3c0f6aea 100644
--- a/desktop/source/app/opencl.cxx
+++ b/desktop/source/app/opencl.cxx
@@ -193,7 +193,7 @@ void Desktop::CheckOpenCLCompute(const Reference< XDesktop2 > &xDesktop)
SAL_INFO("opencl", "Initiating test of OpenCL device");
OpenCLZone aZone;
- OpenCLZone::enterInitialTest();
+ OpenCLInitialZone aInitialZone;
OUString aDevice = officecfg::Office::Calc::Formula::Calculation::OpenCLDevice::get();
OUString aSelectedCLDeviceVersionID;
diff --git a/include/comphelper/crashzone.hxx b/include/comphelper/crashzone.hxx
new file mode 100644
index 000000000000..6cbbe718f8a4
--- /dev/null
+++ b/include/comphelper/crashzone.hxx
@@ -0,0 +1,72 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef INCLUDED_COMPHELPER_CRASHZONE_H
+#define INCLUDED_COMPHELPER_CRASHZONE_H
+
+#include <sal/config.h>
+#include <sal/types.h>
+#include <comphelper/comphelperdllapi.h>
+
+#include <atomic>
+#include <csignal>
+#include <type_traits>
+
+struct CrashWatchdogTimingsValues
+{
+ /// delays to take various actions in 1/4 of a second increments.
+ int mnDisableEntries;
+ int const mnAbortAfter;
+};
+
+/**
+ * A generic class for detecting if a given crash or a lock-up came from a specific
+ * area of code (such as OpenGL).
+ * Use this helper to track that.
+ * The class is a template so that there can be multiple instances of static variables.
+ */
+template <typename Dummy> class CrashZone
+{
+// gnEnterCount and gnLeaveCount are accessed both from multiple threads (cf.
+// WatchdogThread::execute; so need to be of atomic type) and from signal handlers (cf.
+// VCLExceptionSignal_impl; so need to be of lock-free atomic type). sig_atomic_t is chosen as
+// the underlying type under the assumption that it is most likely to lead to an atomic type
+// that is actually lock-free. However, gnEnterCount and gnLeaveCount are both monotonically
+// increasing, so will eventually overflow, so the underlying type better be unsigned, which
+// sig_atomic_t is not guaranteed to be:
+#if !defined ARM32 || (defined ARM32 && defined __ARM_PCS_VFP)
+ using AtomicCounter = std::atomic<std::make_unsigned_t<std::sig_atomic_t>>;
+ static_assert(AtomicCounter::is_always_lock_free);
+#else
+ using AtomicCounter = volatile std::make_unsigned_t<std::sig_atomic_t>;
+#endif
+
+ /// how many times have we entered a zone
+ static inline AtomicCounter gnEnterCount = 0;
+ /// how many times have we left a new zone
+ static inline AtomicCounter gnLeaveCount = 0;
+
+public:
+ CrashZone() { enter(); }
+ ~CrashZone() { leave(); }
+ static bool isInZone() { return gnEnterCount != gnLeaveCount; }
+ static const AtomicCounter& enterCount() { return gnEnterCount; }
+ // prefer creating instances to manually calling enter()/leave()
+ static void enter() { gnEnterCount++; }
+ static void leave() { gnLeaveCount++; }
+ // these should be implemented for each specific zone if needed
+ // static void hardDisable();
+ // static const CrashWatchdogTimingsValues& getCrashWatchdogTimingsValues();
+ // static void checkDebug(int nUnchanged, const CrashWatchdogTimingsValues& aTimingValues);
+ // static const char* name();
+};
+
+#endif // INCLUDED_COMPHELPER_CRASHZONE_H
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/include/opencl/OpenCLZone.hxx b/include/opencl/OpenCLZone.hxx
index 50d0f81c3191..1bbf3a46161c 100644
--- a/include/opencl/OpenCLZone.hxx
+++ b/include/opencl/OpenCLZone.hxx
@@ -12,45 +12,19 @@
#include <sal/config.h>
-#include <cassert>
-#include <csignal>
-
#include <opencl/opencldllapi.h>
-// FIXME: post back-port, templatize me and share with OpenGLZone.
-class OPENCL_DLLPUBLIC OpenCLZone
-{
- /// how many times have we entered a CL zone and not yet left it
- static volatile std::sig_atomic_t gnEnterCount;
- static volatile bool gbInInitialTest;
+#include <comphelper/crashzone.hxx>
+class OPENCL_DLLPUBLIC OpenCLZone : public CrashZone< OpenCLZone >
+{
public:
- OpenCLZone()
- {
- gnEnterCount = gnEnterCount + 1; //TODO: overflow
- }
-
- ~OpenCLZone()
- {
- // coverity[assert_side_effect]
- assert(gnEnterCount > 0);
- gnEnterCount = gnEnterCount - 1;
- if (!isInZone())
- gbInInitialTest = false;
- }
-
- static bool isInZone()
- {
- return gnEnterCount > 0;
- }
-
- static bool isInInitialTest()
- {
- return gbInInitialTest;
- }
-
static void hardDisable();
- static void enterInitialTest();
+};
+
+// Used during initial testing of OpenCL.
+class OPENCL_DLLPUBLIC OpenCLInitialZone : public CrashZone< OpenCLInitialZone >
+{
};
#endif // INCLUDED_OPENCL_INC_OPENCL_ZONE_HXX
diff --git a/include/sal/log-areas.dox b/include/sal/log-areas.dox
index ce0fa239b292..3ebe47afd2b4 100644
--- a/include/sal/log-areas.dox
+++ b/include/sal/log-areas.dox
@@ -504,6 +504,7 @@ certain functionality.
@li @c vcl.unx.dtrans
@li @c vcl.unx.print
@li @c vcl.virdev
+@li @c vcl.watchdog
@li @c vcl.window
@li @c vcl.wmf
diff --git a/opencl/source/OpenCLZone.cxx b/opencl/source/OpenCLZone.cxx
index f7c8e961364d..43ac31899c4d 100644
--- a/opencl/source/OpenCLZone.cxx
+++ b/opencl/source/OpenCLZone.cxx
@@ -17,11 +17,6 @@
#include <com/sun/star/util/XFlushable.hpp>
#include <com/sun/star/configuration/theDefaultProvider.hpp>
-// FIXME: templatize me vs. OpenGLZone.
-
-std::sig_atomic_t volatile OpenCLZone::gnEnterCount = 0;
-bool volatile OpenCLZone::gbInInitialTest = false;
-
/**
* Called from a signal handler if we get
* a crash or hang in some CL code.
@@ -47,9 +42,4 @@ void OpenCLZone::hardDisable()
}
}
-void OpenCLZone::enterInitialTest()
-{
- gbInInitialTest = true;
-}
-
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/Library_vcl.mk b/vcl/Library_vcl.mk
index 3a7122f15b11..16be92968a92 100644
--- a/vcl/Library_vcl.mk
+++ b/vcl/Library_vcl.mk
@@ -399,6 +399,7 @@ $(eval $(call gb_Library_add_exception_objects,vcl,\
vcl/source/app/unohelp2 \
vcl/source/app/unohelp \
vcl/source/app/vclevent \
+ vcl/source/app/watchdog \
vcl/source/app/weldutils \
vcl/source/app/winscheduler \
vcl/source/components/dtranscomp \
diff --git a/vcl/README.vars b/vcl/README.vars
index 538c6975f26d..495c9679e401 100644
--- a/vcl/README.vars
+++ b/vcl/README.vars
@@ -36,7 +36,7 @@ OpenGL
SAL_FORCEGL - force enable OpenGL
SAL_GL_NO_SWAP - disable buffer swapping if set (should show nothing)
SAL_GL_SLEEP_ON_SWAP - sleep for half a second on each swap-buffers.
-SAL_DISABLE_GL_WATCHDOG - don't start the thread that watches for broken GL drivers
+SAL_DISABLE_WATCHDOG - don't start the thread that watches for broken GL/Vulkan/OpenCL drivers
Skia
----
diff --git a/vcl/inc/opengl/watchdog.hxx b/vcl/inc/opengl/watchdog.hxx
deleted file mode 100644
index a675894c4ff3..000000000000
--- a/vcl/inc/opengl/watchdog.hxx
+++ /dev/null
@@ -1,67 +0,0 @@
-/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
-/*
- * This file is part of the LibreOffice project.
- *
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/.
- */
-
-#ifndef INCLUDED_VCL_INC_OPENGL_WATCHDOG_H
-#define INCLUDED_VCL_INC_OPENGL_WATCHDOG_H
-
-#include <sal/config.h>
-#include <salhelper/thread.hxx>
-#include <atomic>
-#include <vector>
-
-struct WatchdogTimingsValues
-{
- /// delays to take various actions in 1/4 of a second increments.
- int mnDisableEntries;
- int const mnAbortAfter;
-};
-
-enum class WatchdogTimingMode
-{
- NORMAL,
- SHADER_COMPILE
-};
-
-class WatchdogTimings
-{
-private:
- std::vector<WatchdogTimingsValues> maTimingValues;
- std::atomic<bool> mbRelaxed;
-
-public:
- WatchdogTimings();
-
- void setRelax(bool bRelaxed)
- {
- mbRelaxed = bRelaxed;
- }
-
- WatchdogTimingsValues const & getWatchdogTimingsValues(WatchdogTimingMode eMode)
- {
- size_t index = (eMode == WatchdogTimingMode::SHADER_COMPILE) ? 1 : 0;
- index = mbRelaxed ? index + 2 : index;
-
- return maTimingValues[index];
- }
-};
-
-class OpenGLWatchdogThread : private salhelper::Thread
-{
- OpenGLWatchdogThread();
- virtual void execute() override;
-public:
- using salhelper::Thread::acquire;
- using salhelper::Thread::release;
- static void start();
- static void stop();
-};
-
-#endif // INCLUDED_VCL_INC_OPENGL_WATCHDOG_H
-
-/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/inc/opengl/zone.hxx b/vcl/inc/opengl/zone.hxx
index 90b7f48fd5a8..621ee4289b27 100644
--- a/vcl/inc/opengl/zone.hxx
+++ b/vcl/inc/opengl/zone.hxx
@@ -13,48 +13,19 @@
#include <sal/config.h>
#include <sal/types.h>
#include <vcl/dllapi.h>
-
-#include <atomic>
-#include <csignal>
-#include <type_traits>
-
-class OpenGLWatchdogThread;
+#include <comphelper/crashzone.hxx>
/**
* We want to be able to detect if a given crash came
* from the OpenGL code, so use this helper to track that.
*/
-class VCL_DLLPUBLIC OpenGLZone {
- friend class OpenGLWatchdogThread;
- friend class OpenGLSalGraphicsImpl;
-
- // gnEnterCount and gnLeaveCount are accessed both from multiple threads (cf.
- // OpenGLWatchdogThread::execute; so need to be of atomic type) and from signal handlers (cf.
- // VCLExceptionSignal_impl; so need to be of lock-free atomic type). sig_atomic_t is chosen as
- // the underlying type under the assumption that it is most likely to lead to an atomic type
- // that is actually lock-free. However, gnEnterCount and gnLeaveCount are both monotonically
- // increasing, so will eventually overflow, so the underlying type better be unsigned, which
- // sig_atomic_t is not guaranteed to be:
-#if !defined ARM32 || (defined ARM32 && defined __ARM_PCS_VFP)
- using AtomicCounter = std::atomic<std::make_unsigned_t<std::sig_atomic_t>>;
- static_assert(AtomicCounter::is_always_lock_free);
-#else
- using AtomicCounter = volatile std::make_unsigned_t<std::sig_atomic_t>;
-#endif
-
- /// how many times have we entered a GL zone
- static AtomicCounter gnEnterCount;
- /// how many times have we left a new GL zone
- static AtomicCounter gnLeaveCount;
-
- static void enter() { gnEnterCount++; }
- static void leave() { gnLeaveCount++; }
+class VCL_DLLPUBLIC OpenGLZone : public CrashZone< OpenGLZone > {
public:
- OpenGLZone() { enter(); }
- ~OpenGLZone() { leave(); }
- static bool isInZone() { return gnEnterCount != gnLeaveCount; }
static void hardDisable();
static void relaxWatchdogTimings();
+ static const CrashWatchdogTimingsValues& getCrashWatchdogTimingsValues();
+ static void checkDebug( int nUnchanged, const CrashWatchdogTimingsValues& aTimingValues );
+ static const char* name() { return "OpenGL"; }
};
/// Create this to not only enter the zone, but set VCL context.
diff --git a/vcl/inc/watchdog.hxx b/vcl/inc/watchdog.hxx
new file mode 100644
index 000000000000..ee357fb2dc89
--- /dev/null
+++ b/vcl/inc/watchdog.hxx
@@ -0,0 +1,32 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef INCLUDED_VCL_INC_WATCHDOG_H
+#define INCLUDED_VCL_INC_WATCHDOG_H
+
+#include <sal/config.h>
+#include <salhelper/thread.hxx>
+#include <atomic>
+#include <vector>
+
+class WatchdogThread : private salhelper::Thread
+{
+ WatchdogThread();
+ virtual void execute() override;
+
+public:
+ using salhelper::Thread::acquire;
+ using salhelper::Thread::release;
+ static void start();
+ static void stop();
+};
+
+#endif // INCLUDED_VCL_INC_WATCHDOG_H
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/source/app/svmain.cxx b/vcl/source/app/svmain.cxx
index b8c97d08d9c8..207a6ff4eaad 100644
--- a/vcl/source/app/svmain.cxx
+++ b/vcl/source/app/svmain.cxx
@@ -88,7 +88,7 @@
#include <opencl/OpenCLZone.hxx>
#include <opengl/zone.hxx>
-#include <opengl/watchdog.hxx>
+#include <watchdog.hxx>
#include <basegfx/utils/systemdependentdata.hxx>
#include <tools/diagnose_ex.h>
@@ -128,7 +128,7 @@ static oslSignalAction VCLExceptionSignal_impl( void* /*pData*/, oslSignalInfo*
{
OpenCLZone::hardDisable();
#ifdef _WIN32
- if (OpenCLZone::isInInitialTest())
+ if (OpenCLInitialZone::isInZone())
TerminateProcess(GetCurrentProcess(), EXITHELPER_NORMAL_RESTART);
#endif
}
@@ -212,9 +212,7 @@ int ImplSVMain()
pSVData->mxAccessBridge.clear();
}
-#if HAVE_FEATURE_OPENGL
- OpenGLWatchdogThread::stop();
-#endif
+ WatchdogThread::stop();
DeInitVCL();
return nReturn;
diff --git a/vcl/source/app/watchdog.cxx b/vcl/source/app/watchdog.cxx
new file mode 100644
index 000000000000..c6c43e7e013b
--- /dev/null
+++ b/vcl/source/app/watchdog.cxx
@@ -0,0 +1,144 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <watchdog.hxx>
+
+#include <config_features.h>
+
+#include <osl/conditn.hxx>
+#include <rtl/ref.hxx>
+#include <rtl/string.hxx>
+#include <sal/log.hxx>
+#include <opengl/zone.hxx>
+
+#include <stdlib.h>
+
+namespace
+{
+static volatile bool gbWatchdogFiring = false;
+static osl::Condition* gpWatchdogExit = nullptr;
+static rtl::Reference<WatchdogThread> gxWatchdog;
+
+template <typename Zone> struct WatchdogHelper
+{
+ static inline sal_uInt64 nLastEnters = 0;
+ static inline int nUnchanged = 0; // how many unchanged nEnters
+ static inline bool bFired = false;
+ static inline bool bAbortFired = false;
+ static void setLastEnters() { nLastEnters = Zone::enterCount(); }
+ static void check()
+ {
+ if (Zone::isInZone())
+ {
+ const CrashWatchdogTimingsValues& aTimingValues = Zone::getCrashWatchdogTimingsValues();
+
+ if (nLastEnters == Zone::enterCount())
+ nUnchanged++;
+ else
+ nUnchanged = 0;
+ Zone::checkDebug(nUnchanged, aTimingValues);
+
+ // Not making progress
+ if (nUnchanged >= aTimingValues.mnDisableEntries)
+ {
+ if (!bFired)
+ {
+ gbWatchdogFiring = true;
+ SAL_WARN("vcl.watchdog",
+ OStringLiteral("Watchdog triggered: hard disable ") + Zone::name());
+ Zone::hardDisable();
+ gbWatchdogFiring = false;
+ }
+ bFired = true;
+
+ // we can hang using VCL in the abort handling -> be impatient
+ if (bAbortFired)
+ {
+ SAL_WARN("vcl.watchdog",
+ OStringLiteral("Watchdog gave up: hard exiting ") + Zone::name());
+ _Exit(1);
+ }
+ }
+
+ // Not making even more progress
+ if (nUnchanged >= aTimingValues.mnAbortAfter)
+ {
+ if (!bAbortFired)
+ {
+ SAL_WARN("vcl.watchdog",
+ OStringLiteral("Watchdog gave up: aborting ") + Zone::name());
+ gbWatchdogFiring = true;
+ std::abort();
+ }
+ // coverity[dead_error_line] - we might have caught SIGABRT and failed to exit yet
+ bAbortFired = true;
+ }
+ }
+ else
+ {
+ nUnchanged = 0;
+ }
+ }
+};
+
+} // namespace
+
+WatchdogThread::WatchdogThread()
+ : salhelper::Thread("Crash Watchdog")
+{
+}
+
+void WatchdogThread::execute()
+{
+ TimeValue aQuarterSecond(0, 1000 * 1000 * 1000 * 0.25);
+ do
+ {
+#if HAVE_FEATURE_OPENGL
+ WatchdogHelper<OpenGLZone>::setLastEnters();
+#endif
+
+ gpWatchdogExit->wait(&aQuarterSecond);
+
+#if HAVE_FEATURE_OPENGL
+ WatchdogHelper<OpenGLZone>::check();
+#endif
+
+ } while (!gpWatchdogExit->check());
+}
+
+void WatchdogThread::start()
+{
+ if (gxWatchdog != nullptr)
+ return; // already running
+ if (getenv("SAL_DISABLE_WATCHDOG"))
+ return;
+ gpWatchdogExit = new osl::Condition();
+ gxWatchdog.set(new WatchdogThread());
+ gxWatchdog->launch();
+}
+
+void WatchdogThread::stop()
+{
+ if (gbWatchdogFiring)
+ return; // in watchdog thread
+
+ if (gpWatchdogExit)
+ gpWatchdogExit->set();
+
+ if (gxWatchdog.is())
+ {
+ gxWatchdog->join();
+ gxWatchdog.clear();
+ }
+
+ delete gpWatchdogExit;
+ gpWatchdogExit = nullptr;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/source/opengl/OpenGLHelper.cxx b/vcl/source/opengl/OpenGLHelper.cxx
index 1c9fa66436c8..081bf240cc8b 100644
--- a/vcl/source/opengl/OpenGLHelper.cxx
+++ b/vcl/source/opengl/OpenGLHelper.cxx
@@ -29,12 +29,11 @@
#include <unordered_map>
#include <opengl/zone.hxx>
-#include <opengl/watchdog.hxx>
-#include <osl/conditn.hxx>
#include <vcl/opengl/OpenGLWrapper.hxx>
#include <vcl/opengl/OpenGLContext.hxx>
#include <desktop/crashreport.hxx>
#include <bitmapwriteaccess.hxx>
+#include <watchdog.hxx>
#if defined UNX && !defined MACOSX && !defined IOS && !defined ANDROID && !defined HAIKU
#include <opengl/x11/X11DeviceInfo.hxx>
@@ -45,8 +44,6 @@
#include "GLMHelper.hxx"
static bool volatile gbInShaderCompile = false;
-OpenGLZone::AtomicCounter OpenGLZone::gnEnterCount = 0;
-OpenGLZone::AtomicCounter OpenGLZone::gnLeaveCount = 0;
namespace {
@@ -793,121 +790,50 @@ bool OpenGLHelper::supportsVCLOpenGL()
return !bDisableGL && !bBlacklisted;
}
-namespace {
- static volatile bool gbWatchdogFiring = false;
- static osl::Condition* gpWatchdogExit = nullptr;
- static WatchdogTimings gWatchdogTimings;
- static rtl::Reference<OpenGLWatchdogThread> gxWatchdog;
-}
-
-WatchdogTimings::WatchdogTimings()
- : maTimingValues{
- {{6, 20} /* 1.5s, 5s */, {20, 120} /* 5s, 30s */,
- {60, 240} /* 15s, 60s */, {60, 240} /* 15s, 60s */}
- }
- , mbRelaxed(false)
+namespace
{
-}
-OpenGLWatchdogThread::OpenGLWatchdogThread()
- : salhelper::Thread("OpenGL Watchdog")
+enum class CrashWatchdogTimingMode
{
-}
+ NORMAL,
+ SHADER_COMPILE
+};
-void OpenGLWatchdogThread::execute()
+class CrashWatchdogTimings
{
- int nUnchanged = 0; // how many unchanged nEnters
- TimeValue aQuarterSecond(0, 1000*1000*1000*0.25);
- bool bAbortFired = false;
+private:
+ std::vector<CrashWatchdogTimingsValues> maTimingValues;
+ std::atomic<bool> mbRelaxed;
- do {
- sal_uInt64 nLastEnters = OpenGLZone::gnEnterCount;
+public:
+ CrashWatchdogTimings();
- gpWatchdogExit->wait(&aQuarterSecond);
+ void setRelax(bool bRelaxed)
+ {
+ mbRelaxed = bRelaxed;
+ }
- if (OpenGLZone::isInZone())
- {
- // The shader compiler can take a long time, first time.
- WatchdogTimingMode eMode = gbInShaderCompile ? WatchdogTimingMode::SHADER_COMPILE : WatchdogTimingMode::NORMAL;
- WatchdogTimingsValues aTimingValues = gWatchdogTimings.getWatchdogTimingsValues(eMode);
+ CrashWatchdogTimingsValues const & getWatchdogTimingsValues(CrashWatchdogTimingMode eMode)
+ {
+ size_t index = (eMode == CrashWatchdogTimingMode::SHADER_COMPILE) ? 1 : 0;
+ index = mbRelaxed ? index + 2 : index;
- if (nLastEnters == OpenGLZone::gnEnterCount)
- nUnchanged++;
- else
- nUnchanged = 0;
- SAL_INFO("vcl.opengl", "GL watchdog - unchanged " <<
- nUnchanged << " enter count " <<
- OpenGLZone::gnEnterCount << " type " <<
- (eMode == WatchdogTimingMode::SHADER_COMPILE ? "in shader" : "normal gl") <<
- "breakpoints mid: " << aTimingValues.mnDisableEntries <<
- " max " << aTimingValues.mnAbortAfter);
-
- // Not making progress
- if (nUnchanged >= aTimingValues.mnDisableEntries)
- {
- static bool bFired = false;
- if (!bFired)
- {
- gbWatchdogFiring = true;
- SAL_WARN("vcl.opengl", "Watchdog triggered: hard disable GL");
- OpenGLZone::hardDisable();
- gbWatchdogFiring = false;
- }
- bFired = true;
-
- // we can hang using VCL in the abort handling -> be impatient
- if (bAbortFired)
- {
- SAL_WARN("vcl.opengl", "Watchdog gave up: hard exiting");
- _exit(1);
- }
- }
+ return maTimingValues[index];
+ }
+};
- // Not making even more progress
- if (nUnchanged >= aTimingValues.mnAbortAfter)
- {
- if (!bAbortFired)
- {
- SAL_WARN("vcl.opengl", "Watchdog gave up: aborting");
- gbWatchdogFiring = true;
- std::abort();
- }
- // coverity[dead_error_line] - we might have caught SIGABRT and failed to exit yet
- bAbortFired = true;
- }
- }
- else
- {
- nUnchanged = 0;
- }
- } while (!gpWatchdogExit->check());
-}
+static CrashWatchdogTimings gWatchdogTimings;
-void OpenGLWatchdogThread::start()
+CrashWatchdogTimings::CrashWatchdogTimings()
+ : maTimingValues{
+ {{6, 20} /* 1.5s, 5s */, {20, 120} /* 5s, 30s */,
+ {60, 240} /* 15s, 60s */, {60, 240} /* 15s, 60s */}
+ }
+ , mbRelaxed(false)
{
- assert (gxWatchdog == nullptr);
- gpWatchdogExit = new osl::Condition();
- gxWatchdog.set(new OpenGLWatchdogThread());
- gxWatchdog->launch();
}
-void OpenGLWatchdogThread::stop()
-{
- if (gbWatchdogFiring)
- return; // in watchdog thread
-
- if (gpWatchdogExit)
- gpWatchdogExit->set();
-
- if (gxWatchdog.is())
- {
- gxWatchdog->join();
- gxWatchdog.clear();
- }
-
- delete gpWatchdogExit;
- gpWatchdogExit = nullptr;
-}
+} // namespace
/**
* Called from a signal handler or watchdog thread if we get
@@ -932,8 +858,6 @@ void OpenGLZone::hardDisable()
css::configuration::theDefaultProvider::get(
comphelper::getProcessComponentContext()),
css::uno::UNO_QUERY_THROW)->flush();
-
- OpenGLWatchdogThread::stop();
}
}
@@ -942,6 +866,22 @@ void OpenGLZone::relaxWatchdogTimings()
gWatchdogTimings.setRelax(true);
}
+void OpenGLZone::checkDebug( int nUnchanged, const CrashWatchdogTimingsValues& aTimingValues )
+{
+ SAL_INFO("vcl.watchdog", "GL watchdog - unchanged "
+ << nUnchanged << " enter count " << enterCount() << " type "
+ << (gbInShaderCompile ? "in shader" : "normal gl")
+ << " breakpoints mid: " << aTimingValues.mnDisableEntries
+ << " max " << aTimingValues.mnAbortAfter);
+}
+
+const CrashWatchdogTimingsValues& OpenGLZone::getCrashWatchdogTimingsValues()
+{
+ // The shader compiler can take a long time, first time.
+ CrashWatchdogTimingMode eMode = gbInShaderCompile ? CrashWatchdogTimingMode::SHADER_COMPILE : CrashWatchdogTimingMode::NORMAL;
+ return gWatchdogTimings.getWatchdogTimingsValues(eMode);
+}
+
OpenGLVCLContextZone::OpenGLVCLContextZone()
{
OpenGLContext::makeVCLCurrent();
@@ -1019,10 +959,8 @@ bool OpenGLHelper::isVCLOpenGLEnabled()
}
if (bRet)
- {
- if (!getenv("SAL_DISABLE_GL_WATCHDOG"))
- OpenGLWatchdogThread::start();
- }
+ WatchdogThread::start();
+
CrashReporter::addKeyValue("UseOpenGL", OUString::boolean(bRet), CrashReporter::Write);
return bRet;