Compare commits

...
19 Commits
Author SHA1 Message Date
isanae 1412befe1b Merge pull request #1198 from isanae/2_3_0
Remove RC
2020-08-17 01:48:22 -04:00
isanae e6e88074ea removed rc 2020-08-17 01:42:11 -04:00
isanae 2388f2471b Merge pull request #1195 from isanae/2_3_0
Cherry pick: die after dump
2020-08-13 14:48:35 -04:00
isanae 2c6c223cb0 bumped to 2.3.2rc2 2020-08-13 14:47:35 -04:00
isanae f16738ffd6 always call the previous terminate handler, which should abort
without it, execution just resumes and dumps are created endlessly
2020-08-13 14:46:47 -04:00
isanae f2dc4ddd30 Merge pull request #1189 from isanae/2_3_0
switched to 2.3.2-rc1
2020-08-12 06:23:19 -04:00
isanae 322b5d59f0 switched to 2.3.2-rc1 2020-08-12 06:22:28 -04:00
isanae 06d356e48f Merge pull request #1188 from isanae/2_3_0
bumped to 2.3.2
2020-08-12 04:26:19 -04:00
isanae 8db55c451c bumped to 2.3.2 2020-08-12 04:24:48 -04:00
isanae 768e6291b3 Merge pull request #1183 from AnyOldName3/cherry-pick-NexusBridgeFix
Cherry pick NexusBridge fix
2020-08-10 18:34:24 -04:00
AnyOldName3 2cdb7c5b13 Don't use reference as class member
This particular QString was only ever constructed from a temporary,
so it was literally never going to work. We only hadn't noticed this
earlier as no one had tried using the mod repository bridge from a
plugin before (which is fairly bad given that three people have
theoretically tested it while working on its Python bindings in the
past).
2020-08-08 14:18:14 +01:00
isanae b9f9e6af94 Merge pull request #1178 from isanae/2_3_0
Merge 2.3.1 changes
2020-08-01 11:33:35 -04:00
isanae b9078ffefd bump to 2.3.1 2020-08-01 11:29:09 -04:00
isanae 04c5986aa6 added startSafeThread() to get core dumps for threads other than the main thread
added terminate handler
2020-08-01 11:29:09 -04:00
isanae 1cb18b3c00 fixed warning when trying to get the file type of files without extensions 2020-08-01 11:29:09 -04:00
isanae e34a9e7315 Merge pull request #1172 from isanae/remove-prerelease
Chang release type to 0
2020-07-28 20:15:42 -04:00
isanae 4d546ea262 changed release type to 0 2020-07-28 20:15:12 -04:00
isanae 2ca7c1c9ea Merge pull request #1171 from isanae/bump-2.3
Bump to 2.3
2020-07-28 18:35:38 -04:00
isanae 4b0ba5c579 bumped to 2.3 2020-07-28 18:33:55 -04:00
8 changed files with 68 additions and 18 deletions
+2 -1
View File
@@ -1,6 +1,7 @@
#ifndef ENV_ENVFS_H
#define ENV_ENVFS_H
#include "thread_utils.h"
#include <thread>
namespace env
@@ -125,7 +126,7 @@ private:
ThreadInfo()
: busy(true), ready(false), stop(false)
{
thread = std::thread([&]{ run(); });
thread = MOShared::startSafeThread([&]{ run(); });
}
~ThreadInfo()
+1 -1
View File
@@ -40,7 +40,7 @@ const QString& directoryFileType()
const QString& cachedFileTypeNoExtension()
{
static const QString name = [] {
const DWORD flags = SHGFI_TYPENAME;
const DWORD flags = SHGFI_TYPENAME | SHGFI_USEFILEATTRIBUTES;
SHFILEINFOW sfi = {};
// dummy filename with no extension
+2 -1
View File
@@ -1,4 +1,5 @@
#include "iconfetcher.h"
#include "thread_utils.h"
#include "shared/util.h"
void IconFetcher::Waiter::wait()
@@ -25,7 +26,7 @@ IconFetcher::IconFetcher()
m_quickCache.file = getPixmapIcon(QFileIconProvider::File);
m_quickCache.directory = getPixmapIcon(QFileIconProvider::Folder);
m_thread = std::thread([&]{ threadFun(); });
m_thread = MOShared::startSafeThread([&]{ threadFun(); });
}
IconFetcher::~IconFetcher()
+33 -4
View File
@@ -127,9 +127,10 @@ bool bootstrap()
return true;
}
LPTOP_LEVEL_EXCEPTION_FILTER prevUnhandledExceptionFilter = nullptr;
thread_local LPTOP_LEVEL_EXCEPTION_FILTER prevUnhandledExceptionFilter = nullptr;
thread_local std::terminate_handler prevTerminateHandler = nullptr;
static LONG WINAPI MyUnhandledExceptionFilter(struct _EXCEPTION_POINTERS *exceptionPtrs)
LONG WINAPI MyUnhandledExceptionFilter(struct _EXCEPTION_POINTERS *exceptionPtrs)
{
const std::wstring& dumpPath = OrganizerCore::crashDumpsPath();
int dumpRes =
@@ -139,12 +140,39 @@ static LONG WINAPI MyUnhandledExceptionFilter(struct _EXCEPTION_POINTERS *except
else
log::error("ModOrganizer has crashed, CreateMiniDump failed ({}, error {}).", dumpRes, GetLastError());
if (prevUnhandledExceptionFilter)
if (prevUnhandledExceptionFilter && exceptionPtrs)
return prevUnhandledExceptionFilter(exceptionPtrs);
else
return EXCEPTION_CONTINUE_SEARCH;
}
void terminateHandler() noexcept
{
__try
{
// force an exception to get a valid stack trace for this thread
*(int*)0 = 42;
}
__except
(
MyUnhandledExceptionFilter(GetExceptionInformation()), EXCEPTION_EXECUTE_HANDLER
)
{
}
if (prevTerminateHandler) {
prevTerminateHandler();
} else {
std::abort();
}
}
void setUnhandledExceptionHandler()
{
prevUnhandledExceptionFilter = SetUnhandledExceptionFilter(MyUnhandledExceptionFilter);
prevTerminateHandler = std::set_terminate(terminateHandler);
}
// Parses the first parseArgCount arguments of the current process command line and returns
// them in parsedArgs, the rest of the command line is returned untouched.
LPCWSTR UntouchedCommandLineArguments(int parseArgCount, std::vector<std::wstring>& parsedArgs)
@@ -171,6 +199,7 @@ LPCWSTR UntouchedCommandLineArguments(int parseArgCount, std::vector<std::wstrin
return cmd;
}
static int SpawnWaitProcess(LPCWSTR workingDirectory, LPCWSTR commandLine) {
PROCESS_INFORMATION pi{ 0 };
STARTUPINFO si{ 0 };
@@ -947,7 +976,7 @@ int main(int argc, char *argv[])
application.setProperty("dataPath", dataPath);
// initialize dump collection only after "dataPath" since the crashes are stored under it
prevUnhandledExceptionFilter = SetUnhandledExceptionFilter(MyUnhandledExceptionFilter);
setUnhandledExceptionHandler();
const auto logFile =
qApp->property("dataPath").toString() + "/logs/mo_interface.log";
+4 -4
View File
@@ -221,7 +221,7 @@ void OrganizerCore::updateExecutablesList()
void OrganizerCore::updateModInfoFromDisc() {
ModInfo::updateFromDisc(
m_Settings.paths().mods(), &m_DirectoryStructure,
m_PluginContainer, m_Settings.interface().displayForeign(),
m_PluginContainer, m_Settings.interface().displayForeign(),
m_Settings.refreshThreadCount(), managedGame());
}
@@ -371,7 +371,7 @@ void OrganizerCore::downloadRequestedNXM(const QString &url)
}
}
void OrganizerCore::userInterfaceInitialized()
void OrganizerCore::userInterfaceInitialized()
{
m_UserInterfaceInitialized(m_UserInterface->mainWindow());
}
@@ -1139,7 +1139,7 @@ void OrganizerCore::refreshModList(bool saveChanges)
ModInfo::updateFromDisc(
m_Settings.paths().mods(), &m_DirectoryStructure,
m_PluginContainer, m_Settings.interface().displayForeign(),
m_PluginContainer, m_Settings.interface().displayForeign(),
m_Settings.refreshThreadCount(), managedGame());
m_CurrentProfile->refreshModStatus();
@@ -1473,7 +1473,7 @@ void OrganizerCore::directory_refreshed()
m_StructureDeleter.join();
}
m_StructureDeleter = std::thread([=]{
m_StructureDeleter = MOShared::startSafeThread([=]{
log::debug("structure deleter thread start");
delete newStructure;
log::debug("structure deleter thread done");
+1 -1
View File
@@ -65,7 +65,7 @@ private:
OrganizerCore *m_Proxied;
PluginContainer *m_PluginContainer;
const QString &m_PluginName;
QString m_PluginName;
};
+22 -3
View File
@@ -1,12 +1,31 @@
#ifndef MO2_THREAD_UTILS_H
#define MO2_THREAD_UTILS_H
#include <log.h>
#include <functional>
#include <mutex>
#include <thread>
// in main.cpp
void setUnhandledExceptionHandler();
LONG WINAPI MyUnhandledExceptionFilter(struct _EXCEPTION_POINTERS *exceptionPtrs);
namespace MOShared {
// starts an std::thread with an unhandled exception handler for core dumps
// and a top-level catch
//
template <class F>
std::thread startSafeThread(F&& f)
{
return std::thread([f=std::forward<F>(f)] {
setUnhandledExceptionHandler();
f();
});
}
/**
* Class that can be used to perform thread-safe memoization.
*
@@ -26,7 +45,7 @@ struct MemoizedLocked {
template <class Callable>
MemoizedLocked(Callable &&callable, T value = {}) :
m_Fn{ std::forward<Callable>(callable) }, m_Value{ std::move(value) } { }
template <class... Args>
T& value(Args&&... args) const {
if (m_NeedUpdating) {
@@ -66,7 +85,7 @@ private:
*
*/
template <class It, class Callable>
void parallelMap(It begin, It end, Callable callable, std::size_t nThreads)
void parallelMap(It begin, It end, Callable callable, std::size_t nThreads)
{
std::mutex m;
std::vector<std::thread> threads(nThreads);
@@ -75,7 +94,7 @@ void parallelMap(It begin, It end, Callable callable, std::size_t nThreads)
// - The mutex is only used to fetch/increment the iterator.
// - The callable is copied in each thread to avoid conflicts.
for (auto &thread: threads) {
thread = std::thread([&m, &begin, end, callable]() {
thread = startSafeThread([&m, &begin, end, callable]() {
while (true) {
decltype(begin) it;
{
+3 -3
View File
@@ -3,14 +3,14 @@
// If VS_FF_PRERELEASE is not set, MO labels the build as a release and uses VER_FILEVERSION to determine version number.
// Otherwise, if letters are used in VER_FILEVERSION_STR, uses the full MOBase::VersionInfo parser
// Otherwise, uses the numbers from VER_FILEVERSION and sets the release type as pre-alpha
#define VER_FILEVERSION 2,3,0
#define VER_FILEVERSION_STR "2.3.0rc2\0"
#define VER_FILEVERSION 2,3,2
#define VER_FILEVERSION_STR "2.3.2\0"
VS_VERSION_INFO VERSIONINFO
FILEVERSION VER_FILEVERSION
PRODUCTVERSION VER_FILEVERSION
FILEFLAGSMASK VS_FFI_FILEFLAGSMASK
FILEFLAGS VS_FF_PRERELEASE
FILEFLAGS (0)
FILEOS VOS__WINDOWS32
FILETYPE VFT_APP
FILESUBTYPE (0)