Skip to content

Commit

Permalink
Merge pull request #1608 from jamescowens/fixwincrashduringinit
Browse files Browse the repository at this point in the history
Fix a spurious segmentation fault during client load on Windows with fast CPUs
  • Loading branch information
jamescowens committed Dec 11, 2019
2 parents 743a34c + b70ec15 commit a7c744e
Show file tree
Hide file tree
Showing 16 changed files with 232 additions and 100 deletions.
2 changes: 1 addition & 1 deletion src/global_objects_noui.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ extern int nBoincUtilization;
extern std::string sRegVer;
extern bool bForceUpdate;
extern bool fQtActive;
extern bool bGridcoinGUILoaded;
extern bool bGridcoinCoreInitComplete;

// Timers
extern std::map<std::string, int> mvTimers; // Contains event timers that reset after max ms duration iterator is exceeded
Expand Down
9 changes: 6 additions & 3 deletions src/gridcoinresearchd.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@ bool AppInit(int argc, char* argv[])

SetupEnvironment();

// Note every function above the InitLogging() call must use fprintf or similar.

ThreadHandlerPtr threads = std::make_shared<ThreadHandler>();
bool fRet = false;

Expand Down Expand Up @@ -95,6 +97,9 @@ bool AppInit(int argc, char* argv[])
/** Check here config file incase TestNet is set there and not in mapArgs **/
ReadConfigFile(mapArgs, mapMultiArgs);

// Initialize logging as early as possible.
InitLogging();

// Check to see if the user requested a snapshot and we are not running TestNet!
if (mapArgs.count("-snapshotdownload") && !mapArgs.count("-testnet"))
{
Expand All @@ -118,7 +123,7 @@ bool AppInit(int argc, char* argv[])

catch (std::runtime_error& e)
{
LogPrintf("Snapshot Downloader: Runtime exception occured in SanpshotMain() (%s)", e.what());
LogPrintf("Snapshot Downloader: Runtime exception occured in SnapshotMain() (%s)", e.what());

Snapshot.DeleteSnapshot();

Expand All @@ -143,8 +148,6 @@ bool AppInit(int argc, char* argv[])
exit(ret);
}

InitLogging();

fRet = AppInit2(threads);
}
catch (std::exception& e) {
Expand Down
50 changes: 20 additions & 30 deletions src/init.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -340,21 +340,11 @@ void InitLogging()

LogInstance().m_print_to_file = !IsArgNegated("-debuglogfile");
LogInstance().m_file_path = AbsPathForConfigVal(GetArg("-debuglogfile", DEFAULT_DEBUGLOGFILE));

//printf("LogInstance().m_file_path = %s\n", LogInstance().m_file_path.c_str());
//printf("LogInstance().m_print_to_file = %i\n", LogInstance().m_print_to_file);

LogInstance().m_print_to_console = fPrintToConsole;
LogInstance().m_log_timestamps = fLogTimestamps;
LogInstance().m_log_time_micros = GetBoolArg("-logtimemicros", DEFAULT_LOGTIMEMICROS);
LogInstance().m_log_threadnames = GetBoolArg("-logthreadnames", DEFAULT_LOGTHREADNAMES);

//BCLog::LogFlags flags = BCLog::LogFlags::ALL;

//LogInstance().EnableCategory(flags);

//printf("LogInstance().GetCategoryMask() = %x\n", LogInstance().GetCategoryMask());

fLogIPs = GetBoolArg("-logips", DEFAULT_LOGIPS);

if (LogInstance().m_print_to_file)
Expand Down Expand Up @@ -423,13 +413,13 @@ void InitLogging()
LogPrintf("Default data directory %s\n", GetDefaultDataDir().string());
LogPrintf("Using data directory %s\n", GetDataDir().string());

std::string version_string = FormatFullVersion();
std::string build_type;
#ifdef DEBUG
version_string += " (debug build)";
build_type = "debug build";
#else
version_string += " (release build)";
build_type = "release build";
#endif
LogPrintf(PACKAGE_NAME " version %s\n", version_string);
LogPrintf(PACKAGE_NAME " version %s (%s - %s)", FormatFullVersion(), build_type, CLIENT_DATE);
}


Expand All @@ -438,11 +428,16 @@ void ThreadAppInit2(ThreadHandlerPtr th)
{
// Make this thread recognisable
RenameThread("grc-appinit2");
bGridcoinGUILoaded=false;
LogPrintf("Initializing GUI...");

bGridcoinCoreInitComplete = false;

LogPrintf("Initializing Core...");

AppInit2(th);
LogPrintf("GUI Loaded...");
bGridcoinGUILoaded = true;

LogPrintf("Core Initialized...");

bGridcoinCoreInitComplete = true;
}


