After an evaluation, GNOME has moved from Bugzilla to GitLab. Learn more about GitLab.
No new issues can be reported in GNOME Bugzilla anymore.
To report an issue in a GNOME project, go to GNOME GitLab.
Do not go to GNOME Gitlab for: Bluefish, Doxygen, GnuCash, GStreamer, java-gnome, LDTP, NetworkManager, Tomboy.
Bug 720661 - audiobasesink: Fix locking bug accessing ring buffer time
audiobasesink: Fix locking bug accessing ring buffer time
Status: RESOLVED FIXED
Product: GStreamer
Classification: Platform
Component: gst-plugins-base
unspecified
Other Linux
: Normal normal
: 1.2.3
Assigned To: GStreamer Maintainers
GStreamer Maintainers
Depends on:
Blocks:
 
 
Reported: 2013-12-18 09:39 UTC by Vincent Penquerc'h
Modified: 2014-01-21 10:27 UTC
See Also:
GNOME target: ---
GNOME version: ---


Attachments
Lock ring buffer acess from query function (1.31 KB, patch)
2013-12-18 09:39 UTC, Vincent Penquerc'h
reviewed Details | Review

Description Vincent Penquerc'h 2013-12-18 09:39:41 UTC
Created attachment 264467 [details] [review]
Lock ring buffer acess from query function

A position query from downstream could happen while the setcaps
function was being called (this can happen when the query comes
from a glib timeout function). The ring buffer could then be
released between gst_audio_base_sink_get_time checking rate==0
and using it to scale samples to time, ending up dividing by 0.

Note that I am not 100% sure it it always safe to get the stream lock here,
it seems to work though.

Relevant backtrace threads follow:

