From 4adb13c9435baade511d3ac78fb142dc73bd2e1f Mon Sep 17 00:00:00 2001 From: Eran Mizrahi Date: Fri, 8 Dec 2017 18:24:06 +0200 Subject: generate dumps using new diagnostics settings --- src/main.cpp | 79 ++++++++++---------------------------------------- src/mainwindow.cpp | 2 +- src/organizercore.cpp | 23 +++++++++++++-- src/organizercore.h | 7 ++++- src/settings.cpp | 2 +- src/usvfsconnector.cpp | 36 ++++++++++++++++------- src/usvfsconnector.h | 4 ++- 7 files changed, 73 insertions(+), 80 deletions(-) (limited to 'src') diff --git a/src/main.cpp b/src/main.cpp index 526563a2..71fbc943 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -48,6 +48,7 @@ along with Mod Organizer. If not, see . #include #include +#include #include #include @@ -127,71 +128,17 @@ bool isNxmLink(const QString &link) static LONG WINAPI MyUnhandledExceptionFilter(struct _EXCEPTION_POINTERS *exceptionPtrs) { - typedef BOOL (WINAPI *FuncMiniDumpWriteDump)(HANDLE process, DWORD pid, HANDLE file, MINIDUMP_TYPE dumpType, - const PMINIDUMP_EXCEPTION_INFORMATION exceptionParam, - const PMINIDUMP_USER_STREAM_INFORMATION userStreamParam, - const PMINIDUMP_CALLBACK_INFORMATION callbackParam); - LONG result = EXCEPTION_CONTINUE_SEARCH; - - HMODULE dbgDLL = ::LoadLibrary(L"dbghelp.dll"); - - static const int errorLen = 200; - char errorBuffer[errorLen + 1]; - memset(errorBuffer, '\0', errorLen + 1); - - if (dbgDLL) { - FuncMiniDumpWriteDump funcDump = (FuncMiniDumpWriteDump)::GetProcAddress(dbgDLL, "MiniDumpWriteDump"); - if (funcDump) { - QString dataPath = qApp->property("dataPath").toString(); - QString exeName = QFileInfo(qApp->applicationFilePath()).fileName(); - QString dumpName = dataPath + "/" + exeName + ".dmp"; - - if (QMessageBox::question(nullptr, QObject::tr("Woops"), - QObject::tr("ModOrganizer has crashed! " - "Should a diagnostic file be created? " - "If you send me this file (%1) to modorganizer@gmail.com, " - "the bug is a lot more likely to be fixed. " - "Please include a short description of what you were " - "doing when the crash happened" - ).arg(dumpName), - QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes) { - - HANDLE dumpFile = ::CreateFile(dumpName.toStdWString().c_str(), - GENERIC_WRITE, FILE_SHARE_WRITE, nullptr, - CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr); - if (dumpFile != INVALID_HANDLE_VALUE) { - _MINIDUMP_EXCEPTION_INFORMATION exceptionInfo; - exceptionInfo.ThreadId = ::GetCurrentThreadId(); - exceptionInfo.ExceptionPointers = exceptionPtrs; - exceptionInfo.ClientPointers = false; - - BOOL success = funcDump(::GetCurrentProcess(), ::GetCurrentProcessId(), dumpFile, - MiniDumpNormal, &exceptionInfo, nullptr, nullptr); - - ::FlushFileBuffers(dumpFile); - ::CloseHandle(dumpFile); - if (success) { - return EXCEPTION_EXECUTE_HANDLER; - } - _snprintf(errorBuffer, errorLen, "failed to save minidump to %ls (error %lu)", - dumpName.toStdWString().c_str(), ::GetLastError()); - } else { - _snprintf(errorBuffer, errorLen, "failed to create %ls (error %lu)", - dumpName.toStdWString().c_str(), ::GetLastError()); - } - } else { - return result; - } - } else { - _snprintf(errorBuffer, errorLen, "dbghelp.dll outdated"); - } - } else { - _snprintf(errorBuffer, errorLen, "dbghelp.dll not found"); + const std::wstring& dumpPath = OrganizerCore::crashDumpsPath(); + int dumpRes = + CreateMiniDump(exceptionPtrs, OrganizerCore::getGlobalCrashDumpsType(), dumpPath.c_str()); + if (!dumpRes) { + qCritical("ModOrganizer has crashed, crash dump created."); + return EXCEPTION_EXECUTE_HANDLER; + } + else { + qCritical("ModOrganizer has crashed, CreateMiniDump failed (%d, error %lu).", dumpRes, GetLastError()); + return EXCEPTION_CONTINUE_SEARCH; } - - QMessageBox::critical(nullptr, QObject::tr("Woops"), - QObject::tr("ModOrganizer has crashed! Unfortunately I was not able to write a diagnostic file: %1").arg(errorBuffer)); - return result; } static bool HaveWriteAccess(const std::wstring &path) @@ -448,6 +395,10 @@ int runApplication(MOApplication &application, SingleInstance &instance, QSettings settings(dataPath + "/" + QString::fromStdWString(AppConfig::iniFileName()), QSettings::IniFormat); + + // global crashDumpType sits in OrganizerCore to make a bit less ugly to update it when the settings are changed during runtime + OrganizerCore::setGlobalCrashDumpsType(settings.value("Settings/crash_dumps_type", static_cast(CrashDumpsType::Mini)).toInt()); + qDebug("initializing core"); OrganizerCore organizer(settings); if (!organizer.bootstrap()) { diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 48dfdfbd..cab4c41f 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -3296,7 +3296,7 @@ void MainWindow::on_actionSettings_triggered() updateDownloadListDelegate(); - m_OrganizerCore.setLogLevel(settings.logLevel()); + m_OrganizerCore.updateVFSParams(settings.logLevel(), settings.crashDumpsType()); } diff --git a/src/organizercore.cpp b/src/organizercore.cpp index f8a368c9..adb895ec 100644 --- a/src/organizercore.cpp +++ b/src/organizercore.cpp @@ -47,6 +47,7 @@ #include // for qPrintable, etc #include +#include #include // for _tcsicmp #include @@ -66,6 +67,9 @@ using namespace MOShared; using namespace MOBase; +//static +CrashDumpsType OrganizerCore::m_globalCrashDumpsType = CrashDumpsType::None; + static bool isOnline() { QList interfaces = QNetworkInterface::allInterfaces(); @@ -643,8 +647,23 @@ void OrganizerCore::prepareVFS() m_USVFS.updateMapping(fileMapping(m_CurrentProfile->name(), QString())); } -void OrganizerCore::setLogLevel(int logLevel) { - m_USVFS.setLogLevel(logLevel); +void OrganizerCore::updateVFSParams(int logLevel, int crashDumpsType) { + setGlobalCrashDumpsType(crashDumpsType); + m_USVFS.updateParams(logLevel, crashDumpsType); +} + +//static +void OrganizerCore::setGlobalCrashDumpsType(int crashDumpsType) { + m_globalCrashDumpsType = ::crashDumpsType(crashDumpsType); +} + +//static +std::wstring OrganizerCore::crashDumpsPath() { + wchar_t appDataLocal[MAX_PATH]{ 0 }; + ::SHGetFolderPathW(NULL, CSIDL_LOCAL_APPDATA, NULL, 0, appDataLocal); + std::wstring dumpPath{ appDataLocal }; + dumpPath += L"\\modorganizer"; + return dumpPath; } void OrganizerCore::setCurrentProfile(const QString &profileName) diff --git a/src/organizercore.h b/src/organizercore.h index 297b94f6..7bb7faa7 100644 --- a/src/organizercore.h +++ b/src/organizercore.h @@ -158,7 +158,11 @@ public: void prepareVFS(); - void setLogLevel(int logLevel); + void updateVFSParams(int logLevel, int crashDumpsType); + + static CrashDumpsType getGlobalCrashDumpsType() { return m_globalCrashDumpsType; } + static void setGlobalCrashDumpsType(int crashDumpsType); + static std::wstring crashDumpsPath(); public: MOBase::IModRepositoryBridge *createNexusBridge() const; @@ -319,6 +323,7 @@ private: MOBase::DelayedFileWriter m_PluginListsWriter; UsvfsConnector m_USVFS; + static CrashDumpsType m_globalCrashDumpsType; }; #endif // ORGANIZERCORE_H diff --git a/src/settings.cpp b/src/settings.cpp index 7d90d861..05a62591 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -28,7 +28,7 @@ along with Mod Organizer. If not, see . #include #include #include -#include +#include #include #include diff --git a/src/usvfsconnector.cpp b/src/usvfsconnector.cpp index 0420ddc2..b90784d9 100644 --- a/src/usvfsconnector.cpp +++ b/src/usvfsconnector.cpp @@ -19,6 +19,8 @@ along with Mod Organizer. If not, see . #include "usvfsconnector.h" #include "settings.h" +#include "organizercore.h" +#include "shared/util.h" #include #include #include @@ -27,6 +29,7 @@ along with Mod Organizer. If not, see . #include #include #include +#include static const char SHMID[] = "mod_organizer_instance"; @@ -101,14 +104,33 @@ LogLevel logLevel(int level) } } +CrashDumpsType crashDumpsType(int type) +{ + switch (type) { + case CrashDumpsType::Mini: + return CrashDumpsType::Mini; + case CrashDumpsType::Data: + return CrashDumpsType::Data; + case CrashDumpsType::Full: + return CrashDumpsType::Full; + default: + return CrashDumpsType::None; + } +} + UsvfsConnector::UsvfsConnector() { USVFSParameters params; LogLevel level = logLevel(Settings::instance().logLevel()); - USVFSInitParameters(¶ms, SHMID, false, level); + CrashDumpsType dumpType = crashDumpsType(Settings::instance().crashDumpsType()); + + std::string dumpPath = MOShared::ToString(OrganizerCore::crashDumpsPath(), true); + USVFSInitParameters(¶ms, SHMID, false, level, dumpType, dumpPath.c_str()); InitLogging(false); + + qDebug("Initializing VFS <%s, %d, %d, %s>", params.instanceName, params.logLevel, params.crashDumpsType, params.crashDumpsPath); + CreateVFS(¶ms); - SetLogLevel(level); BlacklistExecutable(L"TSVNCache.exe"); @@ -165,12 +187,6 @@ void UsvfsConnector::updateMapping(const MappingType &mapping) */ } -void UsvfsConnector::setLogLevel(int logLevel) { - switch (logLevel) { - case LogLevel::Debug: SetLogLevel(LogLevel::Debug); break; - case LogLevel::Info: SetLogLevel(LogLevel::Info); break; - case LogLevel::Warning: SetLogLevel(LogLevel::Warning); break; - case LogLevel::Error: SetLogLevel(LogLevel::Error); break; - default: SetLogLevel(LogLevel::Debug); break; - } +void UsvfsConnector::updateParams(int logLevel, int crashDumpsType) { + USVFSUpdateParams(::logLevel(logLevel), ::crashDumpsType(crashDumpsType)); } diff --git a/src/usvfsconnector.h b/src/usvfsconnector.h index 8f723a01..0935bac1 100644 --- a/src/usvfsconnector.h +++ b/src/usvfsconnector.h @@ -27,6 +27,7 @@ along with Mod Organizer. If not, see . #include #include #include +#include class LogWorker : public QThread { @@ -67,7 +68,7 @@ public: ~UsvfsConnector(); void updateMapping(const MappingType &mapping); - void setLogLevel(int logLevel); + void updateParams(int logLevel, int crashDumpsType); private: @@ -76,5 +77,6 @@ private: }; +CrashDumpsType crashDumpsType(int type); #endif // USVFSCONNECTOR_H -- cgit v1.3.1