[Libreoffice-commits] core.git: desktop/source include/desktop

Mike Kaganski (via logerrit) logerrit at kemper.freedesktop.org
Fri Jan 10 17:05:33 UTC 2020


 desktop/source/app/app.cxx         |    4 ++
 desktop/source/app/crashreport.cxx |   49 ++++++++++++++++++++++++++++---
 desktop/source/app/sofficemain.cxx |   58 -------------------------------------
 include/desktop/crashreport.hxx    |    6 ++-
 4 files changed, 54 insertions(+), 63 deletions(-)

New commits:
commit 12b5892cf9c78dd917f2e50672cd250478e6c7d6
Author:     Mike Kaganski <mike.kaganski at collabora.com>
AuthorDate: Thu Jan 2 15:30:36 2020 +0300
Commit:     Mike Kaganski <mike.kaganski at collabora.com>
CommitDate: Fri Jan 10 18:05:01 2020 +0100

    Delete google_breakpad::ExceptionHandler before calling _exit()
    
    While debugging tdf#129712 on Windows, I saw this sequence:
    
    1. nullptr was dereferenced (the reason for tdf#129712).
    2. ExceptionHandler::HandleException was called (in
       workdir/UnpackedTarball/breakpad/src/client/windows/handler/exception_handler.cc).
    3. It called ExceptionHandler::WriteMinidumpOnHandlerThread.
    4. Minidump was created in ExceptionHandler::ExceptionHandlerThreadMain.
    5. Document Recovery dialog was shown in Desktop::Exception (in
       desktop/source/app/app.cxx).
    6. After closing dialog, _exit() was called in Desktop::Exception.
    7. All threads except main were terminated.
    8. Another access violation was thrown in the "minimal CRT cleanup".
    9. ExceptionHandler::HandleException called again.
    10. ExceptionHandler::WriteMinidumpOnHandlerThread hung on WaitForSingleObject
        because handler thread that should release the semaphore was terminated
        already at step 7.
    
    The process had to be killed manually.
    
    This change destroys the breakpad handler at the start of Desktop::Exception,
    which de-registers itself (on Windows it uses SetUnhandledExceptionFilter).
    Other than preventing the hang, the rationale also is that keeping the handler
    after first minidump creation is wrong: even if the second minidump creation
    succeeded, uploading it to crashdump server would give not the actual problem,
    but some unrelated stack.
    
    Change-Id: If12d0c7db519693f733b5ab3b8a288cef800a149
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/86104
    Reviewed-by: Markus Mohrhard <markus.mohrhard at googlemail.com>
    Tested-by: Mike Kaganski <mike.kaganski at collabora.com>

diff --git a/desktop/source/app/app.cxx b/desktop/source/app/app.cxx
index 7fd35ee3d574..eff6f70df610 100644
--- a/desktop/source/app/app.cxx
+++ b/desktop/source/app/app.cxx
@@ -1136,6 +1136,10 @@ void Desktop::Exception(ExceptionCategory nCategory)
     // protect against recursive calls
     static bool bInException = false;
 
+#if HAVE_FEATURE_BREAKPAD
+    CrashReporter::removeExceptionHandler(); // disallow re-entry
+#endif
+
     SystemWindowFlags nOldMode = Application::GetSystemWindowMode();
     Application::SetSystemWindowMode( nOldMode & ~SystemWindowFlags::NOAUTOMODE );
     if ( bInException )
diff --git a/desktop/source/app/crashreport.cxx b/desktop/source/app/crashreport.cxx
index 3420f20c4496..743ae43e7c9b 100644
--- a/desktop/source/app/crashreport.cxx
+++ b/desktop/source/app/crashreport.cxx
@@ -36,14 +36,44 @@
 #if defined __clang__
 #pragma clang diagnostic pop
 #endif
+#include <locale>
+#include <codecvt>
 #endif
 
 osl::Mutex CrashReporter::maMutex;
-google_breakpad::ExceptionHandler* CrashReporter::mpExceptionHandler = nullptr;
+std::unique_ptr<google_breakpad::ExceptionHandler> CrashReporter::mpExceptionHandler;
 bool CrashReporter::mbInit = false;
 CrashReporter::vmaKeyValues CrashReporter::maKeyValues;
 
 
+#if defined( UNX ) && !defined MACOSX && !defined IOS && !defined ANDROID
+static bool dumpCallback(const google_breakpad::MinidumpDescriptor& descriptor, void* /*context*/, bool succeeded)
+{
+    CrashReporter::addKeyValue("DumpFile", OStringToOUString(descriptor.path(), RTL_TEXTENCODING_UTF8), CrashReporter::Write);
+    SAL_WARN("desktop", "minidump generated: " << descriptor.path());
+
+    return succeeded;
+}
+#elif defined WNT
+static bool dumpCallback(const wchar_t* path, const wchar_t* id,
+    void* /*context*/, EXCEPTION_POINTERS* /*exinfo*/,
+    MDRawAssertionInfo* /*assertion*/,
+    bool succeeded)
+{
+    // TODO: moggi: can we avoid this conversion
+#ifdef _MSC_VER
+#pragma warning (disable: 4996)
+#endif
+    std::wstring_convert<std::codecvt_utf8<wchar_t>> conv1;
+    std::string aPath = conv1.to_bytes(std::wstring(path)) + conv1.to_bytes(std::wstring(id)) + ".dmp";
+    CrashReporter::addKeyValue("DumpFile", OStringToOUString(aPath.c_str(), RTL_TEXTENCODING_UTF8), CrashReporter::AddItem);
+    CrashReporter::addKeyValue("GDIHandles", OUString::number(::GetGuiResources(::GetCurrentProcess(), GR_GDIOBJECTS)), CrashReporter::Write);
+    SAL_WARN("desktop", "minidump generated: " << aPath);
+    return succeeded;
+}
+#endif
+
+
 void CrashReporter::writeToFile(std::ios_base::openmode Openmode)
 {
     std::ofstream ini_file(getIniFileName(), Openmode);
@@ -171,10 +201,21 @@ bool CrashReporter::readSendConfig(std::string& response)
     return crashreport::readConfig(CrashReporter::getIniFileName(), &response);
 }
 
-void CrashReporter::storeExceptionHandler(google_breakpad::ExceptionHandler* pExceptionHandler)
+void CrashReporter::installExceptionHandler()
+{
+    if (!IsDumpEnable())
+        return;
+#if defined( UNX ) && !defined MACOSX && !defined IOS && !defined ANDROID
+    google_breakpad::MinidumpDescriptor descriptor("/tmp");
+    mpExceptionHandler = std::make_unique<google_breakpad::ExceptionHandler>(descriptor, nullptr, dumpCallback, nullptr, true, -1);
+#elif defined WNT
+    mpExceptionHandler = std::make_unique<google_breakpad::ExceptionHandler>(L".", nullptr, dumpCallback, nullptr, google_breakpad::ExceptionHandler::HANDLER_ALL);
+#endif
+}
+
+void CrashReporter::removeExceptionHandler()
 {
-    if(IsDumpEnable())
-        mpExceptionHandler = pExceptionHandler;
+    mpExceptionHandler.reset();
 }
 
 
diff --git a/desktop/source/app/sofficemain.cxx b/desktop/source/app/sofficemain.cxx
index 70d396d232b6..064c08579ab9 100644
--- a/desktop/source/app/sofficemain.cxx
+++ b/desktop/source/app/sofficemain.cxx
@@ -46,22 +46,6 @@
 
 #if HAVE_FEATURE_BREAKPAD
 #include <desktop/crashreport.hxx>
-
-#if defined( UNX ) && !defined MACOSX && !defined IOS && !defined ANDROID
-#include <client/linux/handler/exception_handler.h>
-#elif defined WNT
-#if defined __clang__
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wmicrosoft-enum-value"
-#endif
-#include <client/windows/handler/exception_handler.h>
-#if defined __clang__
-#pragma clang diagnostic pop
-#endif
-#include <locale>
-#include <codecvt>
-#endif
-
 #endif
 
 #include <postwin.h>
@@ -75,52 +59,12 @@
 #  define LOGI(...) ((void)__android_log_print(ANDROID_LOG_INFO, LOGTAG, __VA_ARGS__))
 #endif
 
-#if HAVE_FEATURE_BREAKPAD
-
-#if defined( UNX ) && !defined MACOSX && !defined IOS && !defined ANDROID
-static bool dumpCallback(const google_breakpad::MinidumpDescriptor& descriptor, void* /*context*/, bool succeeded)
-{
-    CrashReporter::addKeyValue("DumpFile", OStringToOUString(descriptor.path(), RTL_TEXTENCODING_UTF8), CrashReporter::Write);
-    SAL_WARN("desktop", "minidump generated: " << descriptor.path());
-
-    return succeeded;
-}
-#elif defined WNT
-static bool dumpCallback(const wchar_t* path, const wchar_t* id,
-                            void* /*context*/, EXCEPTION_POINTERS* /*exinfo*/,
-                            MDRawAssertionInfo* /*assertion*/,
-                            bool succeeded)
-{
-    // TODO: moggi: can we avoid this conversion
-#ifdef _MSC_VER
-#pragma warning (disable: 4996)
-#endif
-    std::wstring_convert<std::codecvt_utf8<wchar_t>> conv1;
-    std::string aPath = conv1.to_bytes(std::wstring(path)) + conv1.to_bytes(std::wstring(id)) + ".dmp";
-    CrashReporter::addKeyValue("DumpFile", OStringToOUString(aPath.c_str(), RTL_TEXTENCODING_UTF8), CrashReporter::AddItem);
-    CrashReporter::addKeyValue("GDIHandles", OUString::number(::GetGuiResources (::GetCurrentProcess(), GR_GDIOBJECTS)), CrashReporter::Write);
-    SAL_WARN("desktop", "minidump generated: " << aPath);
-    return succeeded;
-}
-#endif
-
-#endif
 extern "C" int DESKTOP_DLLPUBLIC soffice_main()
 {
     sal_detail_initialize(sal::detail::InitializeSoffice, nullptr);
 
 #if HAVE_FEATURE_BREAKPAD
-
-#if defined( UNX ) && !defined MACOSX && !defined IOS && !defined ANDROID
-    google_breakpad::MinidumpDescriptor descriptor("/tmp");
-    google_breakpad::ExceptionHandler eh(descriptor, nullptr, dumpCallback, nullptr, true, -1);
-
-    CrashReporter::storeExceptionHandler(&eh);
-#elif defined WNT
-    google_breakpad::ExceptionHandler eh(L".", nullptr, dumpCallback, nullptr, google_breakpad::ExceptionHandler::HANDLER_ALL);
-
-    CrashReporter::storeExceptionHandler(&eh);
-#endif
+    CrashReporter::installExceptionHandler();
 #endif
 
 #if defined( UNX ) && !defined MACOSX && !defined IOS && !defined ANDROID && HAVE_FEATURE_UI && HAVE_FEATURE_OPENGL
diff --git a/include/desktop/crashreport.hxx b/include/desktop/crashreport.hxx
index 585c0af5e1a9..8235cff03501 100644
--- a/include/desktop/crashreport.hxx
+++ b/include/desktop/crashreport.hxx
@@ -18,6 +18,7 @@
 #include <config_features.h>
 
 // vector not sort the entries
+#include <memory>
 #include <vector>
 #include <string>
 
@@ -46,7 +47,8 @@ public:
 #if HAVE_FEATURE_BREAKPAD
     static void addKeyValue(const OUString& rKey, const OUString& rValue, tAddKeyHandling AddKeyHandling);
 
-    static void storeExceptionHandler(google_breakpad::ExceptionHandler* pExceptionHandler);
+    static void installExceptionHandler();
+    static void removeExceptionHandler();
 
     static bool crashReportInfoExists();
 
@@ -71,7 +73,7 @@ private:
     typedef std::vector<mpair> vmaKeyValues;
     static vmaKeyValues maKeyValues; // used to temporarily save entries before the old info has been uploaded
 
-    static google_breakpad::ExceptionHandler* mpExceptionHandler;
+    static std::unique_ptr<google_breakpad::ExceptionHandler> mpExceptionHandler;
 
     static std::string getIniFileName();
     static void writeCommonInfo();


More information about the Libreoffice-commits mailing list