drawin: Fix a segfault.

When a drawable has a pending redraw in a delayed call and the
drawin is GCed (which was impossible because it was broken
until the last commit), it crashes.
This commit is contained in:
Emmanuel Lepage Vallee 2023-08-13 01:00:45 -07:00
parent 16b92a0614
commit ff299d9fb2
3 changed files with 14 additions and 0 deletions

View File

@ -193,6 +193,12 @@ static int
luaA_drawable_refresh(lua_State *L) luaA_drawable_refresh(lua_State *L)
{ {
drawable_t *drawable = luaA_checkudata(L, 1, &drawable_class); drawable_t *drawable = luaA_checkudata(L, 1, &drawable_class);
/* GC race condition where the drawin is gone, but the drawable as a
* refresh in a delayed call */
if (!drawable->refresh_callback)
return 0;
drawable->refreshed = true; drawable->refreshed = true;
(*drawable->refresh_callback)(drawable->refresh_data); (*drawable->refresh_callback)(drawable->refresh_data);
@ -240,6 +246,12 @@ drawable_class_setup(lua_State *L)
NULL); NULL);
} }
void drawable_invalidate(drawable_t *d)
{
d->refresh_callback = NULL;
d->refresh_data = NULL;
}
/* @DOC_cobject_COMMON@ */ /* @DOC_cobject_COMMON@ */
// vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80 // vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80

View File

@ -50,6 +50,7 @@ typedef struct drawable_t drawable_t;
drawable_t *drawable_allocator(lua_State *, drawable_refresh_callback *, void *); drawable_t *drawable_allocator(lua_State *, drawable_refresh_callback *, void *);
void drawable_set_geometry(lua_State *, int, area_t); void drawable_set_geometry(lua_State *, int, area_t);
void drawable_class_setup(lua_State *); void drawable_class_setup(lua_State *);
void drawable_invalidate(drawable_t *d);
#endif #endif
// vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80 // vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80

View File

@ -187,6 +187,7 @@ drawin_wipe(drawin_t *w)
w->window = XCB_NONE; w->window = XCB_NONE;
} }
/* No unref needed because we are being garbage collected */ /* No unref needed because we are being garbage collected */
drawable_invalidate(w->drawable);
w->drawable = NULL; w->drawable = NULL;
} }