Expand Down Expand Up @@ -743,9 +738,6 @@ bool AppInit2(ThreadHandlerPtr threads)
}
#endif

ShrinkDebugFile();
LogPrintf("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n");
LogPrintf("Gridcoin version %s (%s)", FormatFullVersion(), CLIENT_DATE);
LogPrintf("Using OpenSSL version %s", SSLeay_version(SSLEAY_VERSION));
if (!fLogTimestamps)
LogPrintf("Startup time: %s", DateTimeStrFormat("%x %H:%M:%S", GetAdjustedTime()));
Expand All @@ -768,15 +760,6 @@ bool AppInit2(ThreadHandlerPtr threads)

int64_t nStart;


// Start the lightweight task scheduler thread
CScheduler::Function serviceLoop = std::bind(&CScheduler::serviceQueue, &scheduler);
threadGroup.create_thread(std::bind(&TraceThread<CScheduler::Function>, "scheduler", serviceLoop));

// TODO: Do we need this? It would require porting the Bitcoin signal handler.
// GetMainSignals().RegisterBackgroundSignalScheduler(scheduler);


// ********************************************************* Step 5: verify database integrity

uiInterface.InitMessage(_("Verifying database integrity..."));
Expand Down Expand Up @@ -1192,6 +1175,13 @@ bool AppInit2(ThreadHandlerPtr threads)
int64_t nBalanceInQuestion;
pwalletMain->FixSpentCoins(nMismatchSpent, nBalanceInQuestion);

// Start the lightweight task scheduler thread
CScheduler::Function serviceLoop = std::bind(&CScheduler::serviceQueue, &scheduler);
threadGroup.create_thread(std::bind(&TraceThread<CScheduler::Function>, "scheduler", serviceLoop));

// TODO: Do we need this? It would require porting the Bitcoin signal handler.
// GetMainSignals().RegisterBackgroundSignalScheduler(scheduler);

scheduler.scheduleEvery([]{
g_banman->DumpBanlist();
}, DUMP_BANS_INTERVAL * 1000);
Expand Down
2 changes: 1 addition & 1 deletion src/logging.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ bool BCLog::Logger::StartLogging()

// Add newlines to the logfile to distinguish this execution from the
// last one.
FileWriteStr("\n\n\n\n\n", m_fileout);
FileWriteStr("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n", m_fileout);
}

// dump buffered messages from before we opened the log
Expand Down
4 changes: 2 additions & 2 deletions src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ BlockFinder blockFinder;

bool bForceUpdate = false;
bool fQtActive = false;
bool bGridcoinGUILoaded = false;
bool bGridcoinCoreInitComplete = false;

extern void GetGlobalStatus();
bool PollIsActive(const std::string& poll_contract);
Expand Down Expand Up @@ -4781,7 +4781,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
unsigned int banscore_out = 0;

