wayland: hack around presentation_feedback weirdness

964692ad4c added some code to destroy
presentation_feedback we get in the presentation_discarded event. This
is the correct thing to do since the compositor could send us this
instead of feedback_presented. Without that change, mutter could
potentially leak memory on every frame.

Unfortunately, life is not so simple and wlroots and weston act
differently. These compositors only send one presentation_discarded
event if the mpv window is hidden. Not on every single missed frame like
mutter. Now in theory this shouldn't matter, but it also turns out that
mpv attempts to free the presentation feedback twice if you quit it
while it is hidden away (on weston and wlroots compositors only). The
inital wp_presentation_feedback_destroy in feedback_discarded fires, but
then the function goes off again in vo_wayland_uninit because
wl->feedback is apparently not NULL for some reason. Possibly, this is
some race condition but we can't just get rid of what's in
feedback_discarded since mutter needs this line. Instead, just hack it
by explicitly setting wl->feedback to NULL in feedback_discarded after we
destroy the presentation feedback. Some valgrind testing in mutter,
sway, and weston shows that this works correctly on all of those
compositors with various combinations of mpv being visible or not while
quitting. feedback_presented doesn't appear to exhibit this behavior so
we just leave that as-is.
This commit is contained in:
Dudemanguy 2022-10-29 15:59:11 -05:00
parent 667222dffa
commit d3a28f12c9
1 changed files with 10 additions and 1 deletions

View File

@ -1041,8 +1041,17 @@ static void feedback_presented(void *data, struct wp_presentation_feedback *fbac
static void feedback_discarded(void *data, struct wp_presentation_feedback *fback)
{
if (fback)
struct vo_wayland_state *wl = data;
// Really weird hack needed here. wlroots and weston send the discarded event
// only once (not every frame) if the window is hidden. If mpv quits in this
// state, fback will get destroyed but wl->feedback (in theory, this is supposed
// to be same as fback) will not be NULL and thus will be mistakenly tried to be
// free'd again. Hack this by just setting it to NULL explicitly.
if (fback) {
wp_presentation_feedback_destroy(fback);
wl->feedback = NULL;
}
}
static const struct wp_presentation_feedback_listener feedback_listener = {