Bug 117499 - [GTK] Issue performing a navigation action from DOM bindings
Summary: [GTK] Issue performing a navigation action from DOM bindings
Status: RESOLVED INVALID
Alias: None
Product: WebKit
Classification: Unclassified
Component: WebKit2 (show other bugs)
Version: 528+ (Nightly build)
Hardware: Unspecified Unspecified
: P2 Normal
Assignee: Nobody
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2013-06-11 00:43 PDT by Manuel Rego Casasnovas
Modified: 2013-06-20 00:09 PDT (History)
4 users (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Manuel Rego Casasnovas 2013-06-11 00:43:02 PDT
The following code hangs in WebKit2GTK+ (in WK1 it works properly):

    WebKitDOMDocument* document;
    WebKitDOMHTMLElement* body;
    WebKitDOMElement* iframe;

    body = webkit_dom_document_get_body(document);

    iframe = webkit_dom_document_create_element(document, "iframe", NULL);
    webkit_dom_node_append_child(WEBKIT_DOM_NODE(body), WEBKIT_DOM_NODE(iframe), NULL);

The problem seems to be that when the new iframe is added, the WebProcess try to load it and it waits forever for the UIProcess in WebFrameLoaderClient::dispatchDecidePolicyForNavigationAction() when it uses Messages::WebPageProxy::DecidePolicyForNavigationAction().

It seems that there're some communication issues between the WebProcess and the UIProcess, beacause of the UIProcess is never notified in WebPageProxy::decidePolicyForNavigationAction().

WebProcess backtrace:

#0  pthread_cond_wait@@GLIBC_2.3.2 () at ../nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S:185
#1  0x00007ff4da173e3b in WTF::ThreadCondition::timedWait(WTF::Mutex&, double) () from /home/rego/work/WebKit/WebKitBuild/Release/.libs/libjavascriptcoregtk-3.0.so.0
#2  0x00007ff4da190489 in WTF::BinarySemaphore::wait(double) () from /home/rego/work/WebKit/WebKitBuild/Release/.libs/libjavascriptcoregtk-3.0.so.0
#3  0x00007ff4d965e3f6 in CoreIPC::Connection::waitForSyncReply(unsigned long, double, unsigned int) () from /home/rego/work/WebKit/WebKitBuild/Release/.libs/libwebkit2gtk-3.0.so.25
#4  0x00007ff4d9660267 in CoreIPC::Connection::sendSyncMessage(unsigned long, WTF::PassOwnPtr<CoreIPC::MessageEncoder>, double, unsigned int) ()
   from /home/rego/work/WebKit/WebKitBuild/Release/.libs/libwebkit2gtk-3.0.so.25
#5  0x00007ff4d821b587 in bool CoreIPC::Connection::sendSync<Messages::WebPageProxy::DecidePolicyForNavigationAction>(Messages::WebPageProxy::DecidePolicyForNavigationAction const&, Messages::WebPageProxy::DecidePolicyForNavigationAction::Reply const&, unsigned long, double, unsigned int) () from /home/rego/work/WebKit/WebKitBuild/Release/.libs/libwebkit2gtk-3.0.so.25
#6  0x00007ff4d82191a5 in WebKit::WebFrameLoaderClient::dispatchDecidePolicyForNavigationAction(void (WebCore::PolicyChecker::*)(WebCore::PolicyAction), WebCore::NavigationAction const&, WebCore::ResourceRequest const&, WTF::PassRefPtr<WebCore::FormState>) () from /home/rego/work/WebKit/WebKitBuild/Release/.libs/libwebkit2gtk-3.0.so.25
#7  0x00007ff4d882a590 in WebCore::PolicyChecker::checkNavigationPolicy(WebCore::ResourceRequest const&, WebCore::DocumentLoader*, WTF::PassRefPtr<WebCore::FormState>, void (*)(void*, WebCore::ResourceRequest const&, WTF::PassRefPtr<WebCore::FormState>, bool), void*) () from /home/rego/work/WebKit/WebKitBuild/Release/.libs/libwebkit2gtk-3.0.so.25
#8  0x00007ff4d8803502 in WebCore::FrameLoader::loadWithDocumentLoader(WebCore::DocumentLoader*, WebCore::FrameLoadType, WTF::PassRefPtr<WebCore::FormState>) ()
   from /home/rego/work/WebKit/WebKitBuild/Release/.libs/libwebkit2gtk-3.0.so.25
#9  0x00007ff4d8803c9f in WebCore::FrameLoader::loadWithNavigationAction(WebCore::ResourceRequest const&, WebCore::NavigationAction const&, bool, WebCore::FrameLoadType, WTF::PassRefPtr<WebCore::FormState>) ()
   from /home/rego/work/WebKit/WebKitBuild/Release/.libs/libwebkit2gtk-3.0.so.25
#10 0x00007ff4d8804868 in WebCore::FrameLoader::loadURL(WebCore::KURL const&, WTF::String const&, WTF::String const&, bool, WebCore::FrameLoadType, WTF::PassRefPtr<WebCore::Event>, WTF::PassRefPtr<WebCore::FormState>) () from /home/rego/work/WebKit/WebKitBuild/Release/.libs/libwebkit2gtk-3.0.so.25
#11 0x00007ff4d8806765 in WebCore::FrameLoader::loadURLIntoChildFrame(WebCore::KURL const&, WTF::String const&, WebCore::Frame*) () from /home/rego/work/WebKit/WebKitBuild/Release/.libs/libwebkit2gtk-3.0.so.25
#12 0x00007ff4d821786c in WebKit::WebFrameLoaderClient::createFrame(WebCore::KURL const&, WTF::String const&, WebCore::HTMLFrameOwnerElement*, WTF::String const&, bool, int, int) ()
   from /home/rego/work/WebKit/WebKitBuild/Release/.libs/libwebkit2gtk-3.0.so.25
#13 0x00007ff4d8836003 in WebCore::SubframeLoader::loadSubframe(WebCore::HTMLFrameOwnerElement*, WebCore::KURL const&, WTF::String const&, WTF::String const&) ()
   from /home/rego/work/WebKit/WebKitBuild/Release/.libs/libwebkit2gtk-3.0.so.25
#14 0x00007ff4d883630f in WebCore::SubframeLoader::loadOrRedirectSubframe(WebCore::HTMLFrameOwnerElement*, WebCore::KURL const&, WTF::AtomicString const&, bool, bool) ()
   from /home/rego/work/WebKit/WebKitBuild/Release/.libs/libwebkit2gtk-3.0.so.25
#15 0x00007ff4d88370ad in WebCore::SubframeLoader::requestFrame(WebCore::HTMLFrameOwnerElement*, WTF::String const&, WTF::AtomicString const&, bool, bool) ()
   from /home/rego/work/WebKit/WebKitBuild/Release/.libs/libwebkit2gtk-3.0.so.25
#16 0x00007ff4d8625a0c in WebCore::HTMLFrameElementBase::openURL(bool, bool) () from /home/rego/work/WebKit/WebKitBuild/Release/.libs/libwebkit2gtk-3.0.so.25
#17 0x00007ff4d845a20b in WebCore::updateTreeAfterInsertion(WebCore::ContainerNode*, WebCore::Node*, WebCore::AttachBehavior) () from /home/rego/work/WebKit/WebKitBuild/Release/.libs/libwebkit2gtk-3.0.so.25
#18 0x00007ff4d845ca8e in WebCore::ContainerNode::appendChild(WTF::PassRefPtr<WebCore::Node>, int&, WebCore::AttachBehavior) () from /home/rego/work/WebKit/WebKitBuild/Release/.libs/libwebkit2gtk-3.0.so.25
#19 0x00007ff4d84c01c7 in WebCore::Node::appendChild(WTF::PassRefPtr<WebCore::Node>, int&, WebCore::AttachBehavior) () from /home/rego/work/WebKit/WebKitBuild/Release/.libs/libwebkit2gtk-3.0.so.25
#20 0x00007ff4d95fe9c0 in webkit_dom_node_append_child () from /home/rego/work/WebKit/WebKitBuild/Release/.libs/libwebkit2gtk-3.0.so.25
Comment 1 Manuel Rego Casasnovas 2013-06-19 00:29:41 PDT
(In reply to comment #0)
> The following code hangs in WebKit2GTK+ (in WK1 it works properly):
> 
>     WebKitDOMDocument* document;
>     WebKitDOMHTMLElement* body;
>     WebKitDOMElement* iframe;
> 
>     body = webkit_dom_document_get_body(document);
> 
>     iframe = webkit_dom_document_create_element(document, "iframe", NULL);
>     webkit_dom_node_append_child(WEBKIT_DOM_NODE(body), WEBKIT_DOM_NODE(iframe), NULL);

The following code has the very same problem:

    WebKitDOMHTMLElement* body = webkit_dom_document_get_body(document);
    WebKitDOMElement* link = webkit_dom_document_create_element(document, "a", NULL);
    webkit_dom_html_anchor_element_set_href(WEBKIT_DOM_HTML_ANCHOR_ELEMENT(link), "http://www.igalia.com");
    webkit_dom_node_append_child(WEBKIT_DOM_NODE(body), WEBKIT_DOM_NODE(link), NULL);
    webkit_dom_html_element_click(WEBKIT_DOM_HTML_ELEMENT(link));

So it seems that the problem is not related to <iframe> tags, but it's a general issue when we try to perform any navigation action from the DOM bindings.
Comment 2 Manuel Rego Casasnovas 2013-06-19 03:29:49 PDT
Checking the UIProcess backtrace it's clear that the problem is due a synchronous D-Bus call which causes that the UIProcess and it doesn't reply to the WebProcess when it's asked about the navigation policy.

UIProcess backtrace:

#0  0x00007f366a4f91bd in poll () at ../sysdeps/unix/syscall-template.S:81
#1  0x00007f366b4514ec in g_main_context_poll (n_fds=1, fds=0xbfc9c0, timeout=25000, context=0xbfbf60, priority=<optimized out>) at gmain.c:3995
#2  g_main_context_iterate (context=0xbfbf60, block=block@entry=1, dispatch=dispatch@entry=1, self=<optimized out>) at gmain.c:3696
#3  0x00007f366b4519ca in g_main_loop_run (loop=0xbfc510) at gmain.c:3895
#4  0x00007f366b63e1d3 in g_dbus_connection_send_message_with_reply_sync (connection=connection@entry=0xbb4410, message=message@entry=0xbfaad0, flags=flags@entry=G_DBUS_SEND_MESSAGE_FLAGS_NONE, 
    timeout_msec=timeout_msec@entry=-1, out_serial=out_serial@entry=0x0, cancellable=cancellable@entry=0x0, error=error@entry=0x7fffe3a14098) at gdbusconnection.c:2240
#5  0x00007f366b63e5e0 in g_dbus_connection_call_sync_internal (connection=0xbb4410, bus_name=bus_name@entry=0xbfc4f0 ":1.0", object_path=0xbf9e80 "/org/webkit/gtk/WebExtensionTest", 
    interface_name=interface_name@entry=0xba6390 "org.webkit.gtk.WebExtensionTest", method_name=method_name@entry=0x407ab8 "GetTitle", parameters=parameters@entry=0x7f3604005a40, reply_type=0x7f366b67010f, 
    flags=G_DBUS_CALL_FLAGS_NONE, timeout_msec=-1, fd_list=0x0, out_fd_list=0x0, cancellable=0x0, error=0x0) at gdbusconnection.c:5564
