mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-18 14:26:43 +00:00
pad: Fix problem with destroy callback not being called
When we unblock a pad with the same user_data, the destroy callback is not called. This leads to refcounting leaks that cannot be avoided. Instead always call the destroy notify whenever we install a new pad block. In particular, this fixes a nasty pad leak in decodebin2. Also update the unit test to have more accurate comments and test the required behaviour.
This commit is contained in:
parent
5e577aa385
commit
381d35fd1e
2 changed files with 17 additions and 6 deletions
|
@ -1030,8 +1030,7 @@ gst_pad_set_blocked_async_full (GstPad * pad, gboolean blocked,
|
||||||
|
|
||||||
GST_OBJECT_FLAG_SET (pad, GST_PAD_BLOCKED);
|
GST_OBJECT_FLAG_SET (pad, GST_PAD_BLOCKED);
|
||||||
|
|
||||||
if (pad->block_destroy_data && pad->block_data &&
|
if (pad->block_destroy_data && pad->block_data)
|
||||||
pad->block_data != user_data)
|
|
||||||
pad->block_destroy_data (pad->block_data);
|
pad->block_destroy_data (pad->block_data);
|
||||||
|
|
||||||
pad->block_callback = callback;
|
pad->block_callback = callback;
|
||||||
|
@ -1048,8 +1047,7 @@ gst_pad_set_blocked_async_full (GstPad * pad, gboolean blocked,
|
||||||
|
|
||||||
GST_OBJECT_FLAG_UNSET (pad, GST_PAD_BLOCKED);
|
GST_OBJECT_FLAG_UNSET (pad, GST_PAD_BLOCKED);
|
||||||
|
|
||||||
if (pad->block_destroy_data && pad->block_data &&
|
if (pad->block_destroy_data && pad->block_data)
|
||||||
pad->block_data != user_data)
|
|
||||||
pad->block_destroy_data (pad->block_data);
|
pad->block_destroy_data (pad->block_data);
|
||||||
|
|
||||||
pad->block_callback = callback;
|
pad->block_callback = callback;
|
||||||
|
|
|
@ -802,6 +802,7 @@ block_async_full_destroy (gpointer user_data)
|
||||||
|
|
||||||
fail_unless (*state < 2);
|
fail_unless (*state < 2);
|
||||||
|
|
||||||
|
GST_DEBUG ("setting state to 2");
|
||||||
*state = 2;
|
*state = 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -811,6 +812,7 @@ block_async_full_cb (GstPad * pad, gboolean blocked, gpointer user_data)
|
||||||
*(gint *) user_data = (gint) blocked;
|
*(gint *) user_data = (gint) blocked;
|
||||||
|
|
||||||
gst_pad_push_event (pad, gst_event_new_flush_start ());
|
gst_pad_push_event (pad, gst_event_new_flush_start ());
|
||||||
|
GST_DEBUG ("setting state to 1");
|
||||||
}
|
}
|
||||||
|
|
||||||
GST_START_TEST (test_block_async_full_destroy)
|
GST_START_TEST (test_block_async_full_destroy)
|
||||||
|
@ -833,14 +835,25 @@ GST_START_TEST (test_block_async_full_destroy)
|
||||||
fail_unless (state == 1);
|
fail_unless (state == 1);
|
||||||
gst_pad_push_event (pad, gst_event_new_flush_stop ());
|
gst_pad_push_event (pad, gst_event_new_flush_stop ());
|
||||||
|
|
||||||
/* call with the same user_data, should not call the destroy_notify function
|
/* pad was already blocked so nothing happens */
|
||||||
*/
|
|
||||||
gst_pad_set_blocked_async_full (pad, TRUE, block_async_full_cb,
|
gst_pad_set_blocked_async_full (pad, TRUE, block_async_full_cb,
|
||||||
&state, block_async_full_destroy);
|
&state, block_async_full_destroy);
|
||||||
fail_unless (state == 1);
|
fail_unless (state == 1);
|
||||||
|
|
||||||
|
/* unblock with the same data, callback is called */
|
||||||
|
gst_pad_set_blocked_async_full (pad, FALSE, block_async_full_cb,
|
||||||
|
&state, block_async_full_destroy);
|
||||||
|
fail_unless (state == 2);
|
||||||
|
|
||||||
|
/* block with the same data, callback is called */
|
||||||
|
state = 1;
|
||||||
|
gst_pad_set_blocked_async_full (pad, TRUE, block_async_full_cb,
|
||||||
|
&state, block_async_full_destroy);
|
||||||
|
fail_unless (state == 2);
|
||||||
|
|
||||||
/* now change user_data (to NULL in this case) so destroy_notify should be
|
/* now change user_data (to NULL in this case) so destroy_notify should be
|
||||||
* called */
|
* called */
|
||||||
|
state = 1;
|
||||||
gst_pad_set_blocked_async_full (pad, FALSE, block_async_full_cb,
|
gst_pad_set_blocked_async_full (pad, FALSE, block_async_full_cb,
|
||||||
NULL, block_async_full_destroy);
|
NULL, block_async_full_destroy);
|
||||||
fail_unless (state == 2);
|
fail_unless (state == 2);
|
||||||
|
|
Loading…
Reference in a new issue