backends: Improve MetaCrtcMode lifetime management

The same MetaCrtcMode objects can be reached via the
MetaOutputInfo::modes array & MetaMonitorMode::crtc_modes arrays and via
the MetaGpuPrivate::modes list, so all of them need to hold their own
references.

In turn, those references need to dropped in meta_output_info_unref and
meta_monitor_mode_free. (meta_gpu_finalize is already dropping the
MetaGpuPrivate::modes list references)

Fixes leak:

==4092== 123 (32 direct, 91 indirect) bytes in 1 blocks are definitely lost in loss record 11,396 of 13,056
==4092==    at 0x4F81D57: g_type_create_instance (gtype.c:1929)
==4092==    by 0x4F64ABF: g_object_new_internal.part.0 (gobject.c:2606)
==4092==    by 0x4F676BA: g_object_new_internal (gobject.c:2923)
==4092==    by 0x4F676BA: g_object_new_valist (gobject.c:2945)
==4092==    by 0x4F67A0C: g_object_new (gobject.c:2418)
==4092==    by 0x4AB578B: meta_crtc_mode_virtual_new (meta-crtc-mode-virtual.c:51)
==4092==    by 0x4B081BB: meta_virtual_monitor_native_new (meta-virtual-monitor-native.c:83)
==4092==    by 0x4AC58CC: meta_monitor_manager_native_create_virtual_monitor (meta-monitor-manager-native.c:603)
==4092==    by 0x496803B: meta_monitor_manager_create_virtual_monitor (meta-monitor-manager.c:621)
==4092==    by 0x4A4A204: create_virtual_monitor (meta-screen-cast-virtual-stream-src.c:625)
==4092==    by 0x4A4A39D: ensure_virtual_monitor (meta-screen-cast-virtual-stream-src.c:663)
==4092==    by 0x4A4A461: meta_screen_cast_virtual_stream_src_notify_params_updated (meta-screen-cast-virtual-stream-src.c:684)
==4092==    by 0x4A568C5: on_stream_param_changed (meta-screen-cast-stream-src.c:1565)

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/4149>
This commit is contained in:
Michel Dänzer 2024-11-26 10:59:36 +01:00 committed by Marge Bot
parent fbe00573d7
commit 2c56c9a1da
6 changed files with 21 additions and 13 deletions

View File

