[Libreoffice-commits] core.git: Branch 'distro/cib/libreoffice-6-1' - 4 commits - bin/symstore.sh config_host.mk.in configure.ac cui/Library_cui.mk cui/source cui/uiconfig desktop/source framework/source include/desktop instsetoo_native/CustomTarget_setup.mk instsetoo_native/util officecfg/registry sal/osl scp2/source solenv/gbuild svx/source vcl/opengl vcl/source vcl/unx vcl/win

Mike Kaganski (via logerrit) logerrit at kemper.freedesktop.org
Mon Apr 20 01:13:09 UTC 2020


 bin/symstore.sh                                            |   93 ++++++-
 config_host.mk.in                                          |    1 
 configure.ac                                               |   15 +
 cui/Library_cui.mk                                         |    3 
 cui/source/options/optgdlg.cxx                             |   20 +
 cui/source/options/optgdlg.hxx                             |    1 
 cui/uiconfig/ui/optgeneralpage.ui                          |   41 ++-
 desktop/source/app/app.cxx                                 |   43 +--
 desktop/source/app/crashreport.cxx                         |  161 ++++++++++---
 desktop/source/app/sofficemain.cxx                         |   64 -----
 desktop/source/minidump/minidump.cxx                       |   24 +
 desktop/source/minidump/minidump_upload.cxx                |    2 
 framework/source/services/desktop.cxx                      |    2 
 include/desktop/crashreport.hxx                            |   63 +++--
 include/desktop/minidump.hxx                               |   13 -
 instsetoo_native/CustomTarget_setup.mk                     |    1 
 instsetoo_native/util/openoffice.lst.in                    |    1 
 officecfg/registry/schema/org/openoffice/Office/Common.xcs |    7 
 sal/osl/w32/process.cxx                                    |    6 
 scp2/source/ooo/common_brand.scp                           |    9 
 solenv/gbuild/platform/com_MSC_class.mk                    |    2 
 svx/source/dialog/crashreportdlg.cxx                       |    5 
 vcl/opengl/win/WinDeviceInfo.cxx                           |    6 
 vcl/opengl/x11/X11DeviceInfo.cxx                           |    4 
 vcl/source/opengl/OpenGLHelper.cxx                         |    2 
 vcl/source/window/builder.cxx                              |    2 
 vcl/unx/generic/plugadapt/salplug.cxx                      |    2 
 vcl/win/app/salinst.cxx                                    |    2 
 28 files changed, 391 insertions(+), 204 deletions(-)

New commits:
commit 8693e35977f2ec6ea9cca736b41ea558108a6422
Author:     Mike Kaganski <mike.kaganski at collabora.com>
AuthorDate: Thu Jan 2 15:30:36 2020 +0300
Commit:     Thorsten Behrens <Thorsten.Behrens at CIB.de>
CommitDate: Mon Apr 20 03:04:59 2020 +0200

    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>
    (cherry picked from commit 12b5892cf9c78dd917f2e50672cd250478e6c7d6)
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/89690
    Tested-by: Thorsten Behrens <Thorsten.Behrens at CIB.de>
    Reviewed-by: Thorsten Behrens <Thorsten.Behrens at CIB.de>

