QCommandLineParser: suspend execution if built-in options were processed - c++

I am developing a Qt 5.x application whose main function is more or less like that (simplified):
int main(int argc, char *argv[])
{
QApplication app(arg, argv);
QCommandLineParser cmdLineParser;
cmdLineParser.addHelpOption();
cmdLineParser.addVersionOption();
cmdLineParser.process(app);
/// *** SOME INITIALIZATION STUFF *** ///
app.exec();
}
I am experiencing some problems when I invoke the execution of application specifying the --version (or --help) option on command line: the application outputs the version (or the help) and then sometimes terminates with a segmentation fault...
I think it is due to the fact that when QCommandLineParser detects a built-in option on command line (--version or --help) simply calls QApplication's exit() for terminating the execution and this interferes with my own *** SOME INITIALIZATION STUFF *** (basically some other threads are started and maybe a prematurely call on exit() causes some problems)...
However, my question is: is it possible to make Qt avoid to go further in my *** SOME INITIALIZATION STUFF *** if a built-in option is detected on command line? In other words, is there a method to be called for knowing that a built-in option has been detected by the command line parser? Otherwise: is there a method for knowing that exit() has been called on application, and hence the application is terminating? If so, it would suffice to enclose my *** SOME INITIALIZATION STUFF *** in a if condition argumenting on that method and it would be fine...
Thanks for the support.
>> EDIT <<
I've done some further investigations... the behavior seems not be dependent on my own *** SOME INITIALIZATION STUFF ***... in fact even a "minimal, complete and verifiable example" as the following one sometimes terminates the execution with segmentation fault when the executable is triggered with --version on the command line:
#include <QApplication>
#include <QCommandLineParser>
int main(int argc, char *argv[])
{
// Instantiate the application
QApplication app(argc, argv);
app.setApplicationVersion("1.0.0");
// Prepare for parsing the command line
QCommandLineParser cmdLineParser;
cmdLineParser.setApplicationDescription("Test application");
// Add support for command line standard options (help & version)
cmdLineParser.addHelpOption();
cmdLineParser.addVersionOption();
// Perform actual parsing of command line
cmdLineParser.process(app);
// Let the application run
return app.exec();
}
Just to clarify, I am using Qt 5.3.2 on an ARM device running Linux OS.

Related

QProcess does not signal stdout ready

When I launch xfreerdp process out of shell, it prints INFO messages to stdout and WARN/ERROR messages to stderr, as expected (this is just the default /log-level:info mode).
However, when I launch it via QProcess, the QProcess only signals with readyReadStandardError(), i.e. allowing me to read WARN/ERROR messages but never signals with readyReadStandardOutput(). Only when the process finishes (I close the xfreerdp window), the signal is emitted by QProcess and all the stdout is read by me (I have no idea, where was it kept all the way long?)
I have found two topics concerning the problem:
Qt: How to get live output of a running QProcess
stdout from QProcess is nowhere near realtime
I tried solutions proposed there:
1). I tried to use QIODevice::ReadWrite | QIODevice::Unbuffered as the third argument of QProcess::start(). It did not help -- same as it is described by the links.
2). I tried to call QProcess::readAllStandardOutput() every 100ms using QTimer. However, when I read this way, the output byte array is always empty (until the process is finished). So again, same as told by by the links, it did not help.
When I launch xfreerdp with QProcess with /log-level:debug or /log-level:trace, the problem does not hold. I get signals of stdout being ready. But there are lots and lots of DEBUG/TRACE messages.
I search for a way to solve the problem. But if I don't find it, I have two options: either to use the default /log-level:info option or /log-level:debug option. The first one is preferable for me but I am afraid that all that stdout is stuck somewhere and I would get with an overflow of some buffer and the whole thing would crash or it would be like a memory leak (maybe, I will try to explore QProcess source code). The second one is so here, probably, a better option, but the debug mode of xfreerdp is really quite too verbose.
UPDATE with the minimal reproducible example:
Alas, one need a vm to connect to.
If one launches the example (I have checked on Fedora 35 and Fedora 33), one will see that xfreerdp will output the INFO messages only after one will close the xfreerdp window, i.e., only after the process finishes.
//
// main.cpp
// g++ -o main main.cpp -std=c++11 -I/usr/include/qt5 -L/usr/lib64 -lQt5Widgets -lQt5Core
//
#include "QtWidgets/QApplication"
#include "QtCore/QProcess"
int main(int argc, char* argv[])
{
QApplication app{argc, argv};
QProcess p;
QObject::connect(&p, &QProcess::readyReadStandardOutput, [&](){
printf("%s", p.readAllStandardOutput().constData());
});
p.start("xfreerdp", {"/u:user", "/p:123456", "/v:10.38.31.133", "/cert:tofu"});
app.exec();
return 0;
}
I am sorry I was mistaken not to post the minimal reproducible example at once. Maybe, I should close the question and create a new once, so that more people could see it?
In your program, QProcess will do like works as entered in the terminal this command :
For seeing the result better I checked open in Terminal in the Run section of Qt Creator:
So I do this in Qt and add some changes to your code:
#include "QtWidgets/QApplication"
#include "QtCore/QProcess"
int main(int argc, char *argv[])
{
QApplication app { argc, argv };
QProcess *p = new QProcess();
QStringList pArgs;
pArgs << "/u:user" << "/p:123456" << "/v:10.38.31.133" << "/cert:tofu";
p->setProgram(QString("xfreerdp"));
p->setArguments(pArgs);
p->start();
QObject::connect(p, &QProcess::readyReadStandardOutput, [&]()
{
// printf("%s", p->readAllStandardOutput().constData());
qDebug() << p->readAllStandardOutput().constData() << Qt::endl;
});
app.exec();
return 0;
}
you should take Arguments to QProcess by using QStringList.
As I test it takes 15 to 16 seconds delay to show you results but this is my results:

