Skip to content

Commit 5f69580

Browse files
authored
Merge pull request #1337 from yshui/leader-wm-consistency
Fix NULL dereference when refreshing window leader with an inconsistent wm tree
2 parents 61361ad + 67ec733 commit 5f69580

File tree

2 files changed

+27
-0
lines changed

2 files changed

+27
-0
lines changed

src/picom.c

+8
Original file line numberDiff line numberDiff line change
@@ -1448,6 +1448,8 @@ static void unredirect(session_t *ps) {
14481448
/// keeps an internal queue of events, so we have to be 100% sure no events are
14491449
/// left in that queue before we go to sleep.
14501450
static void handle_x_events(struct session *ps) {
1451+
bool wm_was_consistent = wm_is_consistent(ps->wm);
1452+
14511453
if (ps->vblank_scheduler) {
14521454
vblank_handle_x_events(ps->vblank_scheduler);
14531455
}
@@ -1478,6 +1480,12 @@ static void handle_x_events(struct session *ps) {
14781480
log_fatal("X11 server connection broke (error %d)", err);
14791481
exit(1);
14801482
}
1483+
1484+
if (wm_is_consistent(ps->wm) != wm_was_consistent && !wm_was_consistent) {
1485+
log_debug("Window tree has just become consistent, queueing redraw.");
1486+
ps->pending_updates = true;
1487+
queue_redraw(ps);
1488+
}
14811489
}
14821490

14831491
static void handle_x_events_ev(EV_P attr_unused, ev_prepare *w, int revents attr_unused) {

src/wm/wm.c

+19
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,22 @@ void wm_refresh_leaders(struct wm *wm) {
236236
if (!wm->needs_leader_refresh) {
237237
return;
238238
}
239+
if (!wm_is_consistent(wm)) {
240+
// The window tree has not been fully replicated, we might be missing
241+
// windows, so we couldn't refresh the leaders here, but also can't leave
242+
// them NULL. So we just set them to themselves.
243+
log_debug("Window tree is not consistent, setting all leaders to "
244+
"themselves");
245+
list_foreach(struct wm_tree_node, i, &wm->tree.root->children, siblings) {
246+
if (i->is_zombie) {
247+
// Don't change anything about a zombie window.
248+
continue;
249+
}
250+
i->leader_final = i;
251+
}
252+
return;
253+
}
254+
log_debug("Refreshing window leaders");
239255
wm->needs_leader_refresh = false;
240256
list_foreach(struct wm_tree_node, i, &wm->tree.root->children, siblings) {
241257
if (i->is_zombie) {
@@ -249,6 +265,9 @@ void wm_refresh_leaders(struct wm *wm) {
249265
continue;
250266
}
251267
wm_find_leader(wm, i);
268+
BUG_ON_NULL(i->leader_final);
269+
log_verbose("Window %#010x has leader %#010x", i->id.x,
270+
i->leader_final->id.x);
252271
}
253272
}
254273

0 commit comments

Comments
 (0)