From c6b71079c1dfc63e6b1fac5f15a75ff6f0beb0f2 Mon Sep 17 00:00:00 2001 From: Thomas Vander Stichele Date: Wed, 10 May 2006 16:34:06 +0000 Subject: [PATCH] gst/tcp/gstmultifdsink.c: clean up the bufqueue when shutting down Original commit message from CVS: * gst/tcp/gstmultifdsink.c: (gst_multi_fd_sink_stop): clean up the bufqueue when shutting down * tests/check/Makefile.am: * tests/check/elements/multifdsink.c: (setup_multifdsink), (cleanup_multifdsink), (GST_START_TEST), (multifdsink_suite), (main): add a test for the leak that was just fixed --- ChangeLog | 10 +++ gst/tcp/gstmultifdsink.c | 20 ++++++ tests/check/Makefile.am | 1 + tests/check/elements/multifdsink.c | 100 +++++++++++++++++++++++++++++ 4 files changed, 131 insertions(+) create mode 100644 tests/check/elements/multifdsink.c diff --git a/ChangeLog b/ChangeLog index f42129ae24..50cd3f716c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,13 @@ +2006-05-10 Thomas Vander Stichele + + * gst/tcp/gstmultifdsink.c: (gst_multi_fd_sink_stop): + clean up the bufqueue when shutting down + * tests/check/Makefile.am: + * tests/check/elements/multifdsink.c: (setup_multifdsink), + (cleanup_multifdsink), (GST_START_TEST), (multifdsink_suite), + (main): + add a test for the leak that was just fixed + 2006-05-10 Wim Taymans * gst/adder/gstadder.c: (gst_adder_setcaps), diff --git a/gst/tcp/gstmultifdsink.c b/gst/tcp/gstmultifdsink.c index 863e77104b..4de97038ed 100644 --- a/gst/tcp/gstmultifdsink.c +++ b/gst/tcp/gstmultifdsink.c @@ -655,6 +655,8 @@ gst_multi_fd_sink_remove (GstMultiFdSink * sink, int fd) CLIENTS_UNLOCK (sink); } +/* can be called both through the signal (ie from any thread) or when stopping, + * after the writing thread has shut down */ void gst_multi_fd_sink_clear (GstMultiFdSink * sink) { @@ -1859,6 +1861,8 @@ gst_multi_fd_sink_stop (GstBaseSink * bsink) { GstMultiFdSinkClass *fclass; GstMultiFdSink *this; + GstBuffer *buf; + int i; this = GST_MULTI_FD_SINK (bsink); fclass = GST_MULTI_FD_SINK_GET_CLASS (this); @@ -1870,7 +1874,9 @@ gst_multi_fd_sink_stop (GstBaseSink * bsink) SEND_COMMAND (this, CONTROL_STOP); if (this->thread) { + GST_DEBUG_OBJECT (this, "joining thread"); g_thread_join (this->thread); + GST_DEBUG_OBJECT (this, "joined thread"); this->thread = NULL; } @@ -1895,6 +1901,20 @@ gst_multi_fd_sink_stop (GstBaseSink * bsink) this->fdset = NULL; } g_hash_table_foreach_remove (this->fd_hash, multifdsink_hash_remove, this); + + /* remove all queued buffers */ + if (this->bufqueue) { + GST_DEBUG_OBJECT (this, "Emptying bufqueue with %d buffers", + this->bufqueue->len); + for (i = this->bufqueue->len - 1; i >= 0; --i) { + buf = g_array_index (this->bufqueue, GstBuffer *, i); + GST_LOG_OBJECT (this, "Removing buffer %p (%d) with refcount %d", buf, i, + GST_MINI_OBJECT_REFCOUNT (buf)); + gst_buffer_unref (buf); + this->bufqueue = g_array_remove_index (this->bufqueue, i); + } + /* freeing the array is done in _finalize */ + } GST_OBJECT_FLAG_UNSET (this, GST_MULTI_FD_SINK_OPEN); return TRUE; diff --git a/tests/check/Makefile.am b/tests/check/Makefile.am index 314829ad4f..64e92a4224 100644 --- a/tests/check/Makefile.am +++ b/tests/check/Makefile.am @@ -38,6 +38,7 @@ check_PROGRAMS = $(check_vorbis) \ elements/audioconvert \ elements/audioresample \ elements/audiotestsrc \ + elements/multifdsink \ elements/videorate \ elements/videotestsrc \ elements/volume \ diff --git a/tests/check/elements/multifdsink.c b/tests/check/elements/multifdsink.c new file mode 100644 index 0000000000..a5742ce417 --- /dev/null +++ b/tests/check/elements/multifdsink.c @@ -0,0 +1,100 @@ +/* GStreamer + * + * Copyright (C) 2006 Thomas Vander Stichele + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include + +#include + +GstPad *mysrcpad; + +static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src", + GST_PAD_SRC, + GST_PAD_ALWAYS, + GST_STATIC_CAPS ("application/x-gdp") + ); + +GstElement * +setup_multifdsink () +{ + GstElement *multifdsink; + + GST_DEBUG ("setup_multifdsink"); + multifdsink = gst_check_setup_element ("multifdsink"); + mysrcpad = gst_check_setup_src_pad (multifdsink, &srctemplate, NULL); + + return multifdsink; +} + +void +cleanup_multifdsink (GstElement * multifdsink) +{ + GST_DEBUG ("cleanup_multifdsink"); + + gst_check_teardown_src_pad (multifdsink); + gst_check_teardown_element (multifdsink); +} + +GST_START_TEST (test_no_clients) +{ + GstElement *sink; + GstBuffer *buffer; + + sink = setup_multifdsink (); + + ASSERT_SET_STATE (sink, GST_STATE_PLAYING, GST_STATE_CHANGE_ASYNC); + + buffer = gst_buffer_new_and_alloc (4); + fail_unless (gst_pad_push (mysrcpad, buffer) == GST_FLOW_OK); + + GST_DEBUG ("cleaning up multifdsink"); + ASSERT_SET_STATE (sink, GST_STATE_NULL, GST_STATE_CHANGE_SUCCESS); + cleanup_multifdsink (sink); +} + +GST_END_TEST; + +Suite * +multifdsink_suite (void) +{ + Suite *s = suite_create ("multifdsink"); + TCase *tc_chain = tcase_create ("general"); + + suite_add_tcase (s, tc_chain); + tcase_add_test (tc_chain, test_no_clients); + + return s; +} + +int +main (int argc, char **argv) +{ + int nf; + + Suite *s = multifdsink_suite (); + SRunner *sr = srunner_create (s); + + gst_check_init (&argc, &argv); + + srunner_run_all (sr, CK_NORMAL); + nf = srunner_ntests_failed (sr); + srunner_free (sr); + + return nf; +}