Thread 6 (Thread 0x7fe9aa6dc700 (LWP 6383))

  • #0 __lll_unlock_wake
    at ../nptl/sysdeps/unix/sysv/linux/x86_64/lowlevellock.S line 368
  • #1 _L_unlock_644
    from /lib/x86_64-linux-gnu/libpthread.so.0
  • #2 __pthread_mutex_unlock_usercnt
    at pthread_mutex_unlock.c line 52
  • #3 __pthread_mutex_unlock
    at pthread_mutex_unlock.c line 290
  • #4 g_mutex_unlock
    from /lib/x86_64-linux-gnu/libglib-2.0.so.0
  • #5 gst_audio_ring_buffer_release
    at gstaudioringbuffer.c line 696
  • #6 gst_audio_base_sink_setcaps
    at gstaudiobasesink.c line 870
  • #7 gst_base_sink_default_event
    at gstbasesink.c line 3036
  • #8 gst_base_sink_event
    at gstbasesink.c line 3138
  • #9 gst_pad_send_event_unchecked
    at gstpad.c line 4995
  • #10 gst_pad_push_event_unchecked
    at gstpad.c line 4691
  • #11 push_sticky
    at gstpad.c line 3324
  • #12 events_foreach
    at gstpad.c line 533
  • #13 check_sticky
    at gstpad.c line 3380
  • #14 gst_pad_push_event
    at gstpad.c line 4808
  • #15 event_forward_func
    at gstpad.c line 2741
  • #16 gst_pad_forward
    at gstpad.c line 2695
  • #17 gst_pad_event_default
    at gstpad.c line 2792
  • #18 gst_pad_send_event_unchecked
    at gstpad.c line 4995
  • #19 gst_pad_push_event_unchecked
    at gstpad.c line 4691
  • #20 push_sticky
    at gstpad.c line 3324
  • #21 events_foreach
    at gstpad.c line 533
  • #22 check_sticky
    at gstpad.c line 3380
  • #23 gst_pad_push_event
    at gstpad.c line 4808
  • #24 event_forward_func
    at gstpad.c line 2741
  • #25 gst_pad_forward
    at gstpad.c line 2695
  • #26 gst_pad_event_default
    at gstpad.c line 2792
  • #27 gst_pad_send_event_unchecked
    at gstpad.c line 4995
  • #28 gst_pad_push_event_unchecked
    at gstpad.c line 4691
  • #29 push_sticky
    at gstpad.c line 3324
  • #30 events_foreach
    at gstpad.c line 533
  • #31 check_sticky
    at gstpad.c line 3380
  • #32 gst_pad_push_event
    at gstpad.c line 4808
  • #33 gst_pad_set_caps
    at ../../../gst/gstcompat.h line 55
  • #34 gst_base_transform_setcaps
    at gstbasetransform.c line 1348
  • #35 gst_base_transform_sink_eventfunc
    at gstbasetransform.c line 1860
  • #36 gst_pad_send_event_unchecked
    at gstpad.c line 4995
  • #37 gst_pad_push_event_unchecked
    at gstpad.c line 4691
  • #38 push_sticky
    at gstpad.c line 3324
  • #39 events_foreach
    at gstpad.c line 533
  • #40 check_sticky
    at gstpad.c line 3380
  • #41 gst_pad_push_event
    at gstpad.c line 4808
  • #42 gst_pad_set_caps
    at ../../../gst/gstcompat.h line 55
  • #43 gst_base_transform_setcaps
    at gstbasetransform.c line 1348
  • #44 gst_base_transform_sink_eventfunc
    at gstbasetransform.c line 1860
  • #45 gst_pad_send_event_unchecked
    at gstpad.c line 4995
  • #46 gst_pad_push_event_unchecked
    at gstpad.c line 4691
  • #47 push_sticky
    at gstpad.c line 3324
  • #48 events_foreach
    at gstpad.c line 533
  • #49 check_sticky
    at gstpad.c line 3380
  • #50 gst_pad_push_event
    at gstpad.c line 4808
  • #51 gst_pad_set_caps
    at ../../../gst/gstcompat.h line 55
  • #52 gst_base_transform_setcaps
    at gstbasetransform.c line 1348
  • #53 gst_base_transform_sink_eventfunc
    at gstbasetransform.c line 1860
  • #54 gst_pad_send_event_unchecked
    at gstpad.c line 4995
  • #55 gst_pad_push_event_unchecked
    at gstpad.c line 4691
  • #56 push_sticky
    at gstpad.c line 3324
  • #57 events_foreach
    at gstpad.c line 533
  • #58 check_sticky
    at gstpad.c line 3380
  • #59 gst_pad_push_event
    at gstpad.c line 4808
  • #60 event_forward_func
    at gstpad.c line 2741
  • #61 gst_pad_forward
    at gstpad.c line 2695
  • #62 gst_pad_event_default
    at gstpad.c line 2792
  • #63 gst_play_sink_convert_bin_sink_event
    at gstplaysinkconvertbin.c line 254
  • #64 gst_pad_send_event_unchecked
    at gstpad.c line 4995
  • #65 gst_pad_push_event_unchecked
    at gstpad.c line 4691
  • #66 push_sticky
    at gstpad.c line 3324
  • #67 events_foreach
    at gstpad.c line 533
  • #68 check_sticky
    at gstpad.c line 3380
  • #69 gst_pad_push_event
    at gstpad.c line 4808
  • #70 gst_queue_push_one
    at gstqueue.c line 1176
  • #71 gst_queue_loop
    at gstqueue.c line 1253
  • #72 gst_task_func
    at gsttask.c line 316
  • #73 ??
    from /lib/x86_64-linux-gnu/libglib-2.0.so.0
  • #74 ??
    from /lib/x86_64-linux-gnu/libglib-2.0.so.0
  • #75 start_thread
    at pthread_create.c line 308
  • #76 clone
    at ../sysdeps/unix/sysv/linux/x86_64/clone.S line 112
  • #77 ??

