Starting QT app as a Systemd service
-
Hello QT Community,
I need to start my QT application without XFCE, Gnome, KDE, or what-so-ever desktop environment. I have disabled the lxdm.service (on my Toradex board running Angstrom Linux) and created a custom one that starts the X server only.
xserver.service
[Unit] Description=X Server Conflicts=getty@tty1.service plymouth-quit.service After=systemd-user-sessions.service getty@tty1.service plymouth-quit.service [Service] ExecStart=/usr/bin/X ExecStop=/usr/bin/killall -9 X Restart=always IgnoreSIGPIPE=no [Install] Alias=display-manager.service
This works perfectly. The other service is the QT application itself:
qtapp.service
[Unit] Description=QT Application After=xserver.service [Service] Type=simple ExecStart=/opt/TestQtApp ExecStop=/bin/bash -c 'pkill TestQtApp' Restart=always IgnoreSIGPIPE=no [Install] Alias=qtapp.servic
However, it won’t start due to some enviroment issue. The log in the journal looks like this:
Jan 07 14:58:57 apalis-imx6 systemd[1]: Started QT Application. Jan 07 14:58:57 apalis-imx6 TestQtApp[607]: QML debugging is enabled. Only use this in a safe environment. Jan 07 14:58:57 apalis-imx6 TestQtApp[607]: QStandardPaths: XDG_RUNTIME_DIR not set, defaulting to '/tmp/runtime-root' Jan 07 14:58:57 apalis-imx6 TestQtApp[607]: qt.qpa.screen: QXcbConnection: Could not connect to display Jan 07 14:58:57 apalis-imx6 TestQtApp[607]: Could not connect to any X display. Jan 07 14:58:57 apalis-imx6 systemd[1]: qtapp.service: Main process exited, code=exited, status=1/FAILURE Jan 07 14:58:57 apalis-imx6 systemd[1]: qtapp.service: Unit entered failed state. Jan 07 14:58:57 apalis-imx6 systemd[1]: qtapp.service: Failed with result 'exit-code'. Jan 07 14:58:57 apalis-imx6 systemd[1]: qtapp.service: Service hold-off time over, scheduling restart. Jan 07 14:58:57 apalis-imx6 systemd[1]: Stopped QT Application. Jan 07 14:58:57 apalis-imx6 systemd[1]: Started QT Application.
Merging the commands for starting the X server and the QT application within a single service behaves similarly - I see the X process running, but not the QT application.
Logging into the Bash shell and executing the "ExecStart" commands manually launches the QT application correctly.
May someone advise on this?
Thank you in advance!
-
What kind of application is this?
Jan 07 14:58:57 apalis-imx6 TestQtApp[607]: qt.qpa.screen: QXcbConnection: Could not connect to display
Jan 07 14:58:57 apalis-imx6 TestQtApp[607]: Could not connect to any X display.
AFAIK you cant start a
QGuiApplication
without any running X-Server -
@vmetodiev said in Starting QT app as a Systemd service:
Merging the commands for starting the X server and the QT application within a single service behaves similarly - I see the X process running, but not the QT application.
Logging into the Bash shell and executing the "ExecStart" commands manually launches the QT application correctly.
May someone advise on this?
Thank you in advance!If you want to daemonize your application, you must use
QCoreApplication
and notQGuiApplication
orQApplication
.You could add a startup parameter to select appropriated base class:
int startGraphicVersion(int argc, char *argv[]) { QGuiApplication app(argc, argv); ... return app.exec(); } int startAsService(int argc, char *argv[]) { QCoreApplication app(argc, argv); ... return app.exec(); } int main(int argc, char *argv[]) { int returnCode = -1; if(argc > 1 && strcmp(argv[1], "-daemon") == 0) { returnCode = startAsService(argc, argv); } else { returnCode = startGraphicVersion(argc, argv); } return returnCode; }
-
Hi,
Do you even need to have X running ? Wouldn't using the eglfs backend be simpler and less power hungry on your board ?
That said, you should start your application with the QT_DEBUG_PLUGINS environment variable set to 1 to see exactly what is going wrong.
For example, the DISPLAY environment variable might be set to an invalid value.
-
Well, here is a snippet from my main function:
int main(int argc, char *argv[]) { QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling); QGuiApplication app(argc, argv); QQmlApplicationEngine engine; ... }
I will read a bit more about QCore and QGui... now it is some kind of a Frankenstein :D
Yes, I always start the X server before attempting to launch the QT application.
It also starts correctly as a systemd service.About "eglfs" - thanks for mentioning this, I will read about it as well and write another post. I have no idea what you are taking about right now.
Thank you guys for your support and informative directions!
-
@vmetodiev said in Starting QT app as a Systemd service:
I agree! My goal is to make the GUI application start as a service with only the X server running beneath it, without LXDE or any other desktop environment.
I am just struggling how to achieve it no additional overhead...So you want to start you Qt QML/QWidget application with SystemD and X-Server.
Your error looks very similar to this ==> https://community.toradex.com/t/starting-qt-app-as-a-systemd-service/15954So I guess you have to change qtapp.service to setup
QT_QPA_PLATFORM
.
Something like this:[Unit] Description=QT Application After=xserver.service [Service] Type=simple Environment="QT_QPA_PLATFORM=wayland-egl" ExecStart=/opt/TestQtApp ExecStop=/bin/bash -c 'pkill TestQtApp' Restart=always IgnoreSIGPIPE=no [Install] Alias=qtapp.service
-
@vmetodiev said in Starting QT app as a Systemd service:
Jan 07 14:58:57 apalis-imx6 TestQtApp[607]: qt.qpa.screen: QXcbConnection: Could not connect to display
Jan 07 14:58:57 apalis-imx6 TestQtApp[607]: Could not connect to any X display.i think you are just missing the "DISPLAY=:0" env variable?
try it manually by calling
DISPLAY=:0 /opt/TestQtApp
-
@KroMignon
Your error looks very similar to this ==> https://community.toradex.com/t/starting-qt-app-as-a-systemd-service/15954
-> Absolutely :D It was posted by me in the Toradex forum, than I switched here...Environment="QT_QPA_PLATFORM=wayland-egl"
-> As far I understand, in this case the QT app will work with Wayland instead of the X server, correct?@raven-worx
Well, I added it as an enviroment and achived a certain progress.root@apalis-imx6:~# cat /lib/systemd/system/qtapp.service [Unit] Description=QT Application After=xserver.service [Service] Type=simple Environment="DISPLAY=:0" ExecStart=/opt/TestQtApp ExecStop=/bin/bash -c 'pkill TestQtApp' Restart=always IgnoreSIGPIPE=no [Install] Alias=qtapp.service
The service now starts when I manually invoke it by "systemctl start qtapp".
Nevertheless, it won't start automatically after reboot. The journal log is empty. Maybe the "After=xserver.service" is not quite correct? -
@vmetodiev
do you start the xserver service manually?
if not you are also missingRequire=xserver.service
so it is ensured that its running when your qt app gets startedalso to start it after reboot, you have to call
systemctl enable qtapp
-
Yes, the service is enabled. Well, I added "Requires=xserver.service", but still the qtapp.service would not start.
The xserver is fine upon reboot, visible inside "ps -auxf".
Invoking " systemctl start qtapp" start the Qt app...
-
Maybe this service example might help.
-
@vmetodiev said in Starting QT app as a Systemd service:
Invoking " systemctl start qtapp" start the Qt app...
I am far a way to be a systemd expert, so I may be wrong.
But I guess you have to addWantedBy=multi-user.target
in the[Install]
section to start the service automatically. -
@KroMignon said in Starting QT app as a Systemd service:
But I guess you have to add WantedBy=multi-user.target in the [Install] section to start the service automatically.
yep, thats true, good catch
-
@SGaist @KroMignon
Yes, your suggestions helped. Now it works perfectly. Thank you so much for your support!!!I am providing the service files below:
xserver.service
[Unit] Description=X Server Conflicts=getty@tty1.service plymouth-quit.service After=systemd-user-sessions.service getty@tty1.service plymouth-quit.service [Service] ExecStart=/usr/bin/X ExecStop=/usr/bin/killall -9 X Restart=always IgnoreSIGPIPE=no [Install] Alias=display-manager.service
qtapp.service
[Unit] Description=QT Application Requires=xserver.service After=xserver.service [Service] Type=simple Environment="DISPLAY=:0" ExecStart=/opt/TestQtApp ExecStop=/bin/bash -c 'pkill TestQtApp' Restart=always IgnoreSIGPIPE=no [Install] WantedBy=multi-user.target
-