Application as Daemon, With Graphical Needs (QCore- vs QGui-Application)
-
I have written an application that runs as a daemon on Linux, using QCoreApplication. All was well.
Recently, I had to add some relatively simple graphical processing to the application, where I needed to use QPainter and its functions like drawText(). This fell down in a hurry, and after some research I found that I needed to use QGuiApplication (vs QCoreApplication) to be able to perform these simple graphical processes. Upon making this switch, the application ran again.
However, now I can't run the application as a deamon anymore (it errors along the lines of not being able to connect to a display). This, because I'm not using QCoreApplication.
It seems that I'm stuck in the middle between using QCoreApplication (to daemonize) and using QGuiApplication (to perform graphical functions). Is there any way that I can achieve both?? Thanks.
-
@brny said in Application as Daemon, With Graphical Needs (QCore- vs QGui-Application):
Available platform plugins are: eglfs, linuxfb, minimal, minimalegl, offscreen, vnc, xcb.
Have you tried adding
-platform offscreen
to the command or setting the environment variableQT_QPA_PLATFORM=offscreen
? -
@brny
Indeed, a demon won't have any access to a display.where I needed to use QPainter and its functions like drawText()
The question is why did you need such a thing in your demon? You should not use these and you should not need
QGuiApplication
. -
@JonB said in Application as Daemon, With Graphical Needs (QCore- vs QGui-Application):
The question is why did you need such a thing in your demon? You should not use these and you should not need
QGuiApplication
.Good question. My application/daemon is starting to make some graphical products (currently output into image files on a share).
-
@brny
Yes, I can see the problem. You want to save images to file, but not have to use a display....Assuming you must therefore have a
QGuiApplication
, if it is doable I would guess/hope there is some way of instantiating that and telling it you don't have/need a display, or "fooling" it into thinking you do have one....it errors along the lines of not being able to connect to a display
I assume that happens on the
QGuiApplication app
line itself? What is the exact error message?Random mention, as I start to Google:
https://lists.qt-project.org/pipermail/development/2012-November/008099.htmlAt one point in time it was okay to have a QApplication/QGuiApplication as a daemon. However, as of Windows Vista, and more greatly enforced in later versions of Windows, Microsoft is severely curtailing the abilities of Services to have a GUI interface. As such it is really only valid on Windows to have a QCoreApplication-based Service/Daemon.
I don't think most *nix applications typically put a GUI on a daemon, so they probably don't run into that issue.
That was from 2012 :) So you can see maybe this is a problem...!
Read some of the posts in https://forum.qt.io/topic/133449/starting-qt-app-as-a-systemd-service. See what they are saying? Again, not good for you! One claims:
AFAIK you cant start a
QGuiApplication
without any running X-ServerIt looks complicated, but I think in the last post the OP said he got his
QGuiApplication
to work undersystemd
? -
@JonB, correct on all fronts. It just doesn't seem like it'd be that crazy of an idea to have a daemon needing to generate some graphics in files!
When running as a QGuiApplication app, it runs fine if I run it by itself from a command-line. But when I attempt to run it as a daemon (RHEL 8 in this case, using systemctl) I get the following error:
qt.qpa.xcb: Could not connect to display. qt.qpa.plugin: Could not load the Qt platform plugin "xcb" in "" even though it was found. This application failed to start because no Qt platform plugin could be initialized. Reinstalling the application may fix this problem. Available platform plugins are: eglfs, linuxfb, minimal, minimalegl, offscreen, vnc, xcb.
I'm going to keep digging as well, and see if I can find something to work. I appreciate your help, @jonB!
-
@brny
I appreciate your "reasonable" problem here, but do not know the solution.Do look at those threads I have mentioned in my previous post (I may have edited after you started). At one point I believe @SGaist mentions using
eglfs
, which you have, instead of X/xcb
. I have no idea how/whether you could do that, or whether it would help....Just btw, give a couple examples of the sort of GUI classes you are trying to use. Are you indeed doing something like manipulating images (
QImage
etc.) and then, what, saving pngs to file, or something? -
@JonB said in Application as Daemon, With Graphical Needs (QCore- vs QGui-Application):
@brny
Do look at those threads I have mentioned in my previous post (I may have edited after you started). At one point I believe @SGaist mentions usingeglfs
, which you have, instead of X/xcb
. I have no idea how/whether you could do that, or whether it would help....I agree, this is one angle that I am looking into. Admittedly, I'm not familiar with much in that area (yet!) but it may well be worth pursuing.
Just btw, give a couple examples of the sort of GUI classes you are trying to use. Are you indeed doing something like manipulating images (
QImage
etc.) and then, what, saving pngs to file, or something?In my case, I simply have a QImage that I am attempting to manipulate with QPainter. As soon as I try to call drawText() with the latter, is when it crashes (if I'm using QCoreApplication). And it works when I use QGuiApplication. In reduced form, this:
QImage temp_image(200,100,QImage::Format_MonoLSB); QPainter image_painter; image_painter.begin(&temp_image); image_painter.setRenderHint(QPainter::Antialiasing, true); image_painter.setPen(QPen(Qt::white, 1, Qt::SolidLine, Qt::RoundCap,Qt::MiterJoin)); image_painter.setBrush(QBrush(QColor::fromRgb(0,0,0), Qt::SolidPattern)); image_painter.fillRect(0,0,200,100,QBrush(QColor::fromRgb(0,0,0), Qt::SolidPattern)); QFont lbl_font("Arial",10,QFont::Normal); image_painter.setFont(lbl_font); QString label = "Test Text"; image_painter.drawText(10,20,label); // Application crashes here when run as QCoreApplication, works fine as QGuiApplication
Ultimately (after much else further down the line), this is getting written to a PNG as you mentioned.
-
@brny said in Application as Daemon, With Graphical Needs (QCore- vs QGui-Application):
Available platform plugins are: eglfs, linuxfb, minimal, minimalegl, offscreen, vnc, xcb.
Have you tried adding
-platform offscreen
to the command or setting the environment variableQT_QPA_PLATFORM=offscreen
? -
@mchinand said in Application as Daemon, With Graphical Needs (QCore- vs QGui-Application):
@brny said in Application as Daemon, With Graphical Needs (QCore- vs QGui-Application):
Available platform plugins are: eglfs, linuxfb, minimal, minimalegl, offscreen, vnc, xcb.
Have you tried adding
-platform offscreen
to the command or setting the environment variableQT_QPA_PLATFORM=offscreen
?@mchinand, I think this may have done the trick! I added "-platform offscreen" on my dev box and now the daemon launches and seems to persist (errors about connecting to the display are gone).
For other reasons, I can't do a full end-to-end test (and adequately exercise graphics operations downstream) until later in the day ... I will post back later with that result. Thank you and @JonB for your help!!!
-
@JonB it stands for Qt Platform Abstraction.
-
It's for offscreen rendering. Very useful for CI tests.
-
Re: [Application as Daemon](With Graphical Needs (QCore- vs QGui-Application))
Just to follow up, @mchinand 's solution of "-platform offscreen" worked for me. I was able to verify that it runs in our production environment, and was successful in exercising the underlying graphical functions that I was after (e.g. QPainter).
To summarize: A QGuiApplication app can indeed be daemonized, as long as "-platform offscreen" is added to the command at execution time, or variable QT_QPA_PLATFORM=offscreen is set.
Thanks for all of your help, friends!