Launching a second Linux program and exit current one from C/C++?

Is it possible from a C or C++ Linux program (say /usr/bin/foo), to programmatically launch another program (say /usr/bin/bar), and have foo exit normally and for bar to keep running?
system(3) isn't suitable as it blocks until the other program completes. I'd like something that returns immediately.
The programs are both GUI programs, but I suspect that isn't relevant.
Is there anything in Qt or boost::process that can help?
Is there any common Linux wrapper program I could run through system(3) to achieve this? I tried xdg-open but I don't think it's the right thing.
Basically I want the second program to "detach" from the first, and behave as if the user launched it via the system UI. (On MacOS, for example, there is an open command, so it would be like system("open /usr/bin/bar"))
With Qt, you can use bool QProcess::startDetached(const QString &program, const QStringList &arguments, const QString &workingDirectory = QString(), qint64 *pid = nullptr) as described here https://doc.qt.io/qt-5/qprocess.html#startDetached
Here is a minimal example of how to use it :
#include <QCoreApplication>
#include <QProcess>
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
/*
* starting netstat with args
* in case the main event loop is exited
* netstat will be parented to init ( pid 1 ) and continue running
*/
QProcess::startDetached("/bin/netstat", QStringList() << "-pla" << "-ntuc");
return a.exec();
}
The classic way is using Fork-Exec: https://en.wikipedia.org/wiki/Fork%E2%80%93exec which is available in any Unix derived OS, including Linux. No need to add any library, framework, etc.

gtkmm glib gio critical

