Bug 79252 - [WK2][GTK] WebProcess SIGSEVs due to incorrect clipboard handling
Summary: [WK2][GTK] WebProcess SIGSEVs due to incorrect clipboard handling
Status: RESOLVED FIXED
Alias: None
Product: WebKit
Classification: Unclassified
Component: WebKitGTK (show other bugs)
Version: 528+ (Nightly build)
Hardware: Unspecified Unspecified
: P2 Normal
Assignee: Sergio Villar Senin
URL:
Keywords:
Depends on:
Blocks: 76070
  Show dependency treegraph
 
Reported: 2012-02-22 09:54 PST by Sergio Villar Senin
Modified: 2012-02-23 08:38 PST (History)
2 users (show)

See Also:


Attachments
Patch (2.63 KB, patch)
2012-02-22 09:58 PST, Sergio Villar Senin
no flags Details | Formatted Diff | Diff
Patch (3.56 KB, patch)
2012-02-22 12:42 PST, Sergio Villar Senin
mrobinson: review+
Details | Formatted Diff | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Sergio Villar Senin 2012-02-22 09:54:02 PST
WebEditorClient::setSelectionPrimaryClipboardIfNeeded passes a Frame as argument to a callback executed after writing some contents to the clipboard. The problem is that if the WebProcess closes the related to that Frame before the callback is executed then the Frame is destroyed causing a SIGSEV when the callback is executed.

This is easy to reproduce in Debug builds repeatedly running the TestWebViewEditor unit tests. It will fail after 3-4 correct executions.
Comment 1 Sergio Villar Senin 2012-02-22 09:58:50 PST
Created attachment 128235 [details]
Patch
Comment 2 Carlos Garcia Campos 2012-02-22 10:11:55 PST
Comment on attachment 128235 [details]
Patch

Looks good to me
Comment 3 Martin Robinson 2012-02-22 10:16:07 PST
Comment on attachment 128235 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=128235&action=review

> Source/WebKit2/WebProcess/WebCoreSupport/gtk/WebEditorClientGtk.cpp:141
>  static Frame* frameSettingClipboard;
>  static void collapseSelection(GtkClipboard* clipboard, Frame* frame)
>  {
> -    if (frameSettingClipboard && frameSettingClipboard == frame)
> -        return;
> +    if (!frameSettingClipboard || frameSettingClipboard != frame)
> +        // Collapse the selection without clearing it.
> +        frame->selection()->setBase(frame->selection()->extent(), frame->selection()->affinity());
>  
> -    // Collapse the selection without clearing it.
> -    ASSERT(frame);
> -    frame->selection()->setBase(frame->selection()->extent(), frame->selection()->affinity());
> +    frame->deref();
>  }

I think that manually referencing the frame here is the wrong approach. Intead of hanging on to the frame, WebKit1 keeps a reference to the WebView and uses corePage->focusController()->focusedOrMainFrame(). Another approach is to figure out a way to detect when the frame dies and to clear frameSettingClipboard then.
Comment 4 Sergio Villar Senin 2012-02-22 10:31:44 PST
(In reply to comment #3)
> I think that manually referencing the frame here is the wrong approach. Intead of hanging on to the frame, WebKit1 keeps a reference to the WebView and uses corePage->focusController()->focusedOrMainFrame(). Another approach is to figure out a way to detect when the frame dies and to clear frameSettingClipboard then.

In WebKit1 we're not exactly keeping a reference to the WebView, it's just a pointer. The difference is that WebKit1 uses g_cclosure_new_object() that ensures that the callback is not called once the object passed as argument is unref'ed.

Anyway the platform independent WK2 WebEditorClient.cpp has a WebEditorClient::pageDestroyed() method. What about adding there a call (#ifdef'ed for GTK) to clear the frameSettingClipboard ?
Comment 5 Martin Robinson 2012-02-22 10:37:34 PST
(In reply to comment #4)

> Anyway the platform independent WK2 WebEditorClient.cpp has a WebEditorClient::pageDestroyed() method. What about adding there a call (#ifdef'ed for GTK) to clear the frameSettingClipboard ?

That makes sense, but in that case you should keep a reference to the Page instead of the Frame. A Frame can be destroyed before its owning Page.
Comment 6 Sergio Villar Senin 2012-02-22 12:42:37 PST
Created attachment 128268 [details]
Patch
Comment 7 Sergio Villar Senin 2012-02-22 12:45:28 PST
(In reply to comment #6)
> Created an attachment (id=128268) [details]
> Patch

This new approach uses a frame destructor object in combination with gclosure finalization notifications to fix the bug.
Comment 8 Martin Robinson 2012-02-22 13:10:20 PST
Comment on attachment 128268 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=128268&action=review

Great use of FrameDestructionObserver.

> Source/WebKit2/WebProcess/WebCoreSupport/gtk/WebEditorClientGtk.cpp:136
> +    explicit EditorClientFrameDestructionObserver(Frame* frame, GClosure* closure)

I think you can omit "explicit" here.

> Source/WebKit2/WebProcess/WebCoreSupport/gtk/WebEditorClientGtk.cpp:143
> +    void frameDestroyed() { g_closure_invalidate(m_closure); FrameDestructionObserver::frameDestroyed(); }

I'd prefer this to be two spread over multiple lines.

> Source/WebKit2/WebProcess/WebCoreSupport/gtk/WebEditorClientGtk.cpp:150
> +        EditorClientFrameDestructionObserver* observer = static_cast<EditorClientFrameDestructionObserver*>(data);
> +        delete observer;

You can just do:

delete data;
Comment 9 Sergio Villar Senin 2012-02-23 08:38:13 PST
Committed r108631: <http://trac.webkit.org/changeset/108631>