Qt WebEngine in a console application?
-
Hi,
I am trying to run a console application that is linked to Qt WebEngine and well... it just crashes. The backtrace is as follows:
QOpenGLContext::create() QtWebEngineCore::initialize() QCoreApplication::init() QCoreApplication::QCoreApplication() main()
Seeing that
QtWebEngineCore
creates an OpenGL context, I can't say that I am surprised that my application crashes, but is there a way to avoid this? I was hoping that passing-platform offscreen
to my application would work, but not only it doesn't, but as far as I know it would anyway not work on Windows.So, is it at all possible to use Qt WebEngine in a console application?
Before you ask, the reason I need to be able to do this is that my application relies on a plugin architecture and most of its plugins are GUI-based and some of them rely on Qt WebEngine. Now, for some of those plugins, I have corresponding console-based tests, and this is where my problem lies...
FWIW, it all works perfectly fine using Qt WebKit, but I am trying to upgrade to Qt 5.6 and this means having to switch to Qt WebEngine (unfortunately!)...
Cheers, Alan.
-
Ok, I have found a solution... not related to Qt WebEngine.
Basically, in my tests, I have a line that reads:
QTEST_GUILESS_MAIN(MyTest)
Well, the name says it all and explains why some of my tests crash. In other words, I have two choices. Either use
QTEST_MAIN(MyTest)
or
QTEST_APPLESS_MAIN(MyTest)
Ok, now back onto addressing other 'issues' with Qt WebEngine... :)
-
Ok, a bit more information on using Qt WebEngine in a console application...
Upon initialisation, Qt WebEngine creates an OpenGL context object and then creates the OpenGL context itself by calling
QOpenGLContext::create()
(seeQtWebEngineCore::initialize()
in[QtSources]/qtwebengine/src/webengine/api/qtwebengineglobal.cpp
). However, that second step requires having a GUI application. So, to do all of this with a CLI application will not work (read: it will crash your application).This being said, there is a way around it. You need to create your own OpenGL context object (but not its corresponding OpenGL context, obviously) and set it as your global OpenGL context object since Qt WebEngine will only create one if there isn't already a global one available.
In other words, you need to do something like the following:
... #include <QOpenGLContext> ... Q_GUI_EXPORT void qt_gl_set_global_share_context(QOpenGLContext *pContext); ... int main(int argc, char *argv[]) { QOpenGLContext *myOpenglContext = new QOpenGLContext(); qt_gl_set_global_share_context(myOpenglContext); ... qt_gl_set_global_share_context(0); delete myOpenglContext; }
Now back to running CLI tests that make use of one or several Qt WebEngine based libraries, you can use
QTEST_MAIN()
,QTEST_GUILESS_MAIN()
orQTEST_APPLESS_MAIN()
without any problem... as long as you keep the above in mind. -
Thank you for detailing your experience with this. I also ran into this crash on travis when updating to WebEngine from WebKit. We also are using --platform offscreen for unit testing. Adding my backtrace here as well to possibly help others with this same problem find this detailed solution easier.
==6200== Process terminating with default action of signal 11 (SIGSEGV)
==6200== Access not within mapped region at address 0xE0
==6200== at 0x15AAF8B8: ??? (in /opt/qt56/plugins/platforms/libqoffscreen.so)
==6200== by 0x15AAFC62: ??? (in /opt/qt56/plugins/platforms/libqoffscreen.so)
==6200== by 0x9FE63DC: QOpenGLContext::create() (in /opt/qt56/lib/libQt5Gui.so.5.6.2)
==6200== by 0x842AE53: QtWebEngineCore::initialize() (in /opt/qt56/lib/libQt5WebEngineCore.so.5.6.2)
==6200== by 0xA6C1357: QCoreApplicationPrivate::init() (in /opt/qt56/lib/libQt5Core.so.5.6.2)
==6200== by 0x9FA50FB: QGuiApplicationPrivate::init() (in /opt/qt56/lib/libQt5Gui.so.5.6.2)
==6200== by 0x999F6C8: QApplicationPrivate::init() (in /opt/qt56/lib/libQt5Widgets.so.5.6.2)
==6200== by 0x547145: main (main.cpp:81) -
@ericsium You are welcome, although I must confess that I have since given up on Qt WebEngine. At the time, at least, it just had too many limitations and issues for what I needed to do. So, in the end, I simply reverted to QtWebKit, which does everything I need and, this, without any problems (I am planning on upgrading to QtWebKit Reloaded at some point though).