Skip to content

Crash: XDamageCreate on already-destroyed window causes BadDrawable fatal error #807

@UweSchneider

Description

@UweSchneider

Summary

Muffin crashes with a fatal BadDrawable X error when a client rapidly creates and destroys override-redirect windows. The crash originates in create_damage() in src/compositor/meta-surface-actor-x11.c, where XDamageCreate is called without an X error trap.

Steps to Reproduce

  1. Run an application under Wine 9.0 that rapidly creates/destroys override-redirect X11 windows (e.g. Altium Designer entering placement mode for pins, tracks, or lines)
  2. Muffin crashes, all window decorations disappear, keyboard shortcuts stop working, no input possible in any window
  3. Session manager tries to restart Cinnamon but fails ("respawning too quickly")

Error Output

(cinnamon:17468): Gdk-WARNING **: The program 'cinnamon' received an X Window System error.
The error was 'BadDrawable (invalid Pixmap or Window parameter)'.
  (Details: serial 5002 error_code 9 request_code 143 (DAMAGE) minor_code 1)

Also observed before the crash:

Window manager warning: WM_TRANSIENT_FOR window 0x50000c1 for 0x50000c4 window
override-redirect is an override-redirect window and this is not correct according
to the standard, so we'll fallback to the first non-override-redirect window 0x500004c.

Root Cause

In src/compositor/meta-surface-actor-x11.c, the create_damage() function (line 347) calls XDamageCreate without an X error trap:

static void
create_damage (MetaSurfaceActorX11 *self)
{
  Display *xdisplay = meta_x11_display_get_xdisplay (self->display->x11_display);
  Window xwindow = meta_window_x11_get_toplevel_xwindow (self->window);

  self->damage = XDamageCreate (xdisplay, xwindow, XDamageReportBoundingBox);
}

When a client destroys a window between the time Muffin receives the MapNotify event and the time it calls XDamageCreate, the X server returns BadDrawable, which is treated as a fatal error and crashes Cinnamon.

Notably, XDamageDestroy in the same file (line 82-85) is already protected with meta_x11_error_trap_push/pop:

meta_x11_error_trap_push (display->x11_display);
XDamageDestroy (xdisplay, self->damage);
self->damage = None;
meta_x11_error_trap_pop (display->x11_display);

Proposed Fix

Wrap XDamageCreate with the same error trap pattern:

--- a/src/compositor/meta-surface-actor-x11.c
+++ b/src/compositor/meta-surface-actor-x11.c
@@ -349,7 +349,9 @@ create_damage (MetaSurfaceActorX11 *self)
   Display *xdisplay = meta_x11_display_get_xdisplay (self->display->x11_display);
   Window xwindow = meta_window_x11_get_toplevel_xwindow (self->window);
 
+  meta_x11_error_trap_push (self->display->x11_display);
   self->damage = XDamageCreate (xdisplay, xwindow, XDamageReportBoundingBox);
+  meta_x11_error_trap_pop (self->display->x11_display);
 }

This is a minimal, safe change — if the window no longer exists, the error is silently ignored and self->damage remains unset. This is the correct behavior since there is nothing to track damage on for a destroyed window.

Environment

  • Muffin: 6.6.3+zena
  • Cinnamon: Linux Mint 22
  • Kernel: 6.17.0-14-generic
  • GPU: AMD RDNA4 (amdgpu)
  • Trigger application: Wine 9.0 running Altium Designer 16 (but any application rapidly creating/destroying override-redirect windows could trigger this)

Testing

The fix has been locally compiled and tested. With the patched libmuffin.so.0.0.0, the crash no longer occurs — Altium Designer placement operations work without affecting Cinnamon stability.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions