summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLuboš Luňák <l.lunak@collabora.com>2020-02-04 17:28:10 +0100
committerLuboš Luňák <l.lunak@collabora.com>2020-02-07 09:11:32 +0100
commit397ad713cf9bc951b4882ca4b6baeb57541e318c (patch)
tree2096facd2ea8432972d6354f960c528fa0f48a6a
parentbfb08ca517b6854b5c78b0b29c7a4d6dce473adb (diff)
merge OpenGLZone and OpenCLZone into one generic code
To be used also by Skia code to detect problems with Vulkan drivers. The watchdog does not handle OpenCL because neither did the original code, but also because OpenCLZone::hardDisable() called from it would deadlock on SolarMutex for some reason. Change-Id: I483d8cb0b11a4e1e65c564f4e4c29ab68843ff71 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/88008 Tested-by: Jenkins Reviewed-by: Luboš Luňák <l.lunak@collabora.com>
-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;