Esempio n. 1
0
intptr_t DefaultAssertionHandler(intptr_t /*userParameter*/, const char* title, const char* message)
{
    if(OVRIsDebuggerPresent())
    {
        OVR_DEBUG_BREAK;
    }
    else
    {
        #if defined(OVR_BUILD_DEBUG)
            // Print a stack trace of all threads.
            OVR::String s;
            OVR::String threadListOutput;
            static OVR::SymbolLookup symbolLookup;

            s = "Failure: "; 
            s += message;

            if(symbolLookup.Initialize() && symbolLookup.ReportThreadCallstack(threadListOutput, 4)) // This '4' is there to skip our internal handling and retrieve starting at the assertion location (our caller) only.
            {
                s += "\r\n\r\n";
                s += threadListOutput;
            }

            OVR::Util::DisplayMessageBox(title, s.ToCStr());
        #else
            OVR::Util::DisplayMessageBox(title, message);
        #endif
    }
    
    return 0;
}
Esempio n. 2
0
intptr_t DefaultAssertionHandler(intptr_t /*userParameter*/, const char* title, const char* message)
{
    if(OVRIsDebuggerPresent())
    {
        OVR_DEBUG_BREAK;
    }
    else
    {
        OVR_UNUSED(title);
        OVR_UNUSED(message);

        #if defined(OVR_BUILD_DEBUG)
            if(Allocator::GetInstance()) // The code below currently depends on having a valid Allocator.
            {
                // Print a stack trace of all threads.
                OVR::String s;
                OVR::String threadListOutput;
                static OVR::SymbolLookup symbolLookup;

                s = "Failure: ";
                s += message;

                if(symbolLookup.Initialize() && symbolLookup.ReportThreadCallstack(threadListOutput, 4)) // This '4' is there to skip our internal handling and retrieve starting at the assertion location (our caller) only.
                {
                    // threadListOutput has newlines that are merely \n, whereas Windows MessageBox wants \r\n newlines. So we insert \r in front of all \n.
                    for(size_t i = 0, iEnd = threadListOutput.GetSize(); i < iEnd; i++)
                    {
                        if(threadListOutput[i] == '\n')
                        {
                            threadListOutput.Insert("\r", i, 1);
                            ++i;
                            ++iEnd;
                        }
                    }

                    s += "\r\n\r\n";
                    s += threadListOutput;
                }

                OVR::Util::DisplayMessageBox(title, s.ToCStr());
            }
            else
            {
                OVR::Util::DisplayMessageBox(title, message);
            }
        #else
            OVR::Util::DisplayMessageBox(title, message);
        #endif
    }

    return 0;
}
int WatchDogObserver::Run()
{
    OVR_DEBUG_LOG(("[WatchDogObserver] Starting"));

    SetThreadName("WatchDog");

    while (!TerminationEvent.Wait(WakeupInterval))
    {
        Lock::Locker locker(&ListLock);

        const uint32_t t1 = GetFastMsTime();

        const int count = DogList.GetSizeI();
        for (int i = 0; i < count; ++i)
        {
            WatchDog* dog = DogList[i];

            const int threshold = dog->ThreshholdMilliseconds;
            const uint32_t t0 = dog->WhenLastFedMilliseconds;

            // If threshold exceeded, assume there is thread deadlock of some sort.
            int delta = (int)(t1 - t0);
            if (delta > threshold)
            {
                // Expected behavior:
                // SingleProcessDebug, SingleProcessRelease, Debug: This is only ever done for internal testing, so we don't want it to trigger the deadlock termination.
                // Release: This is our release configuration where we want it to terminate itself.

                // Print a stack trace of all threads if there's no debugger present.
                const bool debuggerPresent = OVRIsDebuggerPresent();

                LogError("{ERR-027} [WatchDogObserver] Deadlock detected: %s", dog->ThreadName.ToCStr());
                if (!debuggerPresent) // We don't print threads if a debugger is present because otherwise every time the developer paused the app to debug, it would spit out a long thread trace upon resuming.
                {
                    if (SymbolLookup::Initialize())
                    {
                        // symbolLookup is static here to avoid putting 32 KB on the stack
                        // and potentially overflowing the stack.  This function is only ever
                        // run by one thread so it should be safe.
                        static SymbolLookup symbolLookup;
                        String threadListOutput, moduleListOutput;
                        symbolLookup.ReportThreadCallstacks(threadListOutput);
                        symbolLookup.ReportModuleInformation(moduleListOutput);
                        LogError("---DEADLOCK STATE---\n\n%s\n\n%s\n---END OF DEADLOCK STATE---", threadListOutput.ToCStr(), moduleListOutput.ToCStr());
                    }

                    if (IsReporting)
                    {
                        ExceptionHandler::ReportDeadlock(DogList[i]->ThreadName, OrganizationName , ApplicationName);

                        // Disable reporting after the first deadlock report.
                        IsReporting = false;
                    }
                }

                if (IsExitingOnDeadlock())
                {
                    OVR_ASSERT_M(false, "Watchdog detected a deadlock. Exiting the process."); // This won't have an effect unless asserts are enabled in release builds.
                    OVR::ExitProcess(-1);
                }
            }
        }
    }

    OVR_DEBUG_LOG(("[WatchDogObserver] Good night"));

    return 0;
}