diff --git a/desktop/source/app/app.cxx b/desktop/source/app/app.cxx
index 17c348743ef6..efecdfaf0cc6 100644
--- a/desktop/source/app/app.cxx
+++ b/desktop/source/app/app.cxx
@@ -1126,6 +1126,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 71434ac5b965..ab19dc6327d7 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 d8fc55d86596..a352286c83d4 100644
--- a/desktop/source/app/sofficemain.cxx
+++ b/desktop/source/app/sofficemain.cxx
@@ -42,22 +42,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
 
 
@@ -70,50 +54,10 @@
 #  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()
 {
 #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 && !defined(LIBO_HEADLESS) && 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();
commit 82fe655a8295fb72967960e8d480c7d9faf1036f
Author:     Mike Kaganski <mike.kaganski at collabora.com>
AuthorDate: Tue Apr 16 22:08:42 2019 +0200
Commit:     Thorsten Behrens <Thorsten.Behrens at CIB.de>
CommitDate: Mon Apr 20 03:04:51 2020 +0200

    tdf#124776: don't use SearchPathW to get full path of executable
    
    ... use GetModuleFileNameW() for that.
    
    We call SetDllDirectoryW and SetSearchPathMode to improve security of
    the process, and exclude some paths (including current directory) from
    search when using API that looks for binaries whose names are not fully
    qualified.
    
    So the sequence is this:
    1. Program is started using relative executable path like
       "instdir\program\soffice";
    2. sal_detail_initialize is called, which calls the two mentioned
       hardening functions;
    3. sal_detail_initialize calls osl_setCommandArgs, which in turn calls
       osl_createCommandArgs_Impl;
    4. The latter uses SearchPathW with empty path and first program arg
       "instdir\program\soffice" to find fully qualified program path.
    
    That now naturally fails, because current path is not searched.
    
    But to find the process name, we need no search: we can simply use
    GetModuleFileNameW() with NULL passed as module handle. Let's use that.
    
    Note that we can't use _wpgmptr/_get_wpgmptr, because we don't use wide
    entry point like wmain.
    
    LHM-Stuff
    ---------
    Dieser Patch löst das Problem wenn Symbols eingeschaltet ist, danach
    konnte LO nicht mit scalc.exe, swriter.exe, .. gestartet werden den es
    ist damit abgestürzt. (Dumpfile war im LO-Verzeichnis)
    
    Reviewed-on: https://gerrit.libreoffice.org/70844
    Reviewed-by: Mike Kaganski <mike.kaganski at collabora.com>
    Tested-by: Mike Kaganski <mike.kaganski at collabora.com>
    (cherry picked from commit c650217cc543080928a26de4bfc07ebb0be5c6ca)
    
    Change-Id: I7a0013a0505f7bdd38164b09b045bfade9686664
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/89689
    Tested-by: Thorsten Behrens <Thorsten.Behrens at CIB.de>
    Reviewed-by: Thorsten Behrens <Thorsten.Behrens at CIB.de>

diff --git a/sal/osl/w32/process.cxx b/sal/osl/w32/process.cxx
index 153df540c5ae..60fc80a23070 100644
--- a/sal/osl/w32/process.cxx
+++ b/sal/osl/w32/process.cxx
@@ -334,10 +334,8 @@ static rtl_uString ** osl_createCommandArgs_Impl (int argc, char **)
         {
             /* Ensure absolute path */
             ::osl::LongPathBuffer< sal_Unicode > aBuffer( MAX_LONG_PATH );
-            DWORD dwResult = 0;
-
-            dwResult = SearchPathW (
-                nullptr, o3tl::toW(ppArgs[0]->buffer), L".exe", aBuffer.getBufSizeInSymbols(), o3tl::toW(aBuffer), nullptr);
+            DWORD dwResult
+                = GetModuleFileNameW(nullptr, o3tl::toW(aBuffer), aBuffer.getBufSizeInSymbols());
             if ((0 < dwResult) && (dwResult < aBuffer.getBufSizeInSymbols()))
             {
                 /* Replace argv[0] with its absolute path */
commit b4c63d2fcb11f21a508a469b19ac15d6678b1e06
Author:     Juergen Funk <juergen.funk_ml at cib.de>
AuthorDate: Mon Nov 4 10:42:06 2019 +0100
Commit:     Thorsten Behrens <Thorsten.Behrens at CIB.de>
CommitDate: Mon Apr 20 02:22:20 2020 +0200

    tdf#127711 - A runtime-switch for the MiniCrashDump and associated changes
    
    - add CrashDumpEnable to soffice.ini
    - also check env var CRASH_DUMP_ENABLE (overrides soffice.ini)
    - make sure _all_ binaries are added to symstore
    
    This is a squash of:
     https://gerrit.libreoffice.org/79273
     https://gerrit.libreoffice.org/81989
     https://gerrit.libreoffice.org/c/core/+/87260
     https://gerrit.libreoffice.org/c/core/+/87261
     https://gerrit.libreoffice.org/79272
     https://gerrit.libreoffice.org/83171
     https://gerrit.libreoffice.org/82751
     https://gerrit.libreoffice.org/83066
     https://gerrit.libreoffice.org/83726
     https://gerrit.libreoffice.org/c/core/+/86465

diff --git a/bin/symstore.sh b/bin/symstore.sh
index b368eb3e6715..564739a0279f 100755
--- a/bin/symstore.sh
+++ b/bin/symstore.sh
@@ -1,30 +1,75 @@
 #!/usr/bin/env bash
 
+# Files listed here would not be store in the symbolestore-server.
+# The format is a string with files e.g.
+#  BLACKLIST="python.exe
+#  file.dll
+#  next_file.exe"
+#
+# It removes "python.exe", "file.dll", and "next_file.exe" from what's
+# added to the symstore. Separator is the newline
+BLACK_LIST="python.exe"
+
+# List files here where it's ok for this script to find more than one
+# occurence in the build tree. Files _not_ included here will generate
+# an error, if duplicates are found.
+#
+# Same format as for BLACK_LIST above above
+MOREPDBS_OKLIST="libcurl.dll"
+
+
 add_pdb()
 {
     extension=$1
-    type=$2
+    pdbext=$2
     list=$3
-    for file in $(find "${INSTDIR}/" -name "*.${extension}"); do
+    stats_notfound=0
+    stats_found=0
+    stats_morefound=0
+    declare -a pdball
+    echo "Collect $extension"
+    ret=$(find "${INSTDIR}/" -type f -name "*.${extension}" | grep -vF "$BLACK_LIST")
+    while IFS= read -r file
+    do
         # store dll/exe itself (needed for minidumps)
-        if [ -f "$file" ]; then
+        if [ $WITHEXEC == 1 ] ; then
             cygpath -w "$file" >> "$list"
         fi
         # store pdb file
         filename=$(basename "$file" ".${extension}")
-        pdb="${WORKDIR}/LinkTarget/${type}/${filename}.pdb"
-        if [ -f "$pdb" ]; then
-            cygpath -w "$pdb" >> "$list"
+        pdball+=($(grep -i "/${filename}${pdbext}" <<< ${ALL_PDBS}))
+        if [ -n "${pdball[0]}" ]; then
+            cygpath -w "${pdball[0]}" >> "$list"
         fi
-    done
+        case ${#pdball[@]} in
+            0) ((++stats_notfound)) ;;
+            1) ((++stats_found)) ;;
+            *) ((++stats_morefound))
+                if [ -z "$(echo $file | grep -F "$MOREPDBS_OKLIST")" ]; then
+                    echo "Error: found duplicate PDBs:"
+                    for morepdbs in ${pdball[@]} ; do
+                       echo " $morepdbs"
+                    done
+                    exit 1
+                fi
+            ;;
+        esac
+        unset pdball
+    done <<EOF
+${ret}
+EOF
+
+    echo "  Found PDBs    : $stats_found"
+    echo "  Missing PDBs  : $stats_notfound"
+    echo "  Multiple PDBs : $stats_morefound"
 }
 
 # check preconditions
-if [ -z "${INSTDIR}" ] || [ -z "${WORKDIR}" ]; then
+if [ -z "${INSTDIR}" -o -z "${WORKDIR}" ]; then
     echo "INSTDIR or WORKDIR not set - script expects calling inside buildenv"
     exit 1
 fi
-if [ ! -d "${INSTDIR}" ] || [ ! -d "${WORKDIR}" ]; then
+if [ ! -d "${INSTDIR}" -o ! -d "${WORKDIR}" ]; then
     echo "INSTDIR or WORKDIR not present - script expects calling after full build"
     exit 1
 fi
@@ -36,12 +81,17 @@ which symstore.exe > /dev/null 2>&1 || {
 # defaults
 MAX_KEEP=5
 SYM_PATH=${WORKDIR}/symstore
+COMMENT=""
+COMCMD=""
+WITHEXEC=1
 
 USAGE="Usage: $0 [-h|-k <keep_num_versions>|-p <symbol_store_path>]
-       -h:         this cruft
-       -k <int>:   keep this number of old symbol versions around
-                   (default: ${MAX_KEEP}. Set to 0 for unlimited)
-       -p <path>:  specify full path to symbol store tree
+       -h:          this cruft
+       -c <comment> specifies a comment for the transaction
+       -n           do not store exe/dll on the symbole server
+       -k <int>:    keep this number of old symbol versions around
+                    (default: ${MAX_KEEP}. Set to 0 for unlimited)
+       -p <path>:   specify full path to symbol store tree
 If no path is specified, defaults to ${SYM_PATH}.
 "
 
@@ -51,7 +101,9 @@ do
    case "$1" in
     -k|--keep) MAX_KEEP="$2"; shift 2;;
     -p|--path) SYM_PATH="$2"; shift 2;;
-    -h|--help) echo "${USAGE}"; exit 0; shift;;
+    -c|--comment) COMCMD="/c"; COMMENT="$2"; shift 2;;
+    -n|--noexec) WITHEXEC=0; shift ;;
+    -h|--help) echo "${USAGE}"; exit 0;;
     -*) echo "${USAGE}" >&2; exit 1;;
     *) break;;
    esac
@@ -66,20 +118,25 @@ fi
 TMPFILE=$(mktemp) || exit 1
 trap '{ rm -f ${TMPFILE}; }' EXIT
 
+# collect all PDBs
+ALL_PDBS=$(find "${WORKDIR}/" -type f -name "*.pdb")
+
 # add dlls and executables
-add_pdb dll Library "${TMPFILE}"
-add_pdb exe Executable "${TMPFILE}"
+add_pdb dll .pdb "${TMPFILE}"
+add_pdb exe .pdb "${TMPFILE}"
+add_pdb bin .bin.pdb "${TMPFILE}"
 
 # stick all of it into symbol store
-symstore.exe add /compress /f "@$(cygpath -w "${TMPFILE}")" /s "$(cygpath -w "${SYM_PATH}")" /t "${PRODUCTNAME}" /v "${LIBO_VERSION_MAJOR}.${LIBO_VERSION_MINOR}.${LIBO_VERSION_MICRO}.${LIBO_VERSION_PATCH}${LIBO_VERSION_SUFFIX}${LIBO_VERSION_SUFFIX_SUFFIX}"
+symstore.exe add /compress /f "@$(cygpath -w "${TMPFILE}")" /s "$(cygpath -w "${SYM_PATH}")" /t "${PRODUCTNAME}" /v "${LIBO_VERSION_MAJOR}.${LIBO_VERSION_MINOR}.${LIBO_VERSION_MICRO}.${LIBO_VERSION_PATCH}${LIBO_VERSION_SUFFIX}${LIBO_VERSION_SUFFIX_SUFFIX}" "${COMCMD}" "${COMMENT}"
 rm -f "${TMPFILE}"
 
 # Cleanup symstore, older revisions will be removed.  Unless the
 # .dll/.exe changes, the .pdb should be shared, so with incremental
 # tinderbox several revisions should not be that space-demanding.
