]> git.eshelyaron.com Git - emacs.git/commitdiff
Fix SEGV crash by unref css provider too much
authorYuuki Harano <masm+github@masm11.me>
Mon, 6 Dec 2021 15:20:30 +0000 (00:20 +0900)
committerYuuki Harano <masm+github@masm11.me>
Mon, 6 Dec 2021 15:20:30 +0000 (00:20 +0900)
I Got css provider from F, and was going to remove it from style
context.  But between them, unhighlight was called when
gtk_container_remove was called, and the css provider was already
freed, so I can't use the css provider to remove it from style
context.

As a fix, I call gtk_container_remove after remove it.
Also, I free a css provider set by unhighlight.

* src/pgtkterm.c (x_set_parent_frame):

src/pgtkterm.c

index bf863c84745b70130fd036bcf7f3fc592fd1d005..ed7a4a45c25b3e19b9e1370e3549f91d277085fa 100644 (file)
@@ -798,15 +798,19 @@ x_set_parent_frame (struct frame *f, Lisp_Object new_value,
       gtk_widget_get_allocation (fixed, &alloc);
       g_object_ref (fixed);
 
+      /* Remember the css provider, and restore it later. */
       GtkCssProvider *provider = FRAME_X_OUTPUT (f)->border_color_css_provider;
+      FRAME_X_OUTPUT (f)->border_color_css_provider = NULL;
+      {
+       GtkStyleContext *ctxt = gtk_widget_get_style_context (FRAME_WIDGET (f));
+       gtk_style_context_remove_provider (ctxt, GTK_STYLE_PROVIDER (provider));
+      }
 
       {
        GtkWidget *whbox_of_f = gtk_widget_get_parent (fixed);
+       /* Here, unhighlight can be called and may change border_color_css_provider. */
        gtk_container_remove (GTK_CONTAINER (whbox_of_f), fixed);
 
-       GtkStyleContext *ctxt = gtk_widget_get_style_context (FRAME_WIDGET (f));
-       gtk_style_context_remove_provider (ctxt, GTK_STYLE_PROVIDER (provider));
-
        if (FRAME_GTK_OUTER_WIDGET (f))
          {
            gtk_widget_destroy (FRAME_GTK_OUTER_WIDGET (f));
@@ -842,9 +846,17 @@ x_set_parent_frame (struct frame *f, Lisp_Object new_value,
          gtk_widget_show_all (fixed);
        }
 
+      /* Restore css provider. */
       GtkStyleContext *ctxt = gtk_widget_get_style_context (FRAME_WIDGET (f));
+      GtkCssProvider *old = FRAME_X_OUTPUT (f)->border_color_css_provider;
+      FRAME_X_OUTPUT (f)->border_color_css_provider = provider;
       gtk_style_context_add_provider (ctxt, GTK_STYLE_PROVIDER (provider),
                                      GTK_STYLE_PROVIDER_PRIORITY_USER);
+      if (old != NULL)
+       {
+         gtk_style_context_remove_provider (ctxt, GTK_STYLE_PROVIDER (old));
+         g_object_unref(old);
+       }
 
       g_object_unref (fixed);