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 troublesIt 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
QWebEnginepages not being released properly/processes hanging around from Python code, though I did not get an error message like you. I found thatQWebEngines 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)); -
J JonB referenced this topic on