// Also don't send a manifest that is not current.
if (CScraperManifest::IsManifestAuthorized(manifest.pubkey, banscore_out) && manifest.IsManifestCurrent())
if (CScraperManifest::IsManifestAuthorized(manifest.nTime, manifest.pubkey, banscore_out) && manifest.IsManifestCurrent())
{
CScraperManifest::SendManifestTo(pfrom, inv.hash);
}
Expand Down
36 changes: 23 additions & 13 deletions src/qt/bitcoin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,7 @@ static std::string Translate(const char* psz)
void DebugMessageHandler(QtMsgType type, const char *msg)
{
if (type == QtDebugMsg) {
LogPrint("qt", "GUI: %s\n", msg);
LogPrint(BCLog::LogFlags::QT, "GUI: %s\n", msg);
} else {
LogPrintf("GUI: %s\n", msg);
}
Expand All @@ -181,7 +181,7 @@ void DebugMessageHandler(QtMsgType type, const QMessageLogContext& context, cons
{
Q_UNUSED(context);
if (type == QtDebugMsg) {
LogPrint("qt", "GUI: %s\n", msg.toStdString());
LogPrint(BCLog::LogFlags::QT, "GUI: %s\n", msg.toStdString());
} else {
LogPrintf("GUI: %s\n", msg.toStdString());
}
Expand Down Expand Up @@ -213,8 +213,7 @@ int main(int argc, char *argv[])

SetupEnvironment();

// Do this early as we don't want to bother initializing if we are just calling IPC
ipcScanRelay(argc, argv);
// Note every function above the InitLogging() call must use fprintf or similar.

// Command-line options take precedence:
// Before this would of been done in main then config file loaded.
Expand All @@ -223,6 +222,12 @@ int main(int argc, char *argv[])

ReadConfigFile(mapArgs, mapMultiArgs);

// Initialize logging as early as possible.
InitLogging();

// Do this early as we don't want to bother initializing if we are just calling IPC
ipcScanRelay(argc, argv);

// Here we do it if it was started with the snapshot argument and we not TestNet
if (mapArgs.count("-snapshotdownload") && !mapArgs.count("-testnet"))
{
Expand All @@ -245,7 +250,7 @@ int main(int argc, char *argv[])

catch (std::runtime_error& e)
{
LogPrintf("Snapshot Downloader: Runtime exception occured in SanpshotMain() (%s)", e.what());
LogPrintf("Snapshot Downloader: Runtime exception occured in SnapshotMain() (%s)", e.what());

Snapshot.DeleteSnapshot();

Expand Down Expand Up @@ -328,14 +333,15 @@ int StartGridcoinQt(int argc, char *argv[])
// Install qDebug() message handler to route to debug.log
qInstallMsgHandler(DebugMessageHandler);
#else
#if defined(WIN32)
// Install global event filter for processing Windows session related Windows messages (WM_QUERYENDSESSION and WM_ENDSESSION)
qApp->installNativeEventFilter(new WinShutdownMonitor());
#endif
// Install qDebug() message handler to route to debug.log
qInstallMessageHandler(DebugMessageHandler);
#endif

#if defined(WIN32) && QT_VERSION >= 0x050000
// Install global event filter for processing Windows session related Windows messages (WM_QUERYENDSESSION and WM_ENDSESSION)
app.installNativeEventFilter(new WinShutdownMonitor());
#endif

if (!boost::filesystem::is_directory(GetDataDir(false)))
{
QMessageBox::critical(0, "Gridcoin",
Expand All @@ -355,8 +361,6 @@ int StartGridcoinQt(int argc, char *argv[])
// ... then GUI settings:
OptionsModel optionsModel;

InitLogging();

// Get desired locale (e.g. "de_DE") from command line or use system locale
QString lang_territory = QString::fromStdString(GetArg("-lang", QLocale::system().name().toStdString()));
QString lang = lang_territory;
Expand Down Expand Up @@ -439,10 +443,14 @@ int StartGridcoinQt(int argc, char *argv[])
else
{
//10-31-2015
while (!bGridcoinGUILoaded)
while (!bGridcoinCoreInitComplete)
{
app.processEvents();
MilliSleep(300);

// The sleep here has to be pretty short to avoid a buffer overflow crash with
// fast CPUs due to too many events. It originally was set to 300 ms and has
// been reduced to 100 ms.
MilliSleep(100);
}

{
Expand Down Expand Up @@ -476,6 +484,8 @@ int StartGridcoinQt(int argc, char *argv[])
WinShutdownMonitor::registerShutdownBlockReason(QObject::tr("%1 didn't yet exit safely...").arg(QObject::tr(PACKAGE_NAME)), (HWND)window.winId());
#endif

LogPrintf("GUI loaded.");

app.exec();

window.hide();
Expand Down
2 changes: 1 addition & 1 deletion src/qt/qtipcserver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ static bool ipcScanCmd(int argc, char *argv[], bool fRelay)
// the first start of the first instance
if (ex.get_error_code() != boost::interprocess::not_found_error || !fRelay)
{
LogPrintf("main() - boost interprocess exception #%d: %s", ex.get_error_code(), ex.what());
fprintf(stderr, "main() - boost interprocess exception #%d: %s", ex.get_error_code(), ex.what());
break;
}
}
Expand Down
12 changes: 6 additions & 6 deletions src/qt/winshutdownmonitor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,12 @@ bool WinShutdownMonitor::nativeEventFilter(const QByteArray &eventType, void *pM

// Seed OpenSSL PRNG with Windows event data (e.g. mouse movements and other user interactions)
if (RAND_event(pMsg->message, pMsg->wParam, pMsg->lParam) == 0) {
// Warn only once as this is performance-critical
static bool warned = false;
if (!warned) {
LogPrintf("%s: OpenSSL RAND_event() failed to seed OpenSSL PRNG with enough data.\n", __func__);
warned = true;
}
// Warn only once as this is performance-critical
static bool warned = false;
if (!warned) {
LogPrintf("%s: OpenSSL RAND_event() failed to seed OpenSSL PRNG with enough data.\n", __func__);
warned = true;
}
}

switch(pMsg->message)
Expand Down
Loading

0 comments on commit a7c744e

Please sign in to comment.