QWebEngine not cleaning up Chromium processes and get a warning
-
Hi all,
I have an app with QtWebEngineWidgets, I have a QMainWindow subclass called WrapperWindow where I add a QWebEngineView, then I add a custom QWebEnginePage to that view that implements the createWindow method so, when a user selects the "Open link in new window" item from the context menu, it creates a new WrapperWindow with the QWebEngineView.
If I open a couple of windows, and then I start closing them, I see on the Windows Task Manager that the chromium processes are not being cleaned up, and when I close the application, on the Qt Creator application output, I get a bunch of warnings stating:Release of profile requested but WebEnginePage still not deleted. Expect troubles !
Do any of you know how to get QWebEngineView to correctly clean up Chromium?
Here is the code from my Window to create the QWebEngineView and Page:
WrapperWindow::WrapperWindow(QWidget *parent) : QMainWindow(parent) { WrapperWindow(parent, Q_NULLPTR); } WrapperWindow::WrapperWindow(QWidget *parent, EventAwareWebEnginePage *page) : QMainWindow(parent) { //setup the window main widget mainWidget = new QStackedWidget(); QWidget* layoutWidget = new QWidget(); QHBoxLayout* layout = new QHBoxLayout(); //setup the web view with the system events aware web page webView = new QWebEngineView(); if (page == Q_NULLPTR) { EventAwareWebEnginePage *enginePage = new EventAwareWebEnginePage(); webView->setPage(enginePage); webView->setUrl(QUrl("https://www.google.com")); } else webView->setPage(page); layout->addWidget(webView); //make the layout cover the whole window layout->setContentsMargins(0,0,0,0); layout->setSpacing(0); //layout widgets layoutWidget->setLayout(layout); mainWidget->addWidget(layoutWidget); setCentralWidget(mainWidget); this->setMinimumSize(QSize(800,600)); } void WrapperWindow::setPageUrl(const QUrl &url) { webView->setUrl(url); }
And here is the createWindow function from the custom WebEnginePage class called EventAwareWebEnginePage:
QWebEnginePage *EventAwareWebEnginePage::createWindow(WebWindowType type) { if (type == WebWindowType::WebBrowserWindow) { EventAwareWebEnginePage *page = new EventAwareWebEnginePage(); connect(page, &QWebEnginePage::urlChanged, [page](const QUrl &url) { WrapperWindow *w = new WrapperWindow(Q_NULLPTR, page); w->setPageUrl(url); w->show(); }); return page; } return Q_NULLPTR; }
-
Hi all,
I have an app with QtWebEngineWidgets, I have a QMainWindow subclass called WrapperWindow where I add a QWebEngineView, then I add a custom QWebEnginePage to that view that implements the createWindow method so, when a user selects the "Open link in new window" item from the context menu, it creates a new WrapperWindow with the QWebEngineView.
If I open a couple of windows, and then I start closing them, I see on the Windows Task Manager that the chromium processes are not being cleaned up, and when I close the application, on the Qt Creator application output, I get a bunch of warnings stating:Release of profile requested but WebEnginePage still not deleted. Expect troubles !
Do any of you know how to get QWebEngineView to correctly clean up Chromium?
Here is the code from my Window to create the QWebEngineView and Page:
WrapperWindow::WrapperWindow(QWidget *parent) : QMainWindow(parent) { WrapperWindow(parent, Q_NULLPTR); } WrapperWindow::WrapperWindow(QWidget *parent, EventAwareWebEnginePage *page) : QMainWindow(parent) { //setup the window main widget mainWidget = new QStackedWidget(); QWidget* layoutWidget = new QWidget(); QHBoxLayout* layout = new QHBoxLayout(); //setup the web view with the system events aware web page webView = new QWebEngineView(); if (page == Q_NULLPTR) { EventAwareWebEnginePage *enginePage = new EventAwareWebEnginePage(); webView->setPage(enginePage); webView->setUrl(QUrl("https://www.google.com")); } else webView->setPage(page); layout->addWidget(webView); //make the layout cover the whole window layout->setContentsMargins(0,0,0,0); layout->setSpacing(0); //layout widgets layoutWidget->setLayout(layout); mainWidget->addWidget(layoutWidget); setCentralWidget(mainWidget); this->setMinimumSize(QSize(800,600)); } void WrapperWindow::setPageUrl(const QUrl &url) { webView->setUrl(url); }
And here is the createWindow function from the custom WebEnginePage class called EventAwareWebEnginePage:
QWebEnginePage *EventAwareWebEnginePage::createWindow(WebWindowType type) { if (type == WebWindowType::WebBrowserWindow) { EventAwareWebEnginePage *page = new EventAwareWebEnginePage(); connect(page, &QWebEnginePage::urlChanged, [page](const QUrl &url) { WrapperWindow *w = new WrapperWindow(Q_NULLPTR, page); w->setPageUrl(url); w->show(); }); return page; } return Q_NULLPTR; }
@raulgd said in QWebEngine not cleaning up Chromium processes and get a warning:
Release of profile requested but WebEnginePage still not deleted. Expect troubles
It is worth Googling for that, there are a couple of hits which are worth reading to get some possible ideas.
This is off the wall: does it make any difference if you get rid of your lambda in the
connect()
and replace with an explicitly coded method? It may not matter from C++, but from Python it cannot release/clean up references properly if there is a lambda.I also found problems with
QWebEngine
pages not being released properly/processes hanging around from Python code, though I did not get an error message like you. I found thatQWebEngine
s once closed/deleted did not get correctly deallocated/deleted till I hit the main Qt loop again (e.g.deleteLater()
), though that may not be an issue for you.Food for thought :)
-
Thanks for the reply @JonB
The lambdas don't work the same way in C++ as in Python, in C++ they are generic functions referenced through a function pointer so there is no dangling object reference causing Qt reference counting cleanup to stay hanging (AFAIK, maybe some C++ expert could clarify this reasoning).
Also, if you notice, I reference the page pointer to the lambda as well, if I did a "traditional" signal/slot, I wouldn't be able to do so directly, which would make the implementation harder to read, I guess that's why Qt 5 added lambda support in the first place, to make things cleaner/simpler to implement.
But still, thanks for your time on this.
-
Ok, finally got it fixed, it was something stupid as expected... When closing a window, after going through the simplebrowser example, I wasn't calling the function deleteLater() from the QMainWindow on the closeEvent, so I implemented the closeEvent functions: event->accept and then deleteLater()
That did the trick, I hope that's helpful for anyone with the same issue.
Just as reference for anyone lost like me, here's how the project ended up looking:
wrapperwindow.cpp#include "wrapperwindow.h" #include <QApplication> #include <QStackedWidget> #include <QHBoxLayout> #include <QWebEngineView> #include <QMessageBox> #include <QCloseEvent> #include "eventawarewebenginepage.h" WrapperWindow::WrapperWindow(QWidget *parent) : QMainWindow(parent) { WrapperWindow(parent, Q_NULLPTR); } WrapperWindow::WrapperWindow(QWidget *parent, EventAwareWebEnginePage *page, const QUrl &url) : QMainWindow(parent) { //Basic window setup setMinimumSize(QSize(1024,600)); setWindowTitle(QString("Engineering Architecture IDE")); //setup the window main widget mainWidget = new QStackedWidget(this); QWidget* layoutWidget = new QWidget(mainWidget); QHBoxLayout* layout = new QHBoxLayout(layoutWidget); //setup the web view with the system events aware web page webView = new QWebEngineView(this); if (page == Q_NULLPTR) { EventAwareWebEnginePage *enginePage = new EventAwareWebEnginePage(); webView->setPage(enginePage); webView->setUrl(QUrl("https://www.google.com")); } else { page->setParent(webView); webView->setPage(page); } layout->addWidget(webView); //make the layout cover the whole window layout->setContentsMargins(0,0,0,0); layout->setSpacing(0); //layout widgets mainWidget->addWidget(layoutWidget); setCentralWidget(mainWidget); //show window on page load connect(webView, &QWebEngineView::loadFinished, [this](bool ok) { this->show(); }); } void WrapperWindow::markAsMainWindow() { isMainWindow = true; } void WrapperWindow::closeEvent(QCloseEvent *event) { if (isMainWindow) { QMessageBox::StandardButton reply; reply = QMessageBox::question(this, "Quit the IDE", "Are you sure you want to exit the Engineering Architecture IDE?", QMessageBox::Yes|QMessageBox::No); if (reply == QMessageBox::Yes) { event->accept(); deleteLater(); QApplication::quit(); } else event->ignore(); } else { event->accept(); deleteLater(); } }
eventawarewebenginepage.cpp
#include <QWebEnginePage> #include "eventawarewebenginepage.h" #include "wrapperwindow.h" EventAwareWebEnginePage::EventAwareWebEnginePage(QWidget *parent) : QWebEnginePage(parent) { } QWebEnginePage *EventAwareWebEnginePage::createWindow(WebWindowType type) { if (type == WebWindowType::WebBrowserWindow || type == WebWindowType::WebBrowserTab || type == WebWindowType::WebBrowserBackgroundTab) { EventAwareWebEnginePage *page = new EventAwareWebEnginePage(); connect(page, &QWebEnginePage::urlChanged, [page](const QUrl &url) { new WrapperWindow(Q_NULLPTR, page, url); }); return page; } return Q_NULLPTR; }
-
thanks. I have got the same problem.
HzWindow::~HzWindow()
{
m_webEngineView->deleteLater(); // I try this , solved the problem
qApp->removeTranslator(m_curTranslator);
if (m_pPrintHandler)
{
delete m_pPrintHandler;
}
}and initialize the page like this:
m_webEngineView->setPage(new HzWebEnginePage(m_profile, m_webEngineView));