validate: reporter: break cyclic references with reports

My patch fixing monitor leak (15e7f1bbfd)
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.
The best way I found to break this cycle is to introduce this purge
method. It's not great but the design is a bit tricky.

Reviewed-by: Thibault Saunier <tsaunier@gnome.org>
Differential Revision: https://phabricator.freedesktop.org/D1029
This commit is contained in:
Guillaume Desmottes 2016-05-27 15:37:00 +02:00 committed by Thibault Saunier
parent b8c821dff4
commit dc7382017d
8 changed files with 53 additions and 5 deletions

View file

@ -116,6 +116,15 @@ gst_validate_bin_monitor_get_property (GObject * object, guint prop_id,
}
}
static void
purge_and_unref_reporter (gpointer data)
{
GstValidateReporter *reporter = data;
gst_validate_reporter_purge_reports (reporter);
g_object_unref (reporter);
}
static void
gst_validate_bin_monitor_dispose (GObject * object)
{
@ -125,10 +134,13 @@ gst_validate_bin_monitor_dispose (GObject * object)
if (bin && monitor->element_added_id)
g_signal_handler_disconnect (bin, monitor->element_added_id);
if (monitor->scenario)
if (monitor->scenario) {
gst_validate_reporter_purge_reports (GST_VALIDATE_REPORTER
(monitor->scenario));
g_object_unref (monitor->scenario);
}
g_list_free_full (monitor->element_monitors, g_object_unref);
g_list_free_full (monitor->element_monitors, purge_and_unref_reporter);
G_OBJECT_CLASS (parent_class)->dispose (object);
}

View file

@ -98,6 +98,14 @@ gst_validate_element_set_media_descriptor (GstValidateMonitor * monitor,
gst_iterator_free (iterator);
}
static void
purge_and_unref_reporter (gpointer data)
{
GstValidateReporter *reporter = data;
gst_validate_reporter_purge_reports (reporter);
g_object_unref (reporter);
}
static void
gst_validate_element_monitor_dispose (GObject * object)
@ -109,7 +117,7 @@ gst_validate_element_monitor_dispose (GObject * object)
g_signal_handler_disconnect (GST_VALIDATE_MONITOR_GET_OBJECT (monitor),
monitor->pad_added_id);
g_list_free_full (monitor->pad_monitors, g_object_unref);
g_list_free_full (monitor->pad_monitors, purge_and_unref_reporter);
G_OBJECT_CLASS (parent_class)->dispose (object);
}

View file

@ -436,3 +436,22 @@ gst_validate_reporter_get_reports_count (GstValidateReporter * reporter)
return ret;
}
/**
* gst_validate_reporter_purge_reports:
* @reporter: a #GstValidateReporter
*
* Remove all the #GstValidateReport from @reporter. This should be called
* before unreffing the reporter to break cyclic references.
*/
void
gst_validate_reporter_purge_reports (GstValidateReporter * reporter)
{
GstValidateReporterPrivate *priv;
priv = g_object_get_data (G_OBJECT (reporter), REPORTER_PRIVATE);
GST_VALIDATE_REPORTER_REPORTS_LOCK (reporter);
g_hash_table_remove_all (priv->reports);
GST_VALIDATE_REPORTER_REPORTS_UNLOCK (reporter);
}

View file

@ -115,5 +115,7 @@ GList * gst_validate_reporter_get_reports (GstValidateReporter * reporter);
gint gst_validate_reporter_get_reports_count (GstValidateReporter *reporter);
GstValidateReportingDetails gst_validate_reporter_get_reporting_level (GstValidateReporter *reporter);
void gst_validate_reporter_purge_reports (GstValidateReporter * reporter);
G_END_DECLS
#endif /* _GST_VALIDATE_REPORTER_ */

View file

@ -557,6 +557,7 @@ _run_frame_analysis (GstValidateMediaDescriptorWriter * writer,
writer->priv->loop = NULL;
gst_bus_remove_signal_watch (bus);
gst_object_unref (bus);
gst_validate_reporter_purge_reports (GST_VALIDATE_REPORTER (monitor));
g_object_unref (monitor);
return TRUE;

View file

@ -155,10 +155,14 @@ out:
g_free (output_file);
g_free (expected_file);
if (reference)
if (reference) {
gst_validate_reporter_purge_reports (GST_VALIDATE_REPORTER (reference));
gst_object_unref (reference);
if (writer)
}
if (writer) {
gst_validate_reporter_purge_reports (GST_VALIDATE_REPORTER (writer));
gst_object_unref (writer);
}
if (runner)
gst_object_unref (runner);
gst_deinit ();

View file

@ -978,6 +978,7 @@ exit:
g_main_loop_unref (mainloop);
g_clear_object (&encoding_profile);
g_object_unref (pipeline);
gst_validate_reporter_purge_reports (GST_VALIDATE_REPORTER (monitor));
g_object_unref (monitor);
g_object_unref (runner);

View file

@ -657,6 +657,7 @@ exit:
g_main_loop_unref (mainloop);
g_object_unref (pipeline);
g_object_unref (runner);
gst_validate_reporter_purge_reports (GST_VALIDATE_REPORTER (monitor));
g_object_unref (monitor);
g_clear_error (&err);
#ifdef G_OS_UNIX