Thread 1 (Thread 0x7fe9c051b700 (LWP 6379))

  • #0 g_logv
    from /lib/x86_64-linux-gnu/libglib-2.0.so.0
  • #1 g_log
    from /lib/x86_64-linux-gnu/libglib-2.0.so.0
  • #2 _gst_util_uint64_scale_int
    at gstutils.c line 586
  • #3 gst_audio_base_sink_get_time
    at gstaudiobasesink.c line 540
  • #4 gst_audio_base_sink_get_time
    at gstaudiobasesink.c line 519
  • #5 gst_audio_clock_get_internal_time
    at gstaudioclock.c line 192
  • #6 gst_clock_get_internal_time
    at gstclock.c line 949
  • #7 gst_clock_get_time
    at gstclock.c line 989
  • #8 gst_base_sink_get_position
    at gstbasesink.c line 4500
  • #9 default_element_query
    at gstbasesink.c line 4630
  • #10 gst_audio_base_sink_query
    at gstaudiobasesink.c line 509
  • #11 bin_query_position_fold
  • #12 gst_iterator_fold
    at gstiterator.c line 614
  • #13 bin_iterate_fold
    at gstbin.c line 3935
  • #14 gst_bin_query
    at gstbin.c line 4045
  • #15 bin_query_position_fold
    at gstbin.c line 3818
  • #16 gst_iterator_fold
    at gstiterator.c line 614
  • #17 bin_iterate_fold
    at gstbin.c line 3935
  • #18 gst_bin_query
    at gstbin.c line 4045
  • #19 bin_query_position_fold
    at gstbin.c line 3818
  • #20 gst_iterator_fold
    at gstiterator.c line 614
  • #21 bin_iterate_fold
    at gstbin.c line 3935
  • #22 gst_bin_query
    at gstbin.c line 4045
  • #23 bin_query_position_fold
    at gstbin.c line 3818
  • #24 gst_iterator_fold
  • #25 bin_iterate_fold
    at gstbin.c line 3935
  • #26 gst_bin_query
    at gstbin.c line 4045
  • #27 gst_play_bin_query
    at gstplaybin2.c line 2663
  • #28 gst_element_query_position
    at gstutils.c line 2162
  • #29 play_timeout
    at gst-play.c line 283
  • #30 ??
    from /lib/x86_64-linux-gnu/libglib-2.0.so.0
  • #31 g_main_context_dispatch
    from /lib/x86_64-linux-gnu/libglib-2.0.so.0
  • #32 ??
    from /lib/x86_64-linux-gnu/libglib-2.0.so.0
  • #33 g_main_loop_run
    from /lib/x86_64-linux-gnu/libglib-2.0.so.0
  • #34 do_play
    at gst-play.c line 393
  • #35 main
    at gst-play.c line 512

Comment 1 Sebastian Dröge (slomo) 2014-01-03 09:36:38 UTC
Comment on attachment 264467 [details] [review]
Lock ring buffer acess from query function

I think taking the object lock there is fine... but gst_audio_base_sink_query_pad() does not call anything other than a ringbuffer function. So I would say that the locking should be done one level below inside the ringbuffer?
Comment 2 Vincent Penquerc'h 2014-01-03 10:30:08 UTC
I think the audio sink would need to lock as a block a fair amount of the code in gst_audio_base_sink_setcaps, which would mean the audio sink itself would need adding lock/unlock calls (probably by adding gst_audio_ring_buffer_{,un}lock APIs). This seems more complex, unless I'm not seeing an easier way.
When locking at the base sink level, we already get this lock for free.
Comment 3 Sebastian Dröge (slomo) 2014-01-21 09:08:46 UTC
Sounds sensible but please discuss with Wim before pushing.
Comment 4 Wim Taymans 2014-01-21 10:03:28 UTC
I don't really want to block the whole object for all queries.. The problem is here that the get-time function of the clock calls into the basesink without locking for performance reasons. Essentially, you could have this problem as well if someone gets the current time and the ringbuffer is released.

I'm thinking of doing the rate and ringbuffer checks only once in gst_audio_base_sink_get_time().
Comment 5 Wim Taymans 2014-01-21 10:27:34 UTC
Do you think this is enough for now?

commit 6a88d6f8cdf640d827f1082e4f498fc375fad781
Author: Wim Taymans <wtaymans@redhat.com>
Date:   Tue Jan 21 11:21:56 2014 +0100

    audiobasesink: make _get_time more threadsafe
    
    We call the _get_time function from the provided clock and we don't lock
    the sink object for performance reasons. Make sure we only read and
    check variables once so that they don't change while we are executing
    the code.
    
    Fixes https://bugzilla.gnome.org/show_bug.cgi?id=720661