#6  0x00007f366b640895 in g_dbus_connection_call_with_unix_fd_list_sync (connection=<optimized out>, bus_name=bus_name@entry=0xbfc4f0 ":1.0", object_path=<optimized out>, 
    interface_name=interface_name@entry=0xba6390 "org.webkit.gtk.WebExtensionTest", method_name=method_name@entry=0x407ab8 "GetTitle", parameters=parameters@entry=0x7f3604005a40, reply_type=0x7f366b67010f, 
    reply_type@entry=0x0, flags=flags@entry=G_DBUS_CALL_FLAGS_NONE, timeout_msec=timeout_msec@entry=-1, fd_list=fd_list@entry=0x0, out_fd_list=out_fd_list@entry=0x0, cancellable=cancellable@entry=0x0, 
    error=error@entry=0x0) at gdbusconnection.c:5908
#7  0x00007f366b649d25 in g_dbus_proxy_call_sync_internal (proxy=0xba7250, method_name=<optimized out>, parameters=0x7f3604005a40, flags=G_DBUS_CALL_FLAGS_NONE, timeout_msec=<optimized out>, 
    fd_list=fd_list@entry=0x0, out_fd_list=out_fd_list@entry=0x0, cancellable=0x0, error=error@entry=0x0) at gdbusproxy.c:2910
