Avoid using window id as identifier in finish_destroy_win

Under extreme race conditions (window A close at the same time as window
B create), there can be multiple windows with same id in compton's window
list. If at this point window B closes itself as well, finish_destroy_win
might destroy a different window as what's passed to destroy_callback.

This can be a problem because someone can still hold a reference to that
window (e.g. 't' in paint_preprocess), and there's no way to clear that
reference. If finish_destroy_win always destroy the same window passed
to destroy_callback, this will not be a problem.
This commit is contained in:
Yuxuan Shui 2016-07-14 16:43:20 -04:00
parent f4f39d1989
commit cfdb946992
2 changed files with 9 additions and 8 deletions

View File

@ -3206,17 +3206,18 @@ circulate_win(session_t *ps, XCirculateEvent *ce) {
}
static void
finish_destroy_win(session_t *ps, Window id) {
win **prev = NULL, *w = NULL;
finish_destroy_win(session_t *ps, win *w) {
assert(w->destroyed);
win **prev = NULL, *i = NULL;
#ifdef DEBUG_EVENTS
printf_dbgf("(%#010lx): Starting...\n", id);
printf_dbgf("(%#010lx): Starting...\n", w->id);
#endif
for (prev = &ps->list; (w = *prev); prev = &w->next) {
if (w->id == id && w->destroyed) {
for (prev = &ps->list; (i = *prev); prev = &i->next) {
if (w == i) {
#ifdef DEBUG_EVENTS
printf_dbgf("(%#010lx \"%s\"): %p\n", id, w->name, w);
printf_dbgf("(%#010lx \"%s\"): %p\n", w->id, w->name, w);
#endif
finish_unmap_win(ps, w);
@ -3242,7 +3243,7 @@ finish_destroy_win(session_t *ps, Window id) {
static void
destroy_callback(session_t *ps, win *w) {
finish_destroy_win(ps, w->id);
finish_destroy_win(ps, w);
}
static void

View File

@ -919,7 +919,7 @@ static void
circulate_win(session_t *ps, XCirculateEvent *ce);
static void
finish_destroy_win(session_t *ps, Window id);
finish_destroy_win(session_t *ps, win *w);
static void
destroy_callback(session_t *ps, win *w);