-if [ "${MAX_KEEP}" -gt 0 ] && [ -d "${SYM_PATH}/000Admin" ]; then
+if [ "${MAX_KEEP}" -gt 0 -a -d "${SYM_PATH}/000Admin" ]; then
     to_remove=$(ls -1 "${SYM_PATH}/000Admin" | grep -v '\.txt' | grep -v '\.deleted' | sort | head -n "-${MAX_KEEP}")
     for revision in $to_remove; do
+        echo "Remove $revision from symstore"
         symstore.exe del /i "${revision}" /s "$(cygpath -w "${SYM_PATH}")"
     done
 fi
diff --git a/config_host.mk.in b/config_host.mk.in
index 683abbff2e05..767011a1cb5d 100644
--- a/config_host.mk.in
+++ b/config_host.mk.in
@@ -110,6 +110,7 @@ export EBOOK_CFLAGS=$(gb_SPACE)@EBOOK_CFLAGS@
 export EBOOK_LIBS=$(gb_SPACE)@EBOOK_LIBS@
 export ENABLE_AVAHI=@ENABLE_AVAHI@
 export ENABLE_BREAKPAD=@ENABLE_BREAKPAD@
+export DEFAULT_CRASHDUMP_VALUE=@DEFAULT_CRASHDUMP_VALUE@
 export ENABLE_CAIRO_CANVAS=@ENABLE_CAIRO_CANVAS@
 export ENABLE_CHART_TESTS=@ENABLE_CHART_TESTS@
 export ENABLE_CIPHER_OPENSSL_BACKEND=@ENABLE_CIPHER_OPENSSL_BACKEND@
diff --git a/configure.ac b/configure.ac
index 4accf14e1215..fe394203bf21 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1056,6 +1056,11 @@ libo_FUZZ_ARG_ENABLE(breakpad,
         [Enables breakpad for crash reporting.])
 )
 
