Trap SIGABRT in RenderThread for unit tests
Change-Id: Icc1039543d975497808a8062e9d909537c4a29c9
diff --git a/libs/hwui/Android.mk b/libs/hwui/Android.mk
index bbfc022..1adf9ba 100644
--- a/libs/hwui/Android.mk
+++ b/libs/hwui/Android.mk
@@ -225,6 +225,7 @@
$(hwui_test_common_src_files) \
tests/unit/CanvasStateTests.cpp \
tests/unit/ClipAreaTests.cpp \
+ tests/unit/CrashHandlerInjector.cpp \
tests/unit/DamageAccumulatorTests.cpp \
tests/unit/DeviceInfoTests.cpp \
tests/unit/FatVectorTests.cpp \
diff --git a/libs/hwui/tests/common/TestUtils.cpp b/libs/hwui/tests/common/TestUtils.cpp
index 624f3bd..d56693c 100644
--- a/libs/hwui/tests/common/TestUtils.cpp
+++ b/libs/hwui/tests/common/TestUtils.cpp
@@ -19,6 +19,10 @@
#include "DeferredLayerUpdater.h"
#include "LayerRenderer.h"
+#include <unistd.h>
+#include <signal.h>
+#include <setjmp.h>
+
namespace android {
namespace uirenderer {
@@ -121,5 +125,41 @@
canvas->drawTextOnPath(glyphs.data(), glyphs.size(), path, 0, 0, paint);
}
+static void defaultCrashHandler() {
+ fprintf(stderr, "RenderThread crashed!");
+}
+
+static jmp_buf gErrJmpBuff;
+static std::function<void()> gCrashHandler = defaultCrashHandler;
+
+static void signalHandler(int sig) {
+ longjmp(gErrJmpBuff, 1);
+}
+
+void TestUtils::setRenderThreadCrashHandler(std::function<void()> crashHandler) {
+ gCrashHandler = crashHandler;
+}
+
+void TestUtils::TestTask::run() {
+ struct sigaction act;
+ memset(&act, 0, sizeof(act));
+ act.sa_handler = signalHandler;
+
+ if (setjmp(gErrJmpBuff)) {
+ gCrashHandler();
+ return;
+ }
+
+ sigaction(SIGABRT, &act, nullptr);
+
+
+ // RenderState only valid once RenderThread is running, so queried here
+ RenderState& renderState = renderthread::RenderThread::getInstance().renderState();
+
+ renderState.onGLContextCreated();
+ rtCallback(renderthread::RenderThread::getInstance());
+ renderState.onGLContextDestroyed();
+}
+
} /* namespace uirenderer */
} /* namespace android */
diff --git a/libs/hwui/tests/common/TestUtils.h b/libs/hwui/tests/common/TestUtils.h
index edde31e..d9d32ce 100644
--- a/libs/hwui/tests/common/TestUtils.h
+++ b/libs/hwui/tests/common/TestUtils.h
@@ -173,19 +173,14 @@
typedef std::function<void(renderthread::RenderThread& thread)> RtCallback;
+ static void setRenderThreadCrashHandler(std::function<void()> crashHandler);
+
class TestTask : public renderthread::RenderTask {
public:
TestTask(RtCallback rtCallback)
: rtCallback(rtCallback) {}
virtual ~TestTask() {}
- virtual void run() override {
- // RenderState only valid once RenderThread is running, so queried here
- RenderState& renderState = renderthread::RenderThread::getInstance().renderState();
-
- renderState.onGLContextCreated();
- rtCallback(renderthread::RenderThread::getInstance());
- renderState.onGLContextDestroyed();
- };
+ virtual void run() override;
RtCallback rtCallback;
};
diff --git a/libs/hwui/tests/unit/CrashHandlerInjector.cpp b/libs/hwui/tests/unit/CrashHandlerInjector.cpp
new file mode 100644
index 0000000..685c264
--- /dev/null
+++ b/libs/hwui/tests/unit/CrashHandlerInjector.cpp
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "tests/common/TestUtils.h"
+
+#include <gtest/gtest.h>
+
+using namespace android::uirenderer;
+
+static void gunitCrashHandler() {
+ FAIL() << "RenderThread fatal exception!";
+}
+
+static void hookError() {
+ TestUtils::setRenderThreadCrashHandler(gunitCrashHandler);
+}
+
+class HookErrorInit {
+public:
+ HookErrorInit() { hookError(); }
+};
+
+static HookErrorInit sInit;