From 2c56c9a1da944cd566f289faebb8a560982e7827 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michel=20D=C3=A4nzer?= Date: Tue, 26 Nov 2024 10:59:36 +0100 Subject: [PATCH] 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: --- src/backends/meta-monitor-manager-dummy.c | 4 ++-- src/backends/meta-monitor.c | 16 +++++++++++----- src/backends/meta-output.c | 2 ++ src/backends/native/meta-output-kms.c | 8 ++++---- src/backends/x11/meta-output-xrandr.c | 2 +- src/tests/meta-monitor-test-utils.c | 2 +- 6 files changed, 21 insertions(+), 13 deletions(-) diff --git a/src/backends/meta-monitor-manager-dummy.c b/src/backends/meta-monitor-manager-dummy.c index 45ba0242e..f96f261af 100644 --- a/src/backends/meta-monitor-manager-dummy.c +++ b/src/backends/meta-monitor-manager-dummy.c @@ -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); diff --git a/src/backends/meta-monitor.c b/src/backends/meta-monitor.c index badde7cea..4f8a43604 100644 --- a/src/backends/meta-monitor.c +++ b/src/backends/meta-monitor.c @@ -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); } diff --git a/src/backends/meta-output.c b/src/backends/meta-output.c index aca5a42f5..b278d7ecf 100644 --- a/src/backends/meta-output.c +++ b/src/backends/meta-output.c @@ -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); diff --git a/src/backends/native/meta-output-kms.c b/src/backends/native/meta-output-kms.c index 27b7533a5..e522947d1 100644 --- a/src/backends/native/meta-output-kms.c +++ b/src/backends/native/meta-output-kms.c @@ -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; } diff --git a/src/backends/x11/meta-output-xrandr.c b/src/backends/x11/meta-output-xrandr.c index 5b9b70ed4..55f32ae11 100644 --- a/src/backends/x11/meta-output-xrandr.c +++ b/src/backends/x11/meta-output-xrandr.c @@ -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 diff --git a/src/tests/meta-monitor-test-utils.c b/src/tests/meta-monitor-test-utils.c index bfd6e8fd3..243e8a6e3 100644 --- a/src/tests/meta-monitor-test-utils.c +++ b/src/tests/meta-monitor-test-utils.c @@ -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;