JUCEApplication::initialiseApp() and questions


#1

In my application, exceptions are fatal (with one special case, boost::thread_interrupted is non-terminal). I use an exception to indicate that the application can no longer continue. I put enough information into the exception to report a fancy string to the user.

What I want to do, is have a bullet-proof way of showing the user an AlertWindow detailing the exception. When this AlertWindow appears, it is necessary to kill the entire application process so that nothing can run and cause re-entrancy, or repeating asserts/exceptions, etc…

Therefore, my solution is to launch a second instance of my application to display the AlertWindow, using command line parameters. This way, I can get the dialog up no matter what, and forcefully terminate the faulty original instance.

Here are the questions:

  1. How can I use Juce to launch the second instance?

I have to return false moreThanOneInstanceAllowed() in order for the second instance to get into initialise(), but I still don’t want two instances under regular conditions. Therefore, I am going to make a copy of the code in JUCEApplication::initialiseApp() that creates the InterProcessLock, and put the code copy in my initialise() so I can return false from moreThanOneInstanceAllowed() but still prevent multiple normal launches.

  1. Why the" #if ! JUCE_IOS" in JUCEApplication::initialiseApp()?

  2. Does MacOS allow me to launch the second instance, or does MacOS simply not allow the same app to launch twice?

Anything else I should know about?


#2

I don’t see any call to CreateProcess() anywhere in the Juce code…


#3

Using a second process:
I’m doing this, and it works, but not like you’re explaining. You need to start the 2nd process at the beginning, since when you get an exception, the heap can be crashed (most of the time), and the File.startAsProcess method can’t start anything anymore.
I’ve used IPC to communicate, since it doesn’t require any allocation for this (done on initialization).
Cons: You’re eating some memory for this second process.
Pros: Can be put in a signal / exception handler, so it’s stateless.

Using the initial process:
This is not cross platform, so I’m going to explain per platform.
Windows: This is quite easy, you only need to wrap your thread in SEH code,(__try / __except block), and put a ::MessageBox(…) call, that’ll work since it doesn’t require any heap allocation, and stack is reserved in __except scope.
You can trigger a minidump report generation too (search on codeproject for example code).

Linux: This is tricky, since you no longer can rely on X session’s pointer. I’ve done a workaround this way: I’m vforking my process in the signal handler (it’s crashed, but I can still vfork, since no allocation is required), and then, I execute a crashreport process that simply output the command line to a X window. On the other side, the parent is then unregistering the signal handler, so on exit of the current signal handler, the process will resume at the crashing instruction, and a core file will be generated. The crashreport process pack this core to a Zip file, so the consumer can send this to me.

Mac: I don’t know, never done anything on Mac.

Also, if you don’t care about your dependencies, Google has a very good crashdump reporter, called Breakpad.


#4

Hello File::startAsProcess()! Great looking function, thanks!

But why wouldn’t startAsProcess() work all the time? At least under Windows, all it does is call ShellExecute(), which typically always works. Even under X-Windows, I’m not doing anything fancy just launching another process - faulty X apps can’t interfere with other isolate X-app processes…or can they?

I’m just gonna startAsProcess() with a command line to show the error dialog and then force terminate the original process and see where that gets me.