On running the following simple.cc example for gtkmm
#include <gtkmm.h>
int main(int argc, char * argv[]){
Glib::RefPtr<Gtk::Application> app
= Gtk::Application::create(argc,argv,"org.gtkmm..examples.base");
Gtk::Window window;
//Gtk::ApplicationWindow window(app);
return app->run(window);
}
I face the following message:
(process:9428): GLib-GIO-CRITICAL **: g_application_set_application_id: assertion `application_id == NULL || g_application_id_is_valid (application_id)' failed
However, the application doesn't break, the window is produced and doesn't exit until I ctr+C the program.
What are the implications of this GLib-GIO-Critical message ? What do I do to suppress the message ?
If the provided application-id is not valid then it will not be set. I'm not familiar with the glibmm bits, but if you don't provide an ID to g_application_new then, according to the documentation, "...some features of GApplication (most notably application uniqueness) will be disabled."
"Suppressing" it is easy--just fix it. Provide a valid application ID or don't provide one at all (pass NULL instead of a string). In your example, getting rid of the extra dot ("org.gtkmm.examples.base" instead of "org.gtkmm..examples.base") should do the trick. The g_application_id_is_valid documentation explains what constitutes a valid ID, including that "Application identifiers must not contain consecutive '.' (period) characters."
I'm glad with the explanation in the solution but .. based on that just pass an empty string "". However "org.gtkmm.example" should work

freeglut fails to open display with valgrind

I'm running the Eclipse IDE on Ubuntu 12.04 with the Valgrind plugin. I've been working on a game in C++ for quite some time, and I seem to have a memory error somewhere. Normally, I trace these with Valgrind. However, glut fails to initialize when I run valgrind. I should note that the game initializes without a problem when I'm not using valgrind. The code for my main function is as follows:
int main(int argc, char** argv) {
char windowTitle[12] = "Game Window";
printf("Initializing Glut...\n");
glutInit(&argc, argv);
printf("Glut initialized!\n");
alutInit(&argc, argv);
Game_Object* game = new Game_Object(windowTitle, 1200, 675, argc, argv);
delete game;
printf("game ended\n");
return 0;
}
The resulting output to the console is:
Initializing Glut
freeglut (/home/dsnettleton/Documents/Programming/Eclipse/workspace/Plutoids/Debug/Plutoids): failed to open display ''
Obviously, the program isn't getting very far with valgrind running.
It's really disheartening to be in such a final stage of my development, only to get stuck trying to weed out a memory error. What might be keeping glut from initializing, and what can I do to fix the problem?
This is my guess: your IDE is probably missing the $DISPLAY environment variable. Somewhere you have to configure the environment to set $DISPLAY before launching Valgrind.
Launch a terminal and echo $DISPLAY. Its value is probably :0.0.
In the worst case, I'd try using setenv() inside the C code or set DISPLAY in the command line that launches Valgrind (none of these cases was tested, they may not work).
Also you have to add this environment variable DISPLAY:=0.0 inside Eclipse.
In the launch configuration of your executable, add a Display variable to the Environment tab, or select to inherit environment.
Run->RunConfiguration...->Environment
Now click on
New
and add
DISPLAY :0
in it

Why isn't my C++/Qt program doing anything?

I wrote this program in Qt Creator but I'm not sure how to run it. Here is my code:
#include <QtCore/QCoreApplication>
using namespace std;
#include <iostream>
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
string str;
cin >> str;
cout << " str is : " << str;
return a.exec();
}
When I run it my console shows this:
Starting /home/hamed/qt programs/test3-build-desktop/test3...
...and nothing happens. What should I do?
When copy pasting your code, it runs for me as expected (well, it doesn't terminate, but runs). Here is what I did in command line:
cd testproject
qmake -project
qmake
make
./testproject
As mentioned in the comment above, Qt itself is a library, so you are probably referring to some IDE when saying running it from "within Qt" - behaviour there is solely dependent on what IDE you are using.
Update:
From your message
Starting /home/hamed/qt programs/test3-build-desktop/test3...
I assume that you are using the QtCreator IDE, which does not allow you to enter things to console when running. I don't know whether you can get it to do so, but it works if you enter your project directory in console and use ./projectname. The building part mentioned above will be handled by QtCreator.
Another update:
Check out this thread for information on how to get it to work directly from QtCreator.
nothing happens!!
Your program is expecting an input, as you written here:
cin >> str;
what should i do?
Just type in something and press enter.
Add QTimer::singleShot(0, &a, SLOT(quit())); before the line return a.exec(); and don't forget to #include <QtCore/QTimer> (or you can make life easier and import the everything #include <QtCore>).
The a.exec() enters an event loop which waits for an event; normally in the form of user input with a graphical user interface. This however is a command line program and there isn't really a way for a user to send an event so it sits and waits forever. This is useful for server type applications but not what you're doing here. :)
(Note, this is one of many reasons your application might appear to be doing nothing. You may need to follow several of these answers before your program does what you expect)