backtrace for rc-63

This commit is contained in:
Atlante45 2018-01-22 17:17:48 -08:00 committed by Seth Alves
parent 88f66f03cc
commit 39f26e35f0
5 changed files with 107 additions and 23 deletions

View file

@ -600,7 +600,23 @@ bool setupEssentials(int& argc, char** argv, bool runningMarkerExisted) {
qApp->setProperty(hifi::properties::APP_LOCAL_DATA_PATH, cacheDir); qApp->setProperty(hifi::properties::APP_LOCAL_DATA_PATH, cacheDir);
} }
Setting::init(); // FIXME fix the OSX installer to install the resources.rcc binary instead of resource files and remove
// this conditional exclusion
#if !defined(Q_OS_OSX)
{
#if defined(Q_OS_ANDROID)
const QString resourcesBinaryFile = QStandardPaths::writableLocation(QStandardPaths::CacheLocation) + "/resources.rcc";
#else
const QString resourcesBinaryFile = QCoreApplication::applicationDirPath() + "/resources.rcc";
#endif
if (!QFile::exists(resourcesBinaryFile)) {
throw std::runtime_error("Unable to find primary resources");
}
if (!QResource::registerResource(resourcesBinaryFile)) {
throw std::runtime_error("Unable to load primary resources");
}
}
#endif
// Tell the plugin manager about our statically linked plugins // Tell the plugin manager about our statically linked plugins
auto pluginManager = PluginManager::getInstance(); auto pluginManager = PluginManager::getInstance();

View file

