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,
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
5 Likes
Apologies for reopening this old thread, but I believe it could help others trying to integrate Sentry into their plugins.
I’ve successfully installed the dynamic Sentry library and added the crash handler (Crashpad).
I can manually log events without any issues, but none of my crashes are being automatically reported to Sentry.
I even tried testing an automatic crash report in a production version without a debugger attached, but nothing happened either.
Is this the expected behavior? Have you experienced something similar?
Are you using the JUCE setApplicationCrashHandler function to catch crashes and then manually logging an event with a fatal or error level?
From my understanding, Sentry is supposed to automatically log crashes, so I’m a bit confused.
Any clarification would be appreciated!
Thanks
Hi @DEADBEEF!
I’ve only integrated sentry into the Windows version of my application - not the plug-in - as at the time, I couldn’t figure out how to do it.
At app start-up, I simply call:
sentry_options_t* options = sentry_options_new();
sentry_options_set_release(options, ...);
sentry_options_set_dsn(options, ...);
Very importantly: I found that I couldn’t rely on the default folder - or the crashes are not uploadable in my packaged application, even though it works with non-packaged applications - at a guess, I wouldn’t be surprised if you find that adding code like this resolves your issue.
So, my next few lines are like this:
wchar_t wTempFolder[2048];
wTempFolder[0] = 0;
GetTempPathW((DWORD)sizeof(wTempFolder), wTempFolder);
wcscat(wTempFolder, L"\\myapp_crashfolder");
{
int lRes = SHCreateDirectoryExW(nullptr, wTempFolder.c_str(), nullptr);
if (lRes == ERROR_FILE_EXISTS) {
IM_ASSERT(0);
} else if (lRes == ERROR_ALREADY_EXISTS) {
} else if (lRes == ERROR_SUCCESS) {
} else if (lRes == ERROR_PATH_NOT_FOUND) {
IM_ASSERT(0);
} else {
IM_ASSERT(0);
}
}
sentry_options_set_database_path(options, tempFolder);
I then finish the set-up…
sentry_init(options);
NB the code above has been tweaked for sharing here, so might need another tweak to compile.
I’d be very interested to hear if you could get it working - good luck!
Best wishes, Pete
Thanks a lot for the information @peteatjuce
I managed to upload the crash by switching the backend from Crashpad to Breakpad (and using static libraries).
However, I’m encountering an unusable error with the following message:
<unknown> Unhandled Invalid Minidump
Is there something specific I need to do to generate a valid minidump?
It’s strange because manually triggering the event gives me a proper issue with the related backtrace. 
@DEADBEEF sorry, not something I’ve seen before!
I must say that, pondering this, I’m surprised that it is possible to install a crash reporter in the context of a VST3. I’d have thought any such system might interfere with that of the plug-in host that is running the VST3?
Just FWIW: on Apple platforms, I’m happy to report that Xcode automatically reports crashes, even for AUv3 implementations (macOS, iOS).Some things are much simpler in Apple land than for Windows developers 
Best wishes,
Pete