我有一个需要在线程上呈现HTML的C ++应用程序。我已经研究了QtWebKit和Webkit2Gtk +并遇到了同样的问题:经过大约3-4次迭代后,它崩溃了。
基本设置是这样的(在本例中使用Webkit2Gtk +):
WebKitWebView *HtmlView;
void destroyHtmlWindowCb( GtkWidget *widget, GtkWidget *window ) {
gtk_main_quit();
}
gboolean closeHtmlViewCb( WebKitWebView *webView, GtkWidget *window ) {
webkit_web_view_stop_loading( webView );
gtk_widget_destroy( window );
return true;
}
void RendererThread( boost::barrier &render_barrier ) {
gtk_init( nullptr, nullptr );
GtkWidget *HtmlWindow;
while( true ) {
render_barrier.count_down_and_wait();
HtmlWindow = gtk_window_new( GTK_WINDOW_TOPLEVEL );
HtmlView = WEBKIT_WEB_VIEW(webkit_web_view_new());
g_signal_connect( HtmlView, "close", G_CALLBACK(closeHtmlViewCb), HtmlWindow );
g_signal_connect( HtmlWindow, "destroy", G_CALLBACK(destroyHtmlWindowCb), nullptr );
gtk_container_add( GTK_CONTAINER(HtmlWindow), GTK_WIDGET(HtmlView) );
gtk_widget_show( GTK_WIDGET(HtmlView) );
webkit_web_view_load_uri( HtmlView, "http://www.stackoverflow.com/" );
gtk_window_set_default_size( GTK_WINDOW(HtmlWindow), 1920, 1080 );
gtk_window_fullscreen( GTK_WINDOW(HtmlWindow) );
gtk_widget_show( HtmlWindow );
std::cout << "Calling gtk_main()" << std::endl;
gtk_main();
}
}
void EventHandlerThread( boost::barrier &render_barrier ) {
while( true ) {
render_barrier.count_down_and_wait();
std::this_thread::sleep_for( std::chrono::seconds( 15 ) );
g_signal_emit_by_name( HtmlView, "close" );
}
}
int main() {
boost::barrier render_barrier( 2 );
std::thread Renderer( RendererThread, std::ref(render_barrier) );
Renderer.detach();
std::thread EventHandler( EventHandlerThread, std::ref(render_barrier) );
EventHandler.detach();
//... sleep forever as far as this example is concerned
return 0;
}
这是真实程序的精简版,但任何竞争条件/线程安全问题都应准确表示。
程序在调用gtk_main()时总会崩溃,这是在stderr中生成的:
...
Calling gtk_main()
...
Calling gtk_main()
Error sending IPC message: Connection reset by peer
Nov 30 16:27:50 gmbase xinit[9541]: /usr/bin/xinit: connection to X server lost
Nov 30 16:27:50 gmbase org.a11y.atspi.Registry[9561]: XIO: fatal IO error 11 (Resource temporarily unavailable) on X server ":0.0"
Nov 30 16:27:50 gmbase org.a11y.atspi.Registry[9561]: after 21 requests (19 known processed) with 0 events remaining.
Nov 30 16:27:50 gmbase xinit[9541]: waiting for X server to shut down (II) Server terminated successfully (0). Closing log file.
Nov 30 16:27:50 gmbase systemd-coredump[9646]: Process 9545 (glassmedia-debu) of user 0 dumped core.
Stack trace of thread 9548:
#0 0x00007fcbe0e22970 _ZNK3WTF10StringImpl12hashSlowCaseEv (libjavascriptcoregtk-4.0.so.18)
#1 0x00007fcbe0e15bf8 _ZN3WTF9HashTableIPNS_10StringImplES2_NS_17IdentityExtractorENS_10StringHashENS_10HashTraitsIS2_EES6_E6rehashEjPS2_ (libjavascriptcoregtk-4.0.so.18)
#2 0x00007fcbe0e14c3b _ZN3WTF16AtomicStringImpl11addSlowCaseERNS_10StringImplE (libjavascriptcoregtk-4.0.so.18)
#3 0x00007fcbe36fc4ee n/a (libwebkit2gtk-4.0.so.37)
#4 0x00007fcbe372dd63 n/a (libwebkit2gtk-4.0.so.37)
#5 0x00007fcbe374dfdc n/a (libwebkit2gtk-4.0.so.37)
#6 0x00007fcbe3719743 n/a (libwebkit2gtk-4.0.so.37)
#7 0x00007fcbe3719aec n/a (libwebkit2gtk-4.0.so.37)
#8 0x00007fcbe39c6f13 n/a (libwebkit2gtk-4.0.so.37)
#9 0x00007fcbe3704359 n/a (libwebkit2gtk-4.0.so.37)
#10 0x00007fcbe37c4ae2 n/a (libwebkit2gtk-4.0.so.37)
#11 0x00007fcbe370057b n/a (libwebkit2gtk-4.0.so.37)
#12 0x00007fcbe3700f9b n/a (libwebkit2gtk-4.0.so.37)
#13 0x00007fcbe4dea28f n/a (libwebkit2gtk-4.0.so.37)
#14 0x00007fcbe0e3591c _ZN3WTF15GMainLoopSource12voidCallbackEv (libjavascriptcoregtk-4.0.so.18)
#15 0x00007fcbe0e342ba _ZN3WTF15GMainLoopSource18voidSourceCallbackEPS0_ (libjavascriptcoregtk-4.0.so.18)
#16 0x00007fcbe0352c7a g_main_context_dispatch (libglib-2.0.so.0)
#17 0x00007fcbe0353020 n/a (libglib-2.0.so.0)
#18 0x00007fcbe0353342 g_main_loop_run (libglib-2.0.so.0)
#19 0x00007fcbe2af32a5 gtk_main (libgtk-3.so.0)
#20 0x0000000000477ec9 _ZN10Glassmedia7Display6renderEv (glassmedia-debug)
#21 0x0000000000498dd9 _ZN10Glassmedia14RendererThreadESt10shared_ptrINS_7DisplayEERN5boost7barrierE (glassmedia-debug)
#22 0x0000000000460739 _ZNSt12_Bind_simpleIFPFvSt10shared_ptrIN10Glassmedia7DisplayEERN5boost7barrierEES3_St17reference_wrapperIS5_EEE9_M_invokeIJLm0ELm1EEEEvSt12_Index_tupleIJXspT_EEE (glassmedia-debug)
#23 0x00007fcbe0040350 execute_native_thread_routine (libstdc++.so.6)
#24 0x00007fcbdf85d4a4 start_thread (libpthread.so.0)
#25 0x00007fcbdf59b13d __clone (libc.so.6)
Stack trace of thread 9549:
#0 0x00007fcbdf86307f pthread_cond_wait@@GLIBC_2.3.2 (libpthread.so.0)
#1 0x00007fcbe003aefc __gthread_cond_wait (libstdc++.so.6)
#2 0x00000000004991c3 _ZN10Glassmedia18EventHandlerThreadESt10shared_ptrINS_7DisplayEERNS_12EventCourierERN5boost7barrierE (glassmedia-debug)
#3 0x0000000000460801 _ZNSt12_Bind_simpleIFPFvSt10shared_ptrIN10Glassmedia7DisplayEERNS1_12EventCourierERN5boost7barrierEES3_St17reference_wrapperIS4_ESB_IS7_EEE9_M_invokeIJLm0ELm1ELm2EEEEvSt12_Index_tupleIJXspT_EEE (glassmedia-debug)
#4 0x00007fcbe0040350 execute_native_thread_routine (libstdc++.so.6)
#5 0x00007fcbdf85d4a4 start_thread (libpthread.so.0)
#6 0x00007fcbdf59b13d __clone (libc.so.6)
Stack trace of thread 9566:
#0 0x00007fcbdf59218d poll (libc.so.6)
#1 0x00007fcbe0352fbc n/a (libglib-2.0.so.0)
#2 0x00007fcbe0353342 g_main_loop_run (libglib-2.0.so.0)
#3 0x00007fcbe0e05dd5 n/a (libjavascriptcoregtk-4.0.so.18)
#4 0x00007fcbe0e325fa n/a (libjavascriptcoregtk-4.0.so.18)
#5 0x00007fcbdf85d4a4 start_thread (libpthread.so.0)
#6 0x00007fcbdf59b13d __clone (libc.so.6)
Stack trace of thread 9567:
#0 0x00007fcbdf59218d poll (libc.so.6)
#1 0x00007fcbe0352fbc n/a (libglib-2.0.so.0)
#2 0x00007fcbe0353342 g_main_loop_run (libglib-2.0.so.0)
#3 0x00007fcbe0e05dd5 n/a (libjavascriptcoregtk-4.0.so.18)
#4 0x00007fcbe0e325fa n/a (libjavascriptcoregtk-4.0.so.18)
#5 0x00007fcbdf85d4a4 start_thread (libpthread.so.0)
#6 0x00007fcbdf59b13d __clone (libc.so.6)
Stack trace of thread 9639:
#0 0x00007fcbdf86665d __nanosleep (libpthread.so.0)
#1 0x00007fcbe0e41b3c _ZN7bmalloc4Heap8scavengeERSt11unique_lockINS_11StaticMutexEENSt6chrono8durationIlSt5ratioILl1ELl1000EEEE (libjavascriptcoregtk-4.0.so.18)
#2 0x00007fcbe0e41c5f _ZN7bmalloc4Heap18concurrentScavengeEv (libjavascriptcoregtk-4.0.so.18)
#3 0x00007fcbe0e429ae _ZN7bmalloc9AsyncTaskINS_4HeapEMS1_FvvEE13threadRunLoopEv (libjavascriptcoregtk-4.0.so.18)
#4 0x00007fcbe0040350 execute_native_thread_routine (libstdc++.so.6)
#5 0x00007fcbdf85d4a4 start_thread (libpthread.so.0)
#6 0x00007fcbdf59b13d __clone (libc.so.6)
Stack trace of thread 9545:
#0 0x00007fcbdf85e70d pthread_join (libpthread.so.0)
#1 0x00007fcbe0040267 __gthread_join (libstdc++.so.6)
#2 0x000000000045ed55 main (glassmedia-debug)
#3 0x00007fcbdf4d2610 __libc_start_main (libc.so.6)
#4 0x000000000045dc79 _start (glassmedia-debug)
Stack trace of thread 9569:
#0 0x00007fcbdf59218d poll (libc.so.6)
#1 0x00007fcbe0352fbc n/a (libglib-2.0.so.0)
#2 0x00007fcbe0353342 g_main_loop_run (libglib-2.0.so.0)
#3 0x00007fcbe0e05dd5 n/a (libjavascriptcoregtk-4.0.so.18)
#4 0x00007fcbe0e325fa n/a (libjavascriptcoregtk-4.0.so.18)
#5 0x00007fcbdf85d4a4 start_thread (libpthread.so.0)
#6 0x00007fcbdf59b13d __clone (libc.so.6)
Stack trace of thread 9547:
#0 0x00007fcbdf59b733 epoll_wait (libc.so.6)
#1 0x00007fcbe6298f15 n/a (libev.so.4)
#2 0x00007fcbe629b4b9 ev_run (libev.so.4)
#3 0x000000000047e7c1 ev_loop (glassmedia-debug)
#4 0x0000000000498ae4 _ZN10Glassmedia21EventSubscriberThreadERNS_12EventCourierE (glassmedia-debug)
#5 0x000000000045f086 _ZNSt12_Bind_simpleIFPFvRN10Glassmedia12EventCourierEESt17reference_wrapperIS1_EEE9_M_invokeIJLm0EEEEvSt12_Index_tupleIJXspT_EEE (glassmedia-debug)
#6 0x00007fcbe0040350 execute_native_thread_routine (libstdc++.so.6)
#7 0x00007fcbdf85d4a4 start_thread (libpthread.so.0)
#8 0x00007fcbdf59b13d __clone (libc.so.6)
Stack trace of thread 9572:
#0 0x00007fcbdf59218d poll (libc.so.6)
#1 0x00007fcbe0352fbc n/a (libglib-2.0.so.0)
#2 0x00007fcbe0353342 g_main_loop_run (libglib-2.0.so.0)
#3 0x00007fcbe0e05dd5 n/a (libjavascriptcoregtk-4.0.so.18)
#4 0x00007fcbe0e325fa n/a (libjavascriptcoregtk-4.0.so.18)
#5 0x00007fcbdf85d4a4 start_thread (libpthread.so.0)
#6 0x00007fcbdf59b13d __clone (libc.so.6)
QtWebKit的代码非常相似;相同的结果。
在真实的程序中,我的测试在Reddit和CNN之间循环。就一个网站造成崩溃而另一个网站而言,没有任何模式可以辨别出来。
请忽略任何看起来很愚蠢的主线程永远等待的事情。在真实的节目中,我有我的理由。
感谢您对此问题的任何帮助。我现在已经工作了很长时间。
答案 0 :(得分:1)
我发现,只要我使用QWebEngine(QtWebKit的Google Chrome分支),问题就会消失。代码变得更加简单:
#include <QApplication>
#include <QWebEngineView>
QWebEngineView *HtmlView;
void RendererThread( boost::barrier &render_barrier, int main_argc, char **main_argv ) {
QApplication app( main_argc, main_argv );
while( true ) {
render_barrier.count_down_and_wait();
HtmlView = new QWebEngineView();
HtmlView->setAttribute( Qt::WA_DeleteOnClose );
HtmlView->load( QUrl( "http://www.stackoverflow.com/" ) );
HtmlView->resize( 1920, 1080 );
HtmlView->raise();
HtmlView->move( 0, 0 );
HtmlView->showFullscreen();
app.exec();
}
}
void EventHandlerThread( boost::barrier &render_barrier ) {
while( true ) {
render_barrier.count_down_and_wait();
std::this_thread::sleep_for( std::chrono::seconds( 15 ) );
HtmlView->stop();
HtmlView->close();
}
}
int main( int argc, char *argv[] ) {
boost::barrier render_barrier( 2 );
std::thread Renderer( RendererThread, std::ref(render_barrier), argc, argv );
Renderer.detach();
std::thread EventHandler( EventHandlerThread, std::ref(render_barrier) );
EventHandler.detach();
//... sleep forever as far as this example is concerned
return 0;
}
我在Arch Linux上的qt5-webengine包下安装了QWebEngine。
程序需要Qt5WebEngineWidgets的cflags和libs来编译:
g++ -std=c++11 -Wall `pkg-config --cflags Qt5WebEngineWidgets` webkit_test.cpp -o webkit_test `pkg-config --libs Qt5WebEngineWidgets` -pthread