mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-27 04:01:08 +00:00
alsasink: fix occasional crash intersecting invalid values
When a pipeline using alsasink and push mode upstream fails to preroll, the following state will be the case: - A loop upstream will be PAUSED, pushing a first buffer - alsasink will be READY, pending PAUSED, because async On error, the pipeline will switch to NULL. alsasink is in READY, so goes to NULL immediately. It zeroes its cached caps. Meanwhile, the upstream loop can cause a caps query, conccurent with the state change. This will use those cached caps. If the zeroing happens between the NULL test and the dereferencing, GStreamer will critical down in the GstValue code. Since it appears that such a gap between states (PAUSED and pushing upstream, and NULL downstream) is expected, we need to protect the read/write access to the cached caps. This fixes the critical. See https://bugzilla.gnome.org/show_bug.cgi?id=731121
This commit is contained in:
parent
d2ea3260e9
commit
3b2d583373
1 changed files with 16 additions and 4 deletions
|
@ -280,7 +280,9 @@ gst_alsasink_getcaps (GstBaseSink * bsink, GstCaps * filter)
|
|||
GstAlsaSink *sink = GST_ALSA_SINK (bsink);
|
||||
GstCaps *caps, *templ_caps;
|
||||
|
||||
GST_OBJECT_LOCK (sink);
|
||||
if (sink->handle == NULL) {
|
||||
GST_OBJECT_UNLOCK (sink);
|
||||
GST_DEBUG_OBJECT (sink, "device not open, using template caps");
|
||||
return NULL; /* base class will get template caps for us */
|
||||
}
|
||||
|
@ -289,20 +291,26 @@ gst_alsasink_getcaps (GstBaseSink * bsink, GstCaps * filter)
|
|||
if (filter) {
|
||||
caps = gst_caps_intersect_full (filter, sink->cached_caps,
|
||||
GST_CAPS_INTERSECT_FIRST);
|
||||
GST_OBJECT_UNLOCK (sink);
|
||||
GST_LOG_OBJECT (sink, "Returning cached caps %" GST_PTR_FORMAT " with "
|
||||
"filter %" GST_PTR_FORMAT " applied: %" GST_PTR_FORMAT,
|
||||
sink->cached_caps, filter, caps);
|
||||
return caps;
|
||||
} else {
|
||||
GST_LOG_OBJECT (sink, "Returning cached caps %" GST_PTR_FORMAT,
|
||||
sink->cached_caps);
|
||||
return gst_caps_ref (sink->cached_caps);
|
||||
caps = gst_caps_ref (sink->cached_caps);
|
||||
GST_OBJECT_UNLOCK (sink);
|
||||
GST_LOG_OBJECT (sink, "Returning cached caps %" GST_PTR_FORMAT, caps);
|
||||
return caps;
|
||||
}
|
||||
}
|
||||
|
||||
element_class = GST_ELEMENT_GET_CLASS (sink);
|
||||
pad_template = gst_element_class_get_pad_template (element_class, "sink");
|
||||
g_return_val_if_fail (pad_template != NULL, NULL);
|
||||
if (pad_template == NULL) {
|
||||
GST_OBJECT_UNLOCK (sink);
|
||||
g_assert_not_reached ();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
templ_caps = gst_pad_template_get_caps (pad_template);
|
||||
caps = gst_alsa_probe_supported_formats (GST_OBJECT (sink), sink->device,
|
||||
|
@ -313,6 +321,8 @@ gst_alsasink_getcaps (GstBaseSink * bsink, GstCaps * filter)
|
|||
sink->cached_caps = gst_caps_ref (caps);
|
||||
}
|
||||
|
||||
GST_OBJECT_UNLOCK (sink);
|
||||
|
||||
GST_INFO_OBJECT (sink, "returning caps %" GST_PTR_FORMAT, caps);
|
||||
|
||||
if (filter) {
|
||||
|
@ -953,11 +963,13 @@ gst_alsasink_close (GstAudioSink * asink)
|
|||
{
|
||||
GstAlsaSink *alsa = GST_ALSA_SINK (asink);
|
||||
|
||||
GST_OBJECT_LOCK (asink);
|
||||
if (alsa->handle) {
|
||||
snd_pcm_close (alsa->handle);
|
||||
alsa->handle = NULL;
|
||||
}
|
||||
gst_caps_replace (&alsa->cached_caps, NULL);
|
||||
GST_OBJECT_UNLOCK (asink);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue