Crash reporting with Sentry

Hi,

I am trying to use Sentry Native c/c++ SDK to report crashes. The problem is the SDK provides sentry_shutdown() method which needs to be invoked to flush the report to the sentry server before the showdown of the JUCE app.

Could someone tell me where should I put this method? I tried showdown(), systemRequestedQuit(), and none of them are called before the crash…

The sentry_shutdown() can’t be called earlier because it will remove the sentry instance.

If there is no easy solution. Which crash reporting method should we use in juce?

Best,

I think you want SystemStats::setApplicationCrashHandler ( CrashHandlerFunction ) https://docs.juce.com/master/classSystemStats.html#a9eb84f54c8ebca7a24bb49e37226a82a

Thanks!

Do you have a code snippet to show how to use this function?

Put SystemStats::setApplicationCrashHandler ( CrashHandlerFunction ) in the MainWindow init? And define the SystemStats::CrashHandlerFunction = void()(void) to invoke the sentry_shutdown()?

Something like…

void myCrashHandler(void* platformSpecificCrashData)
{
    sentry_shutdown ();
}

AppClass::AppClass()
{
    SystemStats::setApplicationCrashHandler (crashHandler);
}

Thanks!

However, the myCrashHandler callback has not been invoked when I force a crash, such as using:

abort(); or
raise(SIGSEGV);

I put the function in

void myCrashHandler(void* platformSpecificCrashData)
{
sentry_shutdown();
}

class xxx_appApplication : public JUCEApplication
{
public:

xxx_appApplication() {}

const String getApplicationName() override       { return "xxx"; }
const String getApplicationVersion() override    { return "1.0.0"; }
bool moreThanOneInstanceAllowed() override       { return true; }

void initialise (const String& commandLine) override
{
    // This method is where you should put your application's initialisation code..

    SystemStats::setApplicationCrashHandler(myCrashHandler);

    mainWindow.reset (new MainWindow (getApplicationName()));

}

I don’t think abort is a crash. or raise for that matter… how about dereferencing a null pointer:

char* badPtr = 0;
*badPtr = 1;

Not invoke the callback either with the bad pointer…

Well, sorry to say, that’s about all the help I have… hopefully someone else with more experience with this can comment. I know I successfully used it in an app a few years ago, running on both Mac and Windows, where I dumped out the stack trace into a log file.

Thanks, the normal behavior should be when there is a crash, the callback funtion is invoked right? So the case is either my callback funtion is not set correctly or the crash is not the right type?

Yes. Per the docs:

setApplicationCrashHandler()

static void SystemStats::setApplicationCrashHandler ( CrashHandlerFunction ) static

Sets up a global callback function that will be called if the application executes some kind of illegal instruction.

You may want to call getStackBacktrace() in your handler function, to find out where the problem happened and log it, etc.

And, for completeness:

void SystemStats::setApplicationCrashHandler (CrashHandlerFunction handler)
{
    jassert (handler != nullptr); // This must be a valid function.
    globalCrashHandler = handler;

   #if JUCE_WINDOWS
    SetUnhandledExceptionFilter (handleCrash);
   #else
    const int signals[] = { SIGFPE, SIGILL, SIGSEGV, SIGBUS, SIGABRT, SIGSYS };

    for (int i = 0; i < numElementsInArray (signals); ++i)
    {
        ::signal (signals[i], handleCrash);
        juce_siginterrupt (signals[i], 1);
    }
   #endif
}

Thanks, I am in Windows. setApplicationCrashHandler will
SetUnhandledExceptionFilter (handleCrash);

https://docs.microsoft.com/en-us/windows/win32/api/errhandlingapi/nf-errhandlingapi-setunhandledexceptionfilter

I don’t understand this function. Will it filter out some exceptions?

Thanks, actually the callback got invoked. The problem is Sentry.

I put this into the callback, and it prints the stackbacktrace…

ofstream myfile;
myfile.open("D:\\xxx\\example.txt");
myfile << SystemStats::getStackBacktrace();
myfile.close();
1 Like

Hi folks,

Sorry I’m late to this.

Use this code for a cross-platform approach to force a crash:

// Force crash report for e.g. sentry.io!
int* crashPtr = nullptr;
*std::launder(crashPtr) = 0;
1 Like

Thanks not late!

Since I am still working with C++14 so I can’t use std::launder. (Tried using C++17, but it threw many errors, so I decide not to bother it at this moment)

Your force crash is dereferencing a nullptr right? I think mine does the same thing

unsigned char* test = NULL;
test[1000] = 'a'; //<< here it should crash

I am using breakpad backend for Sentry native SDK since it should work in Windows 10. Btw, I opened an issue in Sentry github https://github.com/getsentry/sentry-native/issues/358

Since it’s a sentry problem, we probably should discuss there…

No problem - I’ve made some suggestions in GitHub, hope they help… Pete

Should somebody end up on this via Google (like I did now), you may have a look an my project which has a working Sentry Native integration into a JUCE app. Just search the source code for the SENRY defines and it’ll give you an idea how to integrate it. It has been working fine for me for over half a year now.

Here is the link to the project: christofmuc/KnobKraft-orm: The KnobKraft Orm - The free modern cross-platform MIDI Sysex Librarian

2 Likes