From 7117e3e3df858812a3e9993dad35ca9699795702 Mon Sep 17 00:00:00 2001 From: Guillaume Desmottes <guillaume.desmottes@collabora.co.uk> Date: Tue, 31 May 2016 12:32:16 +0200 Subject: [PATCH] validate: reporter: break cyclic references with reports My patch fixing monitor leak (15e7f1bbfd84ce2cc5e6420fee2255c2be95e0f6) introduced a ref cycle between GstValidateReporter and GstValidateReport. The reports uses its reporter so it needs a ref on it to ensure it's stay alive. But reports are owned by GstValidateReporter and/or GstValidateRunner. Fix this by not taking a reference on the reporter but instead caching its name. Reviewed-by: Thibault Saunier <tsaunier@gnome.org> Differential Revision: https://phabricator.freedesktop.org/D1029 --- validate/gst/validate/gst-validate-report.c | 16 +++++++++++----- validate/gst/validate/gst-validate-report.h | 1 + 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/validate/gst/validate/gst-validate-report.c b/validate/gst/validate/gst-validate-report.c index 3d535f1965..264409304d 100644 --- a/validate/gst/validate/gst-validate-report.c +++ b/validate/gst/validate/gst-validate-report.c @@ -508,8 +508,8 @@ gst_validate_report_get_issue_id (GstValidateReport * report) static void _report_free (GstValidateReport * report) { - g_object_unref (report->reporter); g_free (report->message); + g_free (report->reporter_name); g_list_free_full (report->shadow_reports, (GDestroyNotify) gst_validate_report_unref); g_list_free_full (report->repeated_reports, @@ -529,7 +529,14 @@ gst_validate_report_new (GstValidateIssue * issue, (GstMiniObjectFreeFunction) _report_free); report->issue = issue; - report->reporter = g_object_ref (reporter); + /* The reporter is owning a ref on the report so it doesn't keep a ref to + * avoid reference cycles. But the report can also be used by + * GstValidateRunner *after* that the reporter has been destroyed, so we + * cache the reporter name to avoid crashing in + * gst_validate_report_print_detected_on if the reporter has been destroyed. + */ + report->reporter = reporter; + report->reporter_name = g_strdup (gst_validate_reporter_get_name (reporter)); report->message = g_strdup (message); g_mutex_init (&report->shadow_reports_lock); report->timestamp = @@ -849,11 +856,10 @@ gst_validate_report_print_detected_on (GstValidateReport * report) GList *tmp; gst_validate_printf (NULL, "%*s Detected on <%s", - 12, "", gst_validate_reporter_get_name (report->reporter)); + 12, "", report->reporter_name); for (tmp = report->shadow_reports; tmp; tmp = tmp->next) { GstValidateReport *shadow_report = (GstValidateReport *) tmp->data; - gst_validate_printf (NULL, ", %s", - gst_validate_reporter_get_name (shadow_report->reporter)); + gst_validate_printf (NULL, ", %s", shadow_report->reporter_name); } gst_validate_printf (NULL, ">\n"); } diff --git a/validate/gst/validate/gst-validate-report.h b/validate/gst/validate/gst-validate-report.h index 98499e3198..2617024f95 100644 --- a/validate/gst/validate/gst-validate-report.h +++ b/validate/gst/validate/gst-validate-report.h @@ -180,6 +180,7 @@ struct _GstValidateReport { GList *repeated_reports; GstValidateReportingDetails reporting_level; + gchar *reporter_name; gpointer _gst_reserved[GST_PADDING]; };