Skip to content

Fix zombie window leak by passing win pointer directly to finish_destroy_win - #47

Open
jEsuSdA wants to merge 1 commit into
tycho-kirchner:masterfrom
jEsuSdA:fix/zombie-window-leak
Open

Fix zombie window leak by passing win pointer directly to finish_destroy_win#47
jEsuSdA wants to merge 1 commit into
tycho-kirchner:masterfrom
jEsuSdA:fix/zombie-window-leak

Conversation

@jEsuSdA

@jEsuSdA jEsuSdA commented Jul 2, 2026

Copy link
Copy Markdown

Summary

Fixes a memory leak where destroyed windows accumulate indefinitely because finish_destroy_win() cannot find them via ID lookup.

Problem

finish_destroy_win() searched for the window by ID using a linear scan that required w->destroyed == True. However, find_win() (used by destroy_win() and other callers) filters out destroyed windows:

win* find_win(Window id) {
  for (w = list; w; w = w->next) {
    if (w->id == id && !w->destroyed)  // <-- filters out destroyed!
      return w;
  }
}

When destroy_win() marks a window as destroyed and then calls finish_destroy_win(), the latter scans the list looking for w->destroyed == True. But if find_win() was called in between (or if the window is accessed again), the destroyed window is skipped. More importantly, finish_destroy_win() itself searches by ID and requires w->destroyed, but since the caller already has the win* pointer, the search is redundant and fragile.

The result: zombie win structs accumulate in the window list forever, causing memory growth and eventual slowdown over long sessions.

Solution

Change finish_destroy_win() to accept a win* pointer directly instead of a Window ID. The callers already have the pointer:

  • destroy_win() finds it via find_win() before marking destroyed
  • destroy_callback() receives it as an argument

This eliminates the problematic ID lookup entirely.

Scope

  • Only fastcompmgr.c is touched
  • Function signature change + two caller updates
  • make clean && make produces zero warnings, zero errors

Note

The list unlink logic remains a linear scan (to be replaced by O(1) unlink once the doubly-linked list PR is merged).

…roy_win

finish_destroy_win() searched for the window by ID using a linear scan
that required w->destroyed to be true. However, find_win() (used by
destroy_win() and other callers) filters out destroyed windows. This meant
that when a window was marked destroyed but not yet freed, finish_destroy_win()
could never find it again via ID lookup, causing an infinite accumulation
of zombie win structs in the window list.

Change finish_destroy_win() to accept a win* pointer directly instead of
a Window ID. This eliminates the problematic ID lookup entirely. The
callers already have the win* pointer available (destroy_win() finds it
via find_win() before marking destroyed, and destroy_callback() receives
it as an argument).

This is a minimal change: only the function signature and its two callers
are touched. The list unlink logic remains a linear scan (to be replaced
by O(1) unlink once the doubly-linked list PR is merged).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant