Determine when QApplication will crash
-
My program can run on a server with no GUI, or on a desktop. When it runs on a system that can display GUIs I want to instantiate QApplication, and when it is on a server I want QCoreApplication.
If I instanciate QApplication on a server, it either Segfault (at least it used to), or display an error message and exit, without letting me the chance to instantiate QCoreApplication instead:
bq. This application failed to start because it could not find or load the Qt platform plugin "xcb". Available platform plugins are: linuxfb, minimal, offscreen. Reinstalling the application may fix this problem.
Currently I just pass a -noGui argument when I run my program on a server. It works fine, but I want to detect if the system can use QApplication or not.
I could launch a small program from my main one, see if it crashes when calling QApplication, and call QCoreApplication if it does. But that's dirty.
Is there a simple way in the framework to know if instantiating QApplication will fail ? -
If you are using *nix then the easiest way to test if a window manager is available or not (i.e. running headless) is to try and get a handle to an X display programatically. The following is a little test program that does just that:
@
#include <X11/Xlib.h>
#include <iostream>
using namespace std;bool isXRunning(void){
return XOpenDisplay(NULL)? true : false;
}int main(void){
cout << isXRunning() << endl;
return 0;
}
@You'll need to have the X11 development libraries installed if you've not got them already (sudo apt-get instal libx11-dev for example) and compile as follows:
@
g++ xtest.cpp -o xtest -L/usr/include/X11 -lX11
@The location of your dependancies may vary, but you get the idea.
Hope this helps ;o)
-
Thanks jazzycamel, that would work, but I don't want to rely on X11, or any other stuff.
I solved this issue by intercepting the SIGABRT signal sent by QApplication, and instantiate QCoreApplication instead. It works surprisingly well, and it is cross-platform.
@#include <QApplication>
#include <csetjmp>
#include <csignal>
#include <cstdlib>jmp_buf env;
void onSigabrt(int)
{
longjmp (env, 1);
}QCoreApplication *loadQt(bool gui)
{
QCoreApplication *application = NULL;if (gui) { if (setjmp(env) == 0) { signal(SIGABRT, &onSigabrt); application = new QApplication(); } signal(SIGABRT, SIG_DFL); } if (!application) application = new QCoreApplication(); return (application);
}@
-
Thanks jazzycamel, that would work, but I don't want to rely on X11, or any other stuff.
I solved this issue by intercepting the SIGABRT signal sent by QApplication, and instantiate QCoreApplication instead. It works surprisingly well, and it is cross-platform.
@#include <QApplication>
#include <csetjmp>
#include <csignal>
#include <cstdlib>jmp_buf env;
void onSigabrt(int)
{
longjmp (env, 1);
}QCoreApplication *loadQt(bool gui)
{
QCoreApplication *application = NULL;if (gui) { if (setjmp(env) == 0) { signal(SIGABRT, &onSigabrt); application = new QApplication(); } signal(SIGABRT, SIG_DFL); } if (!application) application = new QCoreApplication(); return (application);
}@
-
Testing for a crash to determine if you're running under a window manager seems scary to say the least. It's like trying to run to see if your leg is broken.
How do you know in what state the failed QApplication left the app? There might be leaked resources, hanging handles, half-initialized statics etc. I would never rely on something like that. If the app crashes it's for a reason. Don't just "skip the crash" and pretend nothing bad happened.
-
Testing for a crash to determine if you're running under a window manager seems scary to say the least. It's like trying to run to see if your leg is broken.
How do you know in what state the failed QApplication left the app? There might be leaked resources, hanging handles, half-initialized statics etc. I would never rely on something like that. If the app crashes it's for a reason. Don't just "skip the crash" and pretend nothing bad happened.
-
Good point, but this allows me to display a warning on the standard output, which tells the users that they should use the -noGui parameter, and explain the problem, which is way better than a random crash, with obscure plugin not found non sense.
That being said, maybe I should not allow the program to run normally after that, and make a fatal error, or even restart it myself with the -noGui option this time...
-
Good point, but this allows me to display a warning on the standard output, which tells the users that they should use the -noGui parameter, and explain the problem, which is way better than a random crash, with obscure plugin not found non sense.
That being said, maybe I should not allow the program to run normally after that, and make a fatal error, or even restart it myself with the -noGui option this time...
-
You seem to be hanged on the idea that you need to detect a crash. You don't. Forget about it. It's a bad idea.
You want to detect what environment your app is running in and act accordingly. Maybe reading environment variables can help you? IDK, I know little about Linux. -
You seem to be hanged on the idea that you need to detect a crash. You don't. Forget about it. It's a bad idea.
You want to detect what environment your app is running in and act accordingly. Maybe reading environment variables can help you? IDK, I know little about Linux.