#8  0x00007f366b64bc43 in g_dbus_proxy_call_sync (proxy=<optimized out>, method_name=<optimized out>, parameters=<optimized out>, flags=<optimized out>, timeout_msec=<optimized out>, 
    cancellable=<optimized out>, error=0x0) at gdbusproxy.c:3102
#9  0x000000000040500b in testWebExtensionGetTitle(WebViewTest*, void const*) ()
#10 0x00007f366b47407d in test_case_run (tc=0xb24390) at gtestutils.c:1714
#11 g_test_run_suite_internal (suite=suite@entry=0xab70c0, path=<optimized out>, path@entry=0x7f366b4ba6ad "") at gtestutils.c:1767
#12 0x00007f366b4741f6 in g_test_run_suite_internal (suite=suite@entry=0xb264c0, path=<optimized out>, path@entry=0x7f366b4ba6ad "") at gtestutils.c:1778
#13 0x00007f366b4741f6 in g_test_run_suite_internal (suite=suite@entry=0xb264a0, path=<optimized out>, path@entry=0x7f366b4ba6ad "") at gtestutils.c:1778
#14 0x00007f366b47455b in g_test_run_suite (suite=0xb264a0) at gtestutils.c:1823
#15 0x0000000000405904 in main ()


I've checked that this works properly if I use an async D-Bus call, so it's not a WK bug.