@ -57,6 +57,13 @@ int main(int argc, const char* argv[]) {
QCoreApplication::setOrganizationDomain(BuildInfo::ORGANIZATION_DOMAIN); QCoreApplication::setOrganizationDomain(BuildInfo::ORGANIZATION_DOMAIN);
QCoreApplication::setApplicationVersion(BuildInfo::VERSION); QCoreApplication::setApplicationVersion(BuildInfo::VERSION);
Setting::init();
// Instance UserActivityLogger now that the settings are loaded
auto& ual = UserActivityLogger::getInstance();
qDebug() << "UserActivityLogger is enabled:" << ual.isEnabled();
QStringList arguments; QStringList arguments;
for (int i = 0; i < argc; ++i) { for (int i = 0; i < argc; ++i) {
arguments << argv[i]; arguments << argv[i];

View file

@ -20,12 +20,13 @@
#include "SettingHelpers.h" #include "SettingHelpers.h"
#include "SettingManager.h" #include "SettingManager.h"
#include "SharedLogging.h" #include "SharedLogging.h"
#include "SharedUtil.h"
namespace Setting { namespace Setting {
static QSharedPointer<Manager> globalManager; static QSharedPointer<Manager> globalManager;
// cleans up the settings private instance. Should only be run once at closing down. // cleans up the settings private instance. Should only be run once at closing down.
void cleanupPrivateInstance() { static void cleanupPrivateInstance() {
// grab the thread before we nuke the instance // grab the thread before we nuke the instance
QThread* settingsManagerThread = DependencyManager::get<Manager>()->thread(); QThread* settingsManagerThread = DependencyManager::get<Manager>()->thread();
@ -34,12 +35,30 @@ namespace Setting {
// //
globalManager.reset(); globalManager.reset();
// quit the settings manager thread and wait on it to make sure it's gone // quit the settings manager thread and wait on it to make sure it's gone
settingsManagerThread->quit(); settingsManagerThread->quit();
settingsManagerThread->wait(); settingsManagerThread->wait();
} }
static void setupPrivateInstance() {
// Let's set up the settings Private instance on its own thread
QThread* thread = new QThread();
Q_CHECK_PTR(thread);
thread->setObjectName("Settings Thread");
QObject::connect(thread, SIGNAL(started()), globalManager.data(), SLOT(startTimer()));
QObject::connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater()));
QObject::connect(thread, SIGNAL(finished()), globalManager.data(), SLOT(deleteLater()));
globalManager->moveToThread(thread);
thread->start();
qCDebug(shared) << "Settings thread started.";
// Register cleanupPrivateInstance to run inside QCoreApplication's destructor.
qAddPostRoutine(cleanupPrivateInstance);
}
FIXED_Q_COREAPP_STARTUP_FUNCTION(setupPrivateInstance)
// Sets up the settings private instance. Should only be run once at startup. preInit() must be run beforehand, // Sets up the settings private instance. Should only be run once at startup. preInit() must be run beforehand,
void init() { void init() {
// Set settings format // Set settings format
@ -59,23 +78,7 @@ namespace Setting {
qCDebug(shared) << (deleted ? "Deleted" : "Failed to delete") << "settings lock file" << settingsLockFilename; qCDebug(shared) << (deleted ? "Deleted" : "Failed to delete") << "settings lock file" << settingsLockFilename;
} }
// Let's set up the settings Private instance on its own thread
QThread* thread = new QThread();
Q_CHECK_PTR(thread);
thread->setObjectName("Settings Thread");
globalManager = DependencyManager::set<Manager>(); globalManager = DependencyManager::set<Manager>();
QObject::connect(thread, SIGNAL(started()), globalManager.data(), SLOT(startTimer()));
QObject::connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater()));
QObject::connect(thread, SIGNAL(finished()), globalManager.data(), SLOT(deleteLater()));
globalManager->moveToThread(thread);
thread->start();
qCDebug(shared) << "Settings thread started.";
// Register cleanupPrivateInstance to run inside QCoreApplication's destructor.
qAddPostRoutine(cleanupPrivateInstance);
} }
void Interface::init() { void Interface::init() {

View file

@ -20,6 +20,7 @@
#include <mutex> #include <mutex>
#include <thread> #include <thread>
#include <set> #include <set>
#include <unordered_map>
#include <glm/glm.hpp> #include <glm/glm.hpp>
@ -62,6 +63,43 @@ extern "C" FILE * __cdecl __iob_func(void) {
#include "OctalCode.h" #include "OctalCode.h"
#include "SharedLogging.h" #include "SharedLogging.h"
static std::unordered_map<std::string, QVariant> stagedGlobalInstances;
std::mutex& globalInstancesMutex() {
static std::mutex mutex;
return mutex;
}
static void commitGlobalInstances() {
std::unique_lock<std::mutex> lock(globalInstancesMutex());
for (const auto& it : stagedGlobalInstances) {
qApp->setProperty(it.first.c_str(), it.second);
}
stagedGlobalInstances.clear();
}
FIXED_Q_COREAPP_STARTUP_FUNCTION(commitGlobalInstances)
QVariant getGlobalInstance(const char* propertyName) {
if (qApp) {
return qApp->property(propertyName);
} else {
auto it = stagedGlobalInstances.find(propertyName);
if (it != stagedGlobalInstances.end()) {
return it->second;
}
}
return QVariant();
}
void setGlobalInstance(const char* propertyName, const QVariant& variant) {
if (qApp) {
qApp->setProperty(propertyName, variant);
} else {
stagedGlobalInstances[propertyName] = variant;
}
}
static qint64 usecTimestampNowAdjust = 0; // in usec static qint64 usecTimestampNowAdjust = 0; // in usec
void usecTimestampNowForceClockSkew(qint64 clockSkew) { void usecTimestampNowForceClockSkew(qint64 clockSkew) {
::usecTimestampNowAdjust = clockSkew; ::usecTimestampNowAdjust = clockSkew;

View file

@ -25,6 +25,22 @@
#include <QtCore/QCoreApplication> #include <QtCore/QCoreApplication>
#include <QUuid> #include <QUuid>
// Workaround for https://bugreports.qt.io/browse/QTBUG-54479
// Wrap target function inside another function that holds
// a unique string identifier and uses it to ensure it only runs once
// by storing a state within the qApp
// We cannot used std::call_once with a static once_flag because
// this is used in shared libraries that are linked by several DLLs
// (ie. plugins), meaning the static will be useless in that case
#define FIXED_Q_COREAPP_STARTUP_FUNCTION(AFUNC) \
static void AFUNC ## _fixed() { \
const auto propertyName = std::string(Q_FUNC_INFO) + __FILE__; \
if (!qApp->property(propertyName.c_str()).toBool()) { \
AFUNC(); \
qApp->setProperty(propertyName.c_str(), QVariant(true)); \
} \
} \
Q_COREAPP_STARTUP_FUNCTION(AFUNC ## _fixed)
// When writing out avatarEntities to a QByteArray, if the parentID is the ID of MyAvatar, use this ID instead. This allows // When writing out avatarEntities to a QByteArray, if the parentID is the ID of MyAvatar, use this ID instead. This allows
// the value to be reset when the sessionID changes. // the value to be reset when the sessionID changes.
@ -52,6 +68,10 @@ bool destroyGlobalInstance() {
return false; return false;
} }
std::mutex& globalInstancesMutex();
QVariant getGlobalInstance(const char* propertyName);
void setGlobalInstance(const char* propertyName, const QVariant& variant);
// Provides efficient access to a named global type. By storing the value // Provides efficient access to a named global type. By storing the value
// in the QApplication by name we can implement the singleton pattern and // in the QApplication by name we can implement the singleton pattern and
// have the single instance function across DLL boundaries. // have the single instance function across DLL boundaries.
@ -60,9 +80,9 @@ T* globalInstance(const char* propertyName, Args&&... args) {
static T* resultInstance { nullptr }; static T* resultInstance { nullptr };
static std::mutex mutex; static std::mutex mutex;
if (!resultInstance) { if (!resultInstance) {
std::unique_lock<std::mutex> lock(mutex); std::unique_lock<std::mutex> lock(globalInstancesMutex());
if (!resultInstance) { if (!resultInstance) {
auto variant = qApp->property(propertyName); auto variant = getGlobalInstance(propertyName);
if (variant.isNull()) { if (variant.isNull()) {
std::unique_ptr<T>& instancePtr = globalInstancePointer<T>(); std::unique_ptr<T>& instancePtr = globalInstancePointer<T>();
if (!instancePtr.get()) { if (!instancePtr.get()) {
@ -72,7 +92,7 @@ T* globalInstance(const char* propertyName, Args&&... args) {
} }
void* voidInstance = &(*instancePtr); void* voidInstance = &(*instancePtr);
variant = QVariant::fromValue(voidInstance); variant = QVariant::fromValue(voidInstance);
qApp->setProperty(propertyName, variant); setGlobalInstance(propertyName, variant);
} }
void* returnedVoidInstance = variant.value<void*>(); void* returnedVoidInstance = variant.value<void*>();
resultInstance = static_cast<T*>(returnedVoidInstance); resultInstance = static_cast<T*>(returnedVoidInstance);