@ -231,7 +231,7 @@ append_monitor (MetaMonitorManager *manager,
{
MetaCrtcMode *mode = l->data;
output_info->modes[i] = mode;
output_info->modes[i] = g_object_ref (mode);
}
output_info->n_modes = n_mode_specs;
output_info->possible_crtcs = g_new0 (MetaCrtc *, 1);
@ -347,7 +347,7 @@ append_tiled_monitor (MetaMonitorManager *manager,
{
MetaCrtcMode *mode = l->data;
output_info->modes[j] = mode;
output_info->modes[j] = g_object_ref (mode);
}
output_info->n_modes = G_N_ELEMENTS (mode_specs);

View File

@ -40,6 +40,7 @@ typedef struct _MetaMonitorMode
{
MetaMonitor *monitor;
char *id;
unsigned int n_crtc_modes;
MetaMonitorModeSpec spec;
MetaMonitorCrtcMode *crtc_modes;
} MetaMonitorMode;
@ -777,10 +778,11 @@ meta_monitor_normal_generate_modes (MetaMonitorNormal *monitor_normal)
crtc_mode_info->height,
crtc_mode);
mode->id = generate_mode_id (&mode->spec);
mode->n_crtc_modes = 1;
mode->crtc_modes = g_new (MetaMonitorCrtcMode, 1);
mode->crtc_modes[0] = (MetaMonitorCrtcMode) {
.output = output,
.crtc_mode = crtc_mode
.crtc_mode = g_object_ref (crtc_mode)
};
/*
@ -1175,8 +1177,9 @@ create_tiled_monitor_mode (MetaMonitorTiled *monitor_tiled,
meta_monitor_create_spec (monitor, width, height, reference_crtc_mode);
mode->parent.id = generate_mode_id (&mode->parent.spec);
mode->parent.n_crtc_modes = g_list_length (monitor_priv->outputs);
mode->parent.crtc_modes = g_new0 (MetaMonitorCrtcMode,
g_list_length (monitor_priv->outputs));
mode->parent.n_crtc_modes);
for (l = monitor_priv->outputs, i = 0; l; l = l->next, i++)
{
MetaOutput *output = l->data;
@ -1193,7 +1196,7 @@ create_tiled_monitor_mode (MetaMonitorTiled *monitor_tiled,
mode->parent.crtc_modes[i] = (MetaMonitorCrtcMode) {
.output = output,
.crtc_mode = tiled_crtc_mode
.crtc_mode = g_object_ref (tiled_crtc_mode)
};
is_preferred = (is_preferred &&
@ -1309,8 +1312,9 @@ create_untiled_monitor_mode (MetaMonitorTiled *monitor_tiled,
crtc_mode_info->height,
crtc_mode);
mode->parent.id = generate_mode_id (&mode->parent.spec);
mode->parent.n_crtc_modes = g_list_length (monitor_priv->outputs);
mode->parent.crtc_modes = g_new0 (MetaMonitorCrtcMode,
g_list_length (monitor_priv->outputs));
mode->parent.n_crtc_modes);
for (l = monitor_priv->outputs, i = 0; l; l = l->next, i++)
{
@ -1320,7 +1324,7 @@ create_untiled_monitor_mode (MetaMonitorTiled *monitor_tiled,
{
mode->parent.crtc_modes[i] = (MetaMonitorCrtcMode) {
.output = output,
.crtc_mode = crtc_mode
.crtc_mode = g_object_ref (crtc_mode)
};
}
else
@ -1680,6 +1684,8 @@ static void
meta_monitor_mode_free (MetaMonitorMode *monitor_mode)
{
g_free (monitor_mode->id);
for (int i = 0; i < monitor_mode->n_crtc_modes; i++)
g_clear_object (&monitor_mode->crtc_modes[i].crtc_mode);
g_free (monitor_mode->crtc_modes);
g_free (monitor_mode);
}

View File

@ -113,6 +113,8 @@ meta_output_info_unref (MetaOutputInfo *output_info)
g_free (output_info->serial);
g_free (output_info->edid_checksum_md5);
g_clear_pointer (&output_info->edid_info, meta_edid_info_free);
for (int i = 0; i < output_info->n_modes; i++)
g_object_unref (output_info->modes[i]);
g_free (output_info->modes);
g_free (output_info->possible_crtcs);
g_free (output_info->possible_clones);

View File

@ -194,13 +194,13 @@ add_common_modes (MetaOutputInfo *output_info,
crtc_mode = meta_gpu_kms_get_mode_from_kms_mode (gpu_kms,
fallback_mode,
META_CRTC_REFRESH_RATE_MODE_VARIABLE);
g_ptr_array_add (array, crtc_mode);
g_ptr_array_add (array, g_object_ref (crtc_mode));
}
crtc_mode = meta_gpu_kms_get_mode_from_kms_mode (gpu_kms,
fallback_mode,
META_CRTC_REFRESH_RATE_MODE_FIXED);
g_ptr_array_add (array, crtc_mode);
g_ptr_array_add (array, g_object_ref (crtc_mode));
}
output_info->modes = g_renew (MetaCrtcMode *, output_info->modes,
@ -318,7 +318,7 @@ init_output_modes (MetaOutputInfo *output_info,
meta_gpu_kms_get_mode_from_kms_mode (gpu_kms,
kms_mode,
META_CRTC_REFRESH_RATE_MODE_VARIABLE);
output_info->modes[i++] = crtc_mode;
output_info->modes[i++] = g_object_ref (crtc_mode);
if (!output_info->preferred_mode && kms_mode == kms_preferred_mode)
output_info->preferred_mode = crtc_mode;
}
@ -326,7 +326,7 @@ init_output_modes (MetaOutputInfo *output_info,
crtc_mode = meta_gpu_kms_get_mode_from_kms_mode (gpu_kms,
kms_mode,
META_CRTC_REFRESH_RATE_MODE_FIXED);
output_info->modes[i++] = crtc_mode;
output_info->modes[i++] = g_object_ref (crtc_mode);
if (!output_info->preferred_mode && kms_mode == kms_preferred_mode)
output_info->preferred_mode = crtc_mode;
}

View File

@ -874,7 +874,7 @@ output_info_init_modes (MetaOutputInfo *output_info,
{
if (sanity_check_duplicate (output_info->modes, n_actual_modes, mode))
{
output_info->modes[n_actual_modes] = mode;
output_info->modes[n_actual_modes] = g_object_ref (mode);
n_actual_modes += 1;
}
else

View File

@ -727,7 +727,7 @@ meta_create_monitor_test_setup (MetaBackend *backend,
int mode_index;
mode_index = setup->outputs[i].modes[j];
modes[j] = g_list_nth_data (test_setup->modes, mode_index);
modes[j] = g_object_ref (g_list_nth_data (test_setup->modes, mode_index));
}
n_possible_crtcs = setup->outputs[i].n_possible_crtcs;