Anyway I'm wondering if we should add some documentation warning the users about this issue, explaining that if they use a WebKitWebExtension synchronously this kind of deadlock could happen while playing with the DOM bindings. What do you think?
Comment 3 Carlos Garcia Campos 2013-06-20 00:09:54 PDT
(In reply to comment #2)
> Checking the UIProcess backtrace it's clear that the problem is due a synchronous D-Bus call which causes that the UIProcess and it doesn't reply to the WebProcess when it's asked about the navigation policy.
> 
> UIProcess backtrace:
> 
> #0  0x00007f366a4f91bd in poll () at ../sysdeps/unix/syscall-template.S:81
> #1  0x00007f366b4514ec in g_main_context_poll (n_fds=1, fds=0xbfc9c0, timeout=25000, context=0xbfbf60, priority=<optimized out>) at gmain.c:3995
> #2  g_main_context_iterate (context=0xbfbf60, block=block@entry=1, dispatch=dispatch@entry=1, self=<optimized out>) at gmain.c:3696
> #3  0x00007f366b4519ca in g_main_loop_run (loop=0xbfc510) at gmain.c:3895
> #4  0x00007f366b63e1d3 in g_dbus_connection_send_message_with_reply_sync (connection=connection@entry=0xbb4410, message=message@entry=0xbfaad0, flags=flags@entry=G_DBUS_SEND_MESSAGE_FLAGS_NONE, 
>     timeout_msec=timeout_msec@entry=-1, out_serial=out_serial@entry=0x0, cancellable=cancellable@entry=0x0, error=error@entry=0x7fffe3a14098) at gdbusconnection.c:2240
> #5  0x00007f366b63e5e0 in g_dbus_connection_call_sync_internal (connection=0xbb4410, bus_name=bus_name@entry=0xbfc4f0 ":1.0", object_path=0xbf9e80 "/org/webkit/gtk/WebExtensionTest", 
>     interface_name=interface_name@entry=0xba6390 "org.webkit.gtk.WebExtensionTest", method_name=method_name@entry=0x407ab8 "GetTitle", parameters=parameters@entry=0x7f3604005a40, reply_type=0x7f366b67010f, 
>     flags=G_DBUS_CALL_FLAGS_NONE, timeout_msec=-1, fd_list=0x0, out_fd_list=0x0, cancellable=0x0, error=0x0) at gdbusconnection.c:5564
> #6  0x00007f366b640895 in g_dbus_connection_call_with_unix_fd_list_sync (connection=<optimized out>, bus_name=bus_name@entry=0xbfc4f0 ":1.0", object_path=<optimized out>, 
>     interface_name=interface_name@entry=0xba6390 "org.webkit.gtk.WebExtensionTest", method_name=method_name@entry=0x407ab8 "GetTitle", parameters=parameters@entry=0x7f3604005a40, reply_type=0x7f366b67010f, 
>     reply_type@entry=0x0, flags=flags@entry=G_DBUS_CALL_FLAGS_NONE, timeout_msec=timeout_msec@entry=-1, fd_list=fd_list@entry=0x0, out_fd_list=out_fd_list@entry=0x0, cancellable=cancellable@entry=0x0, 
>     error=error@entry=0x0) at gdbusconnection.c:5908
> #7  0x00007f366b649d25 in g_dbus_proxy_call_sync_internal (proxy=0xba7250, method_name=<optimized out>, parameters=0x7f3604005a40, flags=G_DBUS_CALL_FLAGS_NONE, timeout_msec=<optimized out>, 
>     fd_list=fd_list@entry=0x0, out_fd_list=out_fd_list@entry=0x0, cancellable=0x0, error=error@entry=0x0) at gdbusproxy.c:2910
> #8  0x00007f366b64bc43 in g_dbus_proxy_call_sync (proxy=<optimized out>, method_name=<optimized out>, parameters=<optimized out>, flags=<optimized out>, timeout_msec=<optimized out>, 
>     cancellable=<optimized out>, error=0x0) at gdbusproxy.c:3102
> #9  0x000000000040500b in testWebExtensionGetTitle(WebViewTest*, void const*) ()
> #10 0x00007f366b47407d in test_case_run (tc=0xb24390) at gtestutils.c:1714
> #11 g_test_run_suite_internal (suite=suite@entry=0xab70c0, path=<optimized out>, path@entry=0x7f366b4ba6ad "") at gtestutils.c:1767
> #12 0x00007f366b4741f6 in g_test_run_suite_internal (suite=suite@entry=0xb264c0, path=<optimized out>, path@entry=0x7f366b4ba6ad "") at gtestutils.c:1778
> #13 0x00007f366b4741f6 in g_test_run_suite_internal (suite=suite@entry=0xb264a0, path=<optimized out>, path@entry=0x7f366b4ba6ad "") at gtestutils.c:1778
> #14 0x00007f366b47455b in g_test_run_suite (suite=0xb264a0) at gtestutils.c:1823
> #15 0x0000000000405904 in main ()
> 
> 
> I've checked that this works properly if I use an async D-Bus call, so it's not a WK bug.
> 
> Anyway I'm wondering if we should add some documentation warning the users about this issue, explaining that if they use a WebKitWebExtension synchronously this kind of deadlock could happen while playing with the DOM bindings. What do you think?

I see, yes, so the problem is not the DOM code itself, but that it's called in a D-BUS sync message handler. D-BUS uses a nested main loop for sync messages in the caller, so if the web process tries to send a sync message to the UI process, both will be waiting forever. It's unfortunate because we can't know whether a DOM call can produce a sync communication between web and UI processes, but at least we can control the D-BUS messages that our extension uses. I'm not sure it's necessary to document it, any synchronous call is always discouraged, we use them in the unit tests, but not in production code. I'm going to close this as invalid, since it's not actually a WebKit bug.