+libo_FUZZ_ARG_ENABLE(crashdump,
+    AS_HELP_STRING([--disable-crashdump],
+        [Disable dump.ini and dump-file, when --enable-breakpad])
+)
+
 AC_ARG_ENABLE(fetch-external,
     AS_HELP_STRING([--disable-fetch-external],
         [Disables fetching external tarballs from web sources.])
@@ -9148,6 +9153,7 @@ AC_SUBST(ICU_UCHAR_TYPE)
 dnl ==================================================================
 dnl Breakpad
 dnl ==================================================================
+DEFAULT_CRASHDUMP_VALUE="true"
 AC_MSG_CHECKING([whether to enable breakpad])
 if test "$enable_breakpad" != yes; then
     AC_MSG_RESULT([no])
@@ -9158,6 +9164,14 @@ else
     AC_DEFINE(HAVE_FEATURE_BREAKPAD, 1)
     BUILD_TYPE="$BUILD_TYPE BREAKPAD"
 
+    AC_MSG_CHECKING([for disable crash dump])
+    if test "$enable_crashdump" = no; then
+        DEFAULT_CRASHDUMP_VALUE="false"
+        AC_MSG_RESULT([yes])
+    else
+       AC_MSG_RESULT([no])
+    fi
+
     AC_MSG_CHECKING([for crashreport config])
     if test "$with_symbol_config" = "no"; then
         BREAKPAD_SYMBOL_CONFIG="invalid"
@@ -9170,6 +9184,7 @@ else
     AC_SUBST(BREAKPAD_SYMBOL_CONFIG)
 fi
 AC_SUBST(ENABLE_BREAKPAD)
+AC_SUBST(DEFAULT_CRASHDUMP_VALUE)
 
 dnl ==================================================================
 dnl libfuzzer
diff --git a/cui/Library_cui.mk b/cui/Library_cui.mk
index 44bac812c557..302c6890729c 100644
--- a/cui/Library_cui.mk
+++ b/cui/Library_cui.mk
@@ -60,6 +60,9 @@ $(eval $(call gb_Library_use_libraries,cui,\
     ucbhelper \
     utl \
     vcl \
+    $(if $(ENABLE_BREAKPAD), \
+        crashreport \
+    ) \
 ))
 
 $(eval $(call gb_Library_use_externals,cui,\
diff --git a/cui/source/options/optgdlg.cxx b/cui/source/options/optgdlg.cxx
index 05c48787f6b1..e8fc180bb3b4 100644
--- a/cui/source/options/optgdlg.cxx
+++ b/cui/source/options/optgdlg.cxx
@@ -69,6 +69,8 @@
 #include <officecfg/Office/Common.hxx>
 #include <officecfg/Setup.hxx>
 #include <comphelper/configuration.hxx>
+#include <tools/diagnose_ex.h>
+#include <desktop/crashreport.hxx>
 
 #include <com/sun/star/configuration/theDefaultProvider.hpp>
 #include <com/sun/star/container/XNameAccess.hpp>
@@ -427,11 +429,11 @@ void OfaMiscTabPage::Reset( const SfxItemSet* rSet )
     m_pCollectUsageInfo->SaveValue();
 
 #if HAVE_FEATURE_BREAKPAD
-    m_xCrashReport->Check(officecfg::Office::Common::Misc::CrashReport::get());
-    m_xCrashReport->Enable(!officecfg::Office::Common::Misc::CrashReport::isReadOnly());
+    m_xCrashReport->Check(officecfg::Office::Common::Misc::CrashReport::get() && CrashReporter::IsDumpEnable());
+    m_xCrashReport->Enable(!officecfg::Office::Common::Misc::CrashReport::isReadOnly() && CrashReporter::IsDumpEnable());
     m_xCrashReport->SaveValue();
 #else
-    m_xCrashReport->Disable();
+    m_xCrashReport->Hide();
 #endif
 
     SfxItemState eState = rSet->GetItemState( SID_ATTR_QUICKLAUNCHER, false, &pItem );
diff --git a/desktop/source/app/app.cxx b/desktop/source/app/app.cxx
index 59815e72dacb..17c348743ef6 100644
--- a/desktop/source/app/app.cxx
+++ b/desktop/source/app/app.cxx
@@ -122,10 +122,6 @@
 
 #include "langselect.hxx"
 
-#if HAVE_FEATURE_BREAKPAD
-#include <fstream>
-#endif
-
 #if defined MACOSX
 #include <errno.h>
 #include <sys/wait.h>
@@ -889,26 +885,6 @@ void Desktop::HandleBootstrapErrors(
 
 namespace {
 
-bool crashReportInfoExists()
-{
-#if HAVE_FEATURE_BREAKPAD
-    std::string path = CrashReporter::getIniFileName();
-    std::ifstream aFile(path);
-    while (aFile.good())
-    {
-        std::string line;
-        std::getline(aFile, line);
-        int sep = line.find('=');
-        if (sep >= 0)
-        {
-            std::string key = line.substr(0, sep);
-            if (key == "DumpFile")
-                return true;
-        }
-    }
-#endif
-    return false;
-}
 
 #if HAVE_FEATURE_BREAKPAD
 void handleCrashReport()
@@ -968,7 +944,12 @@ void impl_checkRecoveryState(bool& bCrashed           ,
                              bool& bRecoveryDataExists,
                              bool& bSessionDataExists )
 {
-    bCrashed = officecfg::Office::Recovery::RecoveryInfo::Crashed::get() || crashReportInfoExists();
+    bCrashed = officecfg::Office::Recovery::RecoveryInfo::Crashed::get()
+#if HAVE_FEATURE_BREAKPAD
+        || CrashReporter::crashReportInfoExists();
+#else
+        ;
+#endif
     bool elements = officecfg::Office::Recovery::RecoveryList::get()->
         hasElements();
     bool session
@@ -2026,7 +2007,7 @@ void Desktop::OpenClients()
 #endif
 
 #if HAVE_FEATURE_BREAKPAD
-    if (officecfg::Office::Common::Misc::CrashReport::get() && crashReportInfoExists())
+    if (officecfg::Office::Common::Misc::CrashReport::get() && CrashReporter::crashReportInfoExists())
         handleCrashReport();
 #endif
 
@@ -2104,11 +2085,9 @@ void Desktop::OpenClients()
             }
         }
     }
-#if HAVE_FEATURE_BREAKPAD
-    CrashReporter::writeCommonInfo();
+
     // write this information here to avoid depending on vcl in the crash reporter lib
-    CrashReporter::AddKeyValue("Language", Application::GetSettings().GetLanguageTag().getBcp47());
-#endif
+    CrashReporter::addKeyValue("Language", Application::GetSettings().GetLanguageTag().getBcp47(), CrashReporter::Create);
 
     RequestHandler::EnableRequests();
 
diff --git a/desktop/source/app/crashreport.cxx b/desktop/source/app/crashreport.cxx
index 29001367bb91..71434ac5b965 100644
--- a/desktop/source/app/crashreport.cxx
+++ b/desktop/source/app/crashreport.cxx
@@ -14,17 +14,17 @@
 #include <ucbhelper/proxydecider.hxx>
 #include <unotools/bootstrap.hxx>
 #include <o3tl/char16_t2wchar_t.hxx>
+#include <desktop/minidump.hxx>
 
 #include <config_version.h>
 #include <config_folders.h>
 
 #include <string>
-#include <fstream>
 
-osl::Mutex CrashReporter::maMutex;
 
 #if HAVE_FEATURE_BREAKPAD
 
+#include <fstream>
 #if defined( UNX ) && !defined MACOSX && !defined IOS && !defined ANDROID
 #include <client/linux/handler/exception_handler.h>
 #elif defined WNT
@@ -38,41 +38,47 @@ osl::Mutex CrashReporter::maMutex;
 #endif
 #endif
 
+osl::Mutex CrashReporter::maMutex;
 google_breakpad::ExceptionHandler* CrashReporter::mpExceptionHandler = nullptr;
 bool CrashReporter::mbInit = false;
-std::map<OUString, OUString> CrashReporter::maKeyValues;
+CrashReporter::vmaKeyValues CrashReporter::maKeyValues;
 
-namespace {
 
-void writeToStream(std::ofstream& strm, const OUString& rKey, const OUString& rValue)
+void CrashReporter::writeToFile(std::ios_base::openmode Openmode)
 {
-    strm << rtl::OUStringToOString(rKey, RTL_TEXTENCODING_UTF8).getStr() << "=";
-    strm << rtl::OUStringToOString(rValue, RTL_TEXTENCODING_UTF8).getStr() << "\n";
-}
+    std::ofstream ini_file(getIniFileName(), Openmode);
 
+    for (auto& keyValue : maKeyValues)
+    {
+        ini_file << rtl::OUStringToOString(keyValue.first, RTL_TEXTENCODING_UTF8).getStr() << "=";
+        ini_file << rtl::OUStringToOString(keyValue.second, RTL_TEXTENCODING_UTF8).getStr() << "\n";
+    }
+
+    maKeyValues.clear();
+    ini_file.close();
 }
 
-void CrashReporter::AddKeyValue(const OUString& rKey, const OUString& rValue)
+void CrashReporter::addKeyValue(const OUString& rKey, const OUString& rValue, tAddKeyHandling AddKeyHandling)
 {
     osl::MutexGuard aGuard(maMutex);
-    if (mbInit)
-    {
-        std::string ini_path = getIniFileName();
-        std::ofstream ini_file(ini_path, std::ios_base::app);
-        writeToStream(ini_file, rKey, rValue);
-    }
-    else
+
+    if (IsDumpEnable())
     {
-        maKeyValues.insert(std::pair<OUString, OUString>(rKey, rValue));
+        if (!rKey.isEmpty())
+            maKeyValues.push_back(mpair(rKey, rValue));
+
+        if (AddKeyHandling != AddItem)
+        {
+            if (mbInit)
+                writeToFile(std::ios_base::app);
+            else if (AddKeyHandling == Create)
+                writeCommonInfo();
+        }
     }
 }
 
-#endif
-
 void CrashReporter::writeCommonInfo()
 {
-    osl::MutexGuard aGuard(maMutex);
-
     ucbhelper::InternetProxyDecider proxy_decider(::comphelper::getProcessComponentContext());
 
     const OUString protocol = "https";
@@ -81,31 +87,33 @@ void CrashReporter::writeCommonInfo()
 
     const ucbhelper::InternetProxyServer proxy_server = proxy_decider.getProxy(protocol, url, port);
 
+    // save the new Keys
+    vmaKeyValues atlast = maKeyValues;
+    // clear the keys, the following Keys should be at the begin
+    maKeyValues.clear();
+
     // limit the amount of code that needs to be executed before the crash reporting
-    std::string ini_path = CrashReporter::getIniFileName();
-    std::ofstream minidump_file(ini_path, std::ios_base::trunc);
-    minidump_file << "ProductName=LibreOffice\n";
-    minidump_file << "Version=" LIBO_VERSION_DOTTED "\n";
-    minidump_file << "BuildID=" << utl::Bootstrap::getBuildIdData("") << "\n";
-    minidump_file << "URL=" << protocol << "://" << url << "/submit/\n";
+    addKeyValue("ProductName", "LibreOffice", AddItem);
+    addKeyValue("Version", LIBO_VERSION_DOTTED, AddItem);
+    addKeyValue("BuildID", utl::Bootstrap::getBuildIdData(""), AddItem);
+    addKeyValue("URL", protocol + "://" + url + "/submit/", AddItem);
 
     if (proxy_server.aName != OUString())
     {
-        minidump_file << "Proxy=" << proxy_server.aName << ":" << proxy_server.nPort << "\n";
+        addKeyValue("Proxy", proxy_server.aName + ":" + OUString::number(proxy_server.nPort), AddItem);
     }
 
-    for (auto& keyValue : maKeyValues)
-    {
-        writeToStream(minidump_file, keyValue.first, keyValue.second);
-    }
-    maKeyValues.clear();
-    minidump_file.close();
+    // write the new keys at the end
+    maKeyValues.insert(maKeyValues.end(), atlast.begin(), atlast.end());
 
     mbInit = true;
 
+    writeToFile(std::ios_base::trunc);
+
     updateMinidumpLocation();
 }
 
+
 namespace {
 
 OUString getCrashDirectory()
@@ -144,11 +152,48 @@ void CrashReporter::updateMinidumpLocation()
 #endif
 }
 
+bool CrashReporter::crashReportInfoExists()
+{
+    static bool first = true;
+    static bool InfoExist = false;
+
+    if (first)
+    {
+        first = false;
+        InfoExist = crashreport::readConfig(CrashReporter::getIniFileName(), nullptr);
+    }
+
+    return InfoExist;
+}
+
+bool CrashReporter::readSendConfig(std::string& response)
+{
+    return crashreport::readConfig(CrashReporter::getIniFileName(), &response);
+}
+
 void CrashReporter::storeExceptionHandler(google_breakpad::ExceptionHandler* pExceptionHandler)
 {
-    mpExceptionHandler = pExceptionHandler;
+    if(IsDumpEnable())
+        mpExceptionHandler = pExceptionHandler;
 }
 
+
+
+bool CrashReporter::IsDumpEnable()
+{
+    OUString sToken;
+    OString  sEnvVar(std::getenv("CRASH_DUMP_ENABLE"));
+    bool     bEnable = true;   // default, always on
+    // read configuration item 'CrashDumpEnable' -> bool on/off
+    if (rtl::Bootstrap::get("CrashDumpEnable", sToken) && sEnvVar.isEmpty())
+    {
+        bEnable = sToken.toBoolean();
+    }
+
+    return bEnable;
+}
+
+
 std::string CrashReporter::getIniFileName()
 {
     OUString url = getCrashDirectory() + "dump.ini";
@@ -157,4 +202,7 @@ std::string CrashReporter::getIniFileName()
     return aRet;
 }
 
+
+#endif //HAVE_FEATURE_BREAKPAD
+
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/desktop/source/app/sofficemain.cxx b/desktop/source/app/sofficemain.cxx
index 4fb84d39d2d1..d8fc55d86596 100644
--- a/desktop/source/app/sofficemain.cxx
+++ b/desktop/source/app/sofficemain.cxx
@@ -41,7 +41,6 @@
 #include <unotools/mediadescriptor.hxx>
 
 #if HAVE_FEATURE_BREAKPAD
-#include <fstream>
 #include <desktop/crashreport.hxx>
 
 #if defined( UNX ) && !defined MACOSX && !defined IOS && !defined ANDROID
@@ -76,11 +75,9 @@
 #if defined( UNX ) && !defined MACOSX && !defined IOS && !defined ANDROID
 static bool dumpCallback(const google_breakpad::MinidumpDescriptor& descriptor, void* /*context*/, bool succeeded)
 {
-    std::string ini_path = CrashReporter::getIniFileName();
-    std::ofstream minidump_file(ini_path, std::ios_base::app);
-    minidump_file << "DumpFile=" << descriptor.path() << "\n";
-    minidump_file.close();
+    CrashReporter::addKeyValue("DumpFile", OStringToOUString(descriptor.path(), RTL_TEXTENCODING_UTF8), CrashReporter::Write);
     SAL_WARN("desktop", "minidump generated: " << descriptor.path());
+
     return succeeded;
 }
 #elif defined WNT
@@ -89,17 +86,14 @@ static bool dumpCallback(const wchar_t* path, const wchar_t* id,
                             MDRawAssertionInfo* /*assertion*/,
                             bool succeeded)
 {
-    std::string ini_path = CrashReporter::getIniFileName();
-    std::ofstream minidump_file(ini_path, std::ios_base::app);
     // 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";
-    minidump_file << "DumpFile=" << aPath << "\n";
-    minidump_file << "GDIHandles=" << ::GetGuiResources (::GetCurrentProcess(), GR_GDIOBJECTS) << "\n";
-    minidump_file.close();
+    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;
 }
diff --git a/desktop/source/minidump/minidump.cxx b/desktop/source/minidump/minidump.cxx
index f3eefd023b75..05cf13a1e929 100644
--- a/desktop/source/minidump/minidump.cxx
+++ b/desktop/source/minidump/minidump.cxx
@@ -23,7 +23,9 @@ std::map<std::string, std::string> readStrings(std::istream& file)
 {
     std::map<std::string, std::string> parameters;
 
-    while (!file.eof())
+    // when file is not readable, the status eof would not be set
+    // better test of state is okay
+    while (file)
     {
         std::string line;
         std::getline(file, line);
@@ -189,7 +191,7 @@ bool uploadContent(std::map<std::string, std::string>& parameters, std::string&
 
 namespace crashreport {
 
-bool readConfig(const std::string& iniPath, std::string& response)
+bool readConfig(const std::string& iniPath, std::string * response)
 {
     std::ifstream file(iniPath);
     std::map<std::string, std::string> parameters = readStrings(file);
@@ -197,17 +199,29 @@ bool readConfig(const std::string& iniPath, std::string& response)
     // make sure that at least the mandatory parameters are in there
     if (parameters.find("DumpFile") == parameters.end())
     {
-        response = "ini file needs to contain a key DumpFile!";
+        if(response != nullptr)
+            *response = "ini file needs to contain a key DumpFile!";
         return false;
     }
 
     if (parameters.find("Version") == parameters.end())
     {
-        response = "ini file needs to contain a key Version!";
+        if (response != nullptr)
+            *response = "ini file needs to contain a key Version!";
         return false;
     }
 
-    return uploadContent(parameters, response);
+    if (parameters.find("URL") == parameters.end())
+    {
+        if (response != nullptr)
+            *response = "ini file needs to contain a key URL!";
+        return false;
+    }
+
+    if (response != nullptr)
+        return uploadContent(parameters, *response);
+
+    return true;
 }
 
 }
diff --git a/desktop/source/minidump/minidump_upload.cxx b/desktop/source/minidump/minidump_upload.cxx
index ded2f1df0a43..15af26430764 100644
--- a/desktop/source/minidump/minidump_upload.cxx
+++ b/desktop/source/minidump/minidump_upload.cxx
@@ -22,7 +22,7 @@ int main(int argc, char** argv)
 
     std::string iniPath(argv[1]);
     std::string response;
-    if (!crashreport::readConfig(iniPath, response))
+    if (!crashreport::readConfig(iniPath, &response))
         return EXIT_FAILURE;
 
     std::cout << "Response: " << response << std::endl;
diff --git a/framework/source/services/desktop.cxx b/framework/source/services/desktop.cxx
index d88371979f20..0b296b90dd35 100644
--- a/framework/source/services/desktop.cxx
+++ b/framework/source/services/desktop.cxx
@@ -314,7 +314,7 @@ sal_Bool SAL_CALL Desktop::terminate()
         // see dispose() for further information.
         /* SAFE AREA --------------------------------------------------------------------------------------- */
         SolarMutexClearableGuard aWriteLock;
-        CrashReporter::AddKeyValue("ShutDown", OUString::boolean(true));
+        CrashReporter::addKeyValue("ShutDown", OUString::boolean(true), CrashReporter::Write);
         m_bIsTerminated = true;
         aWriteLock.clear();
         /* UNSAFE AREA ------------------------------------------------------------------------------------- */
diff --git a/include/desktop/crashreport.hxx b/include/desktop/crashreport.hxx
index 6056adbe1d28..585c0af5e1a9 100644
--- a/include/desktop/crashreport.hxx
+++ b/include/desktop/crashreport.hxx
@@ -17,7 +17,8 @@
 
 #include <config_features.h>
 
-#include <map>
+// vector not sort the entries
+#include <vector>
 #include <string>
 
 namespace google_breakpad
@@ -41,40 +42,52 @@ CRASHREPORT_DLLPUBLIC
 /*class*/ CrashReporter
 {
 public:
-    static void AddKeyValue(const OUString& rKey, const OUString& rValue);
+    typedef enum {AddItem, Write, Create} tAddKeyHandling;
+#if HAVE_FEATURE_BREAKPAD
+    static void addKeyValue(const OUString& rKey, const OUString& rValue, tAddKeyHandling AddKeyHandling);
 
-    static std::string getIniFileName();
+    static void storeExceptionHandler(google_breakpad::ExceptionHandler* pExceptionHandler);
 
-    static void writeCommonInfo();
+    static bool crashReportInfoExists();
 
-    static void storeExceptionHandler(google_breakpad::ExceptionHandler* pExceptionHandler);
+    static bool readSendConfig(std::string& response);
 
-    // when we create the ExceptionHandler we have no access to the user
-    // profile yet, so update when we have access
-    static void updateMinidumpLocation();
+    static bool IsDumpEnable();
 
 private:
-
     static osl::Mutex maMutex;
-
     static bool mbInit;
-
-    static std::map<OUString, OUString> maKeyValues; // used to temporarily save entries before the old info has been uploaded
+    typedef  struct _mpair
+    {
+        OUString first;
+        OUString second;
+        _mpair(const OUString& First, const OUString& Second)
+        {
+            first  = First;
+            second = Second;
+        };
+    } mpair;
+
+    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;
-};
 
-// Add dummy methods for the non-breakpad case. That allows us to use
-// the code without linking to the lib and without adding HAVE_FEATURE_BREAKPAD
-// everywhere we want to log something to the crash report system.
-#if HAVE_FEATURE_BREAKPAD
-#else
-inline void CrashReporter::AddKeyValue(SAL_UNUSED_PARAMETER const OUString& /*rKey*/, SAL_UNUSED_PARAMETER const OUString& /*rValue*/)
-{
-}
-#endif
+    static std::string getIniFileName();
+    static void writeCommonInfo();
+    static void writeToFile(std::ios_base::openmode Openmode);
+    // when we create the ExceptionHandler we have no access to the user
+    // profile yet, so update when we have access
+    static void updateMinidumpLocation();
 
+#else
+    // Add dummy methods for the non-breakpad case. That allows us to use
+    // // the code without linking to the lib and without adding HAVE_FEATURE_BREAKPAD
+    // // everywhere we want to log something to the crash report system.
+    inline static void addKeyValue(SAL_UNUSED_PARAMETER const OUString& /*rKey*/, SAL_UNUSED_PARAMETER const OUString& /*rValue*/, SAL_UNUSED_PARAMETER tAddKeyHandling /*AddKeyHandling*/) {};
+#endif // HAVE_FEATURE_BREAKPAD
+};
 
-#endif
+#endif // INCLUDED_DESKTOP_CRASHREPORT_HXX
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/include/desktop/minidump.hxx b/include/desktop/minidump.hxx
index 63336cae5595..6ed0e18277f8 100644
--- a/include/desktop/minidump.hxx
+++ b/include/desktop/minidump.hxx
@@ -16,7 +16,18 @@
 
 namespace crashreport {
 
-CRASHREPORT_DLLPUBLIC bool readConfig(const std::string& iniPath, std::string& response);
+// when response = nullptr only make test
+/** Read+Send, Test and send info from the Dump.ini .
+
+        @param [in] iniPath Path-file to the read/test ini-file
+        @param [in] response=nullptr in this case made the Test only
+        @param [in] response!=nullptr in this case made the Read+Send
+
+        @retval true       Read+Send, Test was okay
+        @retval false      Read+Send, Test is a error
+*/
+
+CRASHREPORT_DLLPUBLIC bool readConfig(const std::string& iniPath, std::string * response);
 
 }
 
diff --git a/instsetoo_native/CustomTarget_setup.mk b/instsetoo_native/CustomTarget_setup.mk
index 4d47d8d894e8..98ec287ada3f 100644
--- a/instsetoo_native/CustomTarget_setup.mk
+++ b/instsetoo_native/CustomTarget_setup.mk
@@ -119,6 +119,7 @@ $(call gb_CustomTarget_get_workdir,instsetoo_native/setup)/$(call gb_Helper_get_
 	( \
 		echo '[Bootstrap]' \
 		&& echo 'CrashDirectory=$${$$BRAND_BASE_DIR/$(LIBO_ETC_FOLDER)/$(call gb_Helper_get_rcfile,bootstrap):UserInstallation}/crash' \
+		&& echo 'CrashDumpEnable=$(DEFAULT_CRASHDUMP_VALUE)' \
 		&& echo 'HideEula=1' \
 		&& echo 'Logo=1' \
 		&& echo 'NativeProgress=false' \
diff --git a/instsetoo_native/util/openoffice.lst.in b/instsetoo_native/util/openoffice.lst.in
index 569c6ed8f9c3..18d3aa742cd7 100644
--- a/instsetoo_native/util/openoffice.lst.in
+++ b/instsetoo_native/util/openoffice.lst.in
@@ -36,6 +36,7 @@ Globals
             STARTCENTER_HIDE_EXTERNAL_LINKS 0
             64BITPRODUCT @WINDOWS_X64@
             WINDOWSSDKVERSION @WINDOWS_SDK_VERSION@
+            CRASHDUMPENABLE @DEFAULT_CRASHDUMP_VALUE@
         }
     }
 }
diff --git a/scp2/source/ooo/common_brand.scp b/scp2/source/ooo/common_brand.scp
index 08e3b43df660..e46bd98acd60 100644
--- a/scp2/source/ooo/common_brand.scp
+++ b/scp2/source/ooo/common_brand.scp
@@ -439,6 +439,15 @@ ProfileItem gid_Brand_Profileitem_Soffice_CrashDirectory
     Value = "${$BRAND_BASE_DIR/" LIBO_ETC_FOLDER "/" PROFILENAME(bootstrap) ":UserInstallation}/crash";
 End
 
+ProfileItem gid_Brand_Profileitem_Soffice_CrashDump
+    ProfileID = gid_Brand_Profile_Soffice_Ini;
+    ModuleID = gid_Module_Root_Brand;
+    Section = "Bootstrap";
+    Key = "CrashDumpEnable";
+    Value = "${CRASHDUMPENABLE}";
+End
+
+
 ProfileItem gid_Brand_Profileitem_Soffice_SecureUserConfig
     ProfileID = gid_Brand_Profile_Soffice_Ini;
     ModuleID = gid_Module_Root_Brand;
diff --git a/solenv/gbuild/platform/com_MSC_class.mk b/solenv/gbuild/platform/com_MSC_class.mk
index 1dfa3b899ebf..f05793b83dfa 100644
--- a/solenv/gbuild/platform/com_MSC_class.mk
+++ b/solenv/gbuild/platform/com_MSC_class.mk
@@ -114,7 +114,7 @@ gb_LinkTarget_INCLUDE :=\
 # We must name the .pdb like libname.pdb, not libname.\(dll\|exe\|pyd\).pdb,
 # otherwise WinDbg does not find it.
 define gb_LinkTarget__get_pdb_filename
-$(patsubst %.dll,%.pdb,$(patsubst %.exe,%.pdb,$(patsubst %.pyd,%.pdb,$(1))))
+$(patsubst %.dll,%.pdb,$(patsubst %.exe,%.pdb,$(patsubst %.bin,%.bin.pdb,$(patsubst %.pyd,%.pdb,$(1)))))
 endef
 
 gb_LinkTarget_get_pdbfile_in = \
diff --git a/svx/source/dialog/crashreportdlg.cxx b/svx/source/dialog/crashreportdlg.cxx
index 70799f969bba..482af1f28950 100644
--- a/svx/source/dialog/crashreportdlg.cxx
+++ b/svx/source/dialog/crashreportdlg.cxx
@@ -14,7 +14,6 @@
 
 #include <rtl/bootstrap.hxx>
 #include <desktop/crashreport.hxx>
-#include <desktop/minidump.hxx>
 #include <sfx2/safemode.hxx>
 #include <comphelper/processfactory.hxx>
 #include <osl/file.hxx>
@@ -77,10 +76,8 @@ IMPL_LINK(CrashReportDialog, BtnHdl, Button*, pBtn, void)
 {
     if (pBtn == mpBtnSend.get())
     {
-        std::string ini_path = CrashReporter::getIniFileName();
-
         std::string response;
-        bool bSuccess = crashreport::readConfig(ini_path, response);
+        bool bSuccess = CrashReporter::readSendConfig(response);
 
         OUString aCrashID = OUString::createFromAscii(response.c_str());
 
diff --git a/vcl/opengl/win/WinDeviceInfo.cxx b/vcl/opengl/win/WinDeviceInfo.cxx
index 9b4438cbccdb..00f05df0066d 100644
--- a/vcl/opengl/win/WinDeviceInfo.cxx
+++ b/vcl/opengl/win/WinDeviceInfo.cxx
@@ -540,9 +540,9 @@ void writeToLog(SvStream& rStrm, const char* pKey, const OUString & rVal)
 
 bool WinOpenGLDeviceInfo::isDeviceBlocked()
 {
-    CrashReporter::AddKeyValue("OpenGLVendor", maAdapterVendorID);
-    CrashReporter::AddKeyValue("OpenGLDevice", maAdapterDeviceID);
-    CrashReporter::AddKeyValue("OpenGLDriver", maDriverVersion);
+    CrashReporter::addKeyValue("OpenGLVendor", maAdapterVendorID, CrashReporter::AddItem);
+    CrashReporter::addKeyValue("OpenGLDevice", maAdapterDeviceID, CrashReporter::AddItem);
+    CrashReporter::addKeyValue("OpenGLDriver", maDriverVersion, CrashReporter::Write);
 
     SAL_INFO("vcl.opengl", maDriverVersion);
     SAL_INFO("vcl.opengl", maDriverDate);
diff --git a/vcl/opengl/x11/X11DeviceInfo.cxx b/vcl/opengl/x11/X11DeviceInfo.cxx
index 5388f85c0c3d..6ac3269035f4 100644
--- a/vcl/opengl/x11/X11DeviceInfo.cxx
+++ b/vcl/opengl/x11/X11DeviceInfo.cxx
@@ -282,8 +282,8 @@ bool X11OpenGLDeviceInfo::isDeviceBlocked()
     if (mnGLMajorVersion == 1)
         return true;
 
-    CrashReporter::AddKeyValue("AdapterVendorId", rtl::OStringToOUString(maVendor, RTL_TEXTENCODING_UTF8));
-    CrashReporter::AddKeyValue("AdapterDeviceId", rtl::OStringToOUString(maRenderer, RTL_TEXTENCODING_UTF8));
+    CrashReporter::addKeyValue("AdapterVendorId", rtl::OStringToOUString(maVendor, RTL_TEXTENCODING_UTF8), CrashReporter::AddItem);
+    CrashReporter::addKeyValue("AdapterDeviceId", rtl::OStringToOUString(maRenderer, RTL_TEXTENCODING_UTF8), CrashReporter::Write);
 
     SAL_INFO("vcl.opengl", "Vendor: " << maVendor);
     SAL_INFO("vcl.opengl", "Renderer: " << maRenderer);
diff --git a/vcl/source/opengl/OpenGLHelper.cxx b/vcl/source/opengl/OpenGLHelper.cxx
index 3bad4ea44b87..cad628204626 100644
--- a/vcl/source/opengl/OpenGLHelper.cxx
+++ b/vcl/source/opengl/OpenGLHelper.cxx
@@ -1044,7 +1044,7 @@ bool OpenGLHelper::isVCLOpenGLEnabled()
         if (!getenv("SAL_DISABLE_GL_WATCHDOG"))
             OpenGLWatchdogThread::start();
     }
-    CrashReporter::AddKeyValue("UseOpenGL", OUString::boolean(bRet));
+    CrashReporter::addKeyValue("UseOpenGL", OUString::boolean(bRet), CrashReporter::Write);
 
     return bRet;
 }
diff --git a/vcl/source/window/builder.cxx b/vcl/source/window/builder.cxx
index 8aa9d46f876d..2de55dd63d76 100644
--- a/vcl/source/window/builder.cxx
+++ b/vcl/source/window/builder.cxx
@@ -361,7 +361,7 @@ VclBuilder::VclBuilder(vcl::Window *pParent, const OUString& sUIDir, const OUStr
     catch (const css::uno::Exception &rExcept)
     {
         DBG_UNHANDLED_EXCEPTION("vcl.layout", "Unable to read .ui file");
-        CrashReporter::AddKeyValue("VclBuilderException", "Unable to read .ui file: " + rExcept.Message);
+        CrashReporter::addKeyValue("VclBuilderException", "Unable to read .ui file: " + rExcept.Message, CrashReporter::Write);
         throw;
     }
 
diff --git a/vcl/unx/generic/plugadapt/salplug.cxx b/vcl/unx/generic/plugadapt/salplug.cxx
index b7ed29a22f5d..792b6ae1fff0 100644
--- a/vcl/unx/generic/plugadapt/salplug.cxx
+++ b/vcl/unx/generic/plugadapt/salplug.cxx
@@ -278,7 +278,7 @@ void SalAbort( const OUString& rErrorText, bool bDumpCore )
         std::fprintf( stderr, "Application Error\n" );
     else
     {
-        CrashReporter::AddKeyValue("AbortMessage", rErrorText);
+        CrashReporter::addKeyValue("AbortMessage", rErrorText, CrashReporter::Write);
         std::fprintf( stderr, "%s\n", OUStringToOString(rErrorText, osl_getThreadTextEncoding()).getStr() );
     }
     if( bDumpCore )
diff --git a/vcl/win/app/salinst.cxx b/vcl/win/app/salinst.cxx
index 67b6c26b66e5..25c43916338b 100644
--- a/vcl/win/app/salinst.cxx
+++ b/vcl/win/app/salinst.cxx
@@ -77,7 +77,7 @@ void SalAbort( const OUString& rErrorText, bool )
     }
     else
     {
-        CrashReporter::AddKeyValue("AbortMessage", rErrorText);
+        CrashReporter::addKeyValue("AbortMessage", rErrorText, CrashReporter::Write);
         // make sure crash reporter is triggered
         RaiseException( 0, EXCEPTION_NONCONTINUABLE, 0, nullptr );
         FatalAppExitW( 0, o3tl::toW(rErrorText.getStr()) );
commit 44c9e12820e1a8bc74f98fe142a69d3499ef67b3
Author:     Gabor Kelemen <kelemen.gabor2 at nisz.hu>
AuthorDate: Wed Jul 31 23:54:29 2019 +0200
Commit:     Thorsten Behrens <Thorsten.Behrens at CIB.de>
CommitDate: Mon Apr 20 02:21:34 2020 +0200

    tdf#107471 Add checkbox to enable/disable sending crash reports to TDF
    
    Also hide it when compiled with --disable-breakpad i.e. most Linux distributions
    
    Reviewed-on: https://gerrit.libreoffice.org/76771
    Tested-by: Jenkins
    Reviewed-by: Samuel Mehrbrodt <Samuel.Mehrbrodt at cib.de>
    (cherry picked from commit 5841be069cf9891669b385f62f2e7f8d8e877981)
    
    Change-Id: I5d392e22410614550aa9602d0c30b0b81ec22ea0
    Reviewed-on: https://gerrit.libreoffice.org/79057
    Reviewed-by: Juergen Funk (CIB) <juergen.funk_ml at cib.de>
    Tested-by: Juergen Funk (CIB) <juergen.funk_ml at cib.de>

diff --git a/cui/source/options/optgdlg.cxx b/cui/source/options/optgdlg.cxx
index 3d0e7ee81be7..05c48787f6b1 100644
--- a/cui/source/options/optgdlg.cxx
+++ b/cui/source/options/optgdlg.cxx
@@ -279,6 +279,8 @@ OfaMiscTabPage::OfaMiscTabPage(vcl::Window* pParent, const SfxItemSet& rSet)
     get(m_pToYearFT, "toyear");
     get(m_pCollectUsageInfo, "collectusageinfo");
     get(m_pQuickStarterFrame, "quickstarter");
+    get(m_xCrashReport, "crashreport");
+
 
 #if defined(UNX)
     get(m_pQuickLaunchCB, "systray");
@@ -376,6 +378,14 @@ bool OfaMiscTabPage::FillItemSet( SfxItemSet* rSet )
         bModified = true;
     }
 
+#if HAVE_FEATURE_BREAKPAD
+    if (m_xCrashReport->IsValueChangedFromSaved())
+    {
+        officecfg::Office::Common::Misc::CrashReport::set(m_xCrashReport->IsChecked(), batch);
+        bModified = true;
+    }
+#endif
+
     batch->commit();
 
     if( m_pQuickLaunchCB->IsValueChangedFromSaved())
@@ -416,6 +426,14 @@ void OfaMiscTabPage::Reset( const SfxItemSet* rSet )
     m_pCollectUsageInfo->Enable(!officecfg::Office::Common::Misc::CollectUsageInformation::isReadOnly());
     m_pCollectUsageInfo->SaveValue();
 
+#if HAVE_FEATURE_BREAKPAD
+    m_xCrashReport->Check(officecfg::Office::Common::Misc::CrashReport::get());
+    m_xCrashReport->Enable(!officecfg::Office::Common::Misc::CrashReport::isReadOnly());
+    m_xCrashReport->SaveValue();
+#else
+    m_xCrashReport->Disable();
+#endif
+
     SfxItemState eState = rSet->GetItemState( SID_ATTR_QUICKLAUNCHER, false, &pItem );
     if ( SfxItemState::SET == eState )
         m_pQuickLaunchCB->Check( static_cast<const SfxBoolItem*>(pItem)->GetValue() );
diff --git a/cui/source/options/optgdlg.hxx b/cui/source/options/optgdlg.hxx
index f6296ff87679..d4b568c2479b 100644
--- a/cui/source/options/optgdlg.hxx
+++ b/cui/source/options/optgdlg.hxx
@@ -60,6 +60,7 @@ private:
 
     VclPtr<VclContainer> m_pQuickStarterFrame;
     VclPtr<CheckBox>     m_pQuickLaunchCB;
+    VclPtr<CheckBox>     m_xCrashReport;
 
     DECL_LINK( TwoFigureHdl, Edit&, void );
 protected:
diff --git a/cui/uiconfig/ui/optgeneralpage.ui b/cui/uiconfig/ui/optgeneralpage.ui
index 022fb620bcdd..1b807b495051 100644
--- a/cui/uiconfig/ui/optgeneralpage.ui
+++ b/cui/uiconfig/ui/optgeneralpage.ui
@@ -287,14 +287,41 @@
             <property name="top_padding">6</property>
             <property name="left_padding">12</property>
             <child>
-              <object class="GtkCheckButton" id="collectusageinfo">
-                <property name="label" translatable="yes" context="optgeneralpage|collectusageinfo">Collect usage data and send it to The Document Foundation</property>
+              <object class="GtkGrid">
                 <property name="visible">True</property>
-                <property name="can_focus">True</property>
-                <property name="receives_default">False</property>
-                <property name="use_underline">True</property>
-                <property name="xalign">0</property>
-                <property name="draw_indicator">True</property>
+                <property name="can_focus">False</property>
+                <child>
+                  <object class="GtkCheckButton" id="collectusageinfo">
+                    <property name="label" translatable="yes" context="optgeneralpage|collectusageinfo">Collect usage data and send it to The Document Foundation</property>
+                    <property name="visible">True</property>
+                    <property name="can_focus">True</property>
+                    <property name="receives_default">False</property>
+                    <property name="margin_top">1</property>
+                    <property name="use_underline">True</property>
+                    <property name="xalign">0</property>
+                    <property name="draw_indicator">True</property>
+                  </object>
+                  <packing>
+                    <property name="left_attach">0</property>
+                    <property name="top_attach">0</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkCheckButton" id="crashreport">
+                    <property name="label" translatable="yes" context="optgeneralpage|crashreport">Sen_d crash reports to The Document Foundation</property>
+                    <property name="visible">True</property>
+                    <property name="can_focus">True</property>
+                    <property name="receives_default">False</property>
+                    <property name="halign">start</property>
+                    <property name="use_underline">True</property>
+                    <property name="active">True</property>
+                    <property name="draw_indicator">True</property>
+                  </object>
+                  <packing>
+                    <property name="left_attach">0</property>
+                    <property name="top_attach">1</property>
+                  </packing>
+                </child>
               </object>
             </child>
           </object>
diff --git a/desktop/source/app/app.cxx b/desktop/source/app/app.cxx
index e7a4f82ba081..59815e72dacb 100644
--- a/desktop/source/app/app.cxx
+++ b/desktop/source/app/app.cxx
@@ -2026,7 +2026,7 @@ void Desktop::OpenClients()
 #endif
 
 #if HAVE_FEATURE_BREAKPAD
-    if (crashReportInfoExists())
+    if (officecfg::Office::Common::Misc::CrashReport::get() && crashReportInfoExists())
         handleCrashReport();
 #endif
 
diff --git a/officecfg/registry/schema/org/openoffice/Office/Common.xcs b/officecfg/registry/schema/org/openoffice/Office/Common.xcs
index 2830a61082ba..d1bd76e1fffe 100644
--- a/officecfg/registry/schema/org/openoffice/Office/Common.xcs
+++ b/officecfg/registry/schema/org/openoffice/Office/Common.xcs
@@ -5391,6 +5391,13 @@
         </info>
         <value>false</value>
       </prop>
+      <prop oor:name="CrashReport" oor:type="xs:boolean" oor:nillable="false">
+        <!-- UIHints: Tools - Options - General -->
+        <info>
+          <desc>Enable sending crash reports to The Document Foundation</desc>
+        </info>
+        <value>true</value>
+      </prop>
       <prop oor:name="UseOpenCL" oor:type="xs:boolean" oor:nillable="false">
         <info>
           <desc>Determines whether OpenCL can be used, when available, to speed up


More information about the Libreoffice-commits mailing list