Calling libvlc_media_player_stop() on DVB-T channel never returns
Posted: 28 Jan 2015 03:11
I have been struggling with this for a few days. I think it's a bug but it's over my head to pin down exactly what's happening.
We have an app using libvlc to play TV streams. In this case it is playing an MRL like "dvb-t://frequency=177500000". This generally works but there's an annoying case, with the new tv tuner driver we have, where libvlc will stop playing any streams (tv or not) until you restart the app. To reproduce it, I:
1) Start trying to play a BOGUS frequency, i.e. one with no data on it.
2) Shortly after... call libvlc_media_player_stop(). The key is that it must be done quickly, within a couple seconds.
3) Now, no MRLs will play, including ones on the filesystem (e.g. foo.mpg).
I have gathered some info. When the problem happens, I can stop the program in gdb and see
(gdb) bt
#0 0x00132416 in __kernel_vsyscall ()
#1 0x016ad460 in poll () from /lib/i386-linux-gnu/libc.so.6
#2 0x045c3327 in dvb_read (d=0xae609b20, buf=0xae60afa0, len=3760) at dtv/linux.c:328
#3 0x045be610 in Read (access=0xae609aa8) at dtv/access.c:512
#4 0x017c75ee in AReadBlock (s=<optimized out>, pb_eof=0xb1236f9f) at input/stream.c:1725
#5 0x017c79ad in AStreamPrebufferBlock (s=0xae60a3c0) at input/stream.c:684
#6 0x017ca79a in stream_AccessNew (p_access=0xae609aa8, ppsz_list=0x0) at input/stream.c:378
#7 0x017be3a5 in InputSourceInit (p_input=0xb4727288, in=<optimized out>, psz_mrl=0xae83f718 "dvb-c://:frequency=330000000",
psz_forced_demux=0x0, b_in_can_fail=false) at input/input.c:2486
#8 0x017bf56f in Init (p_input=0xb4727288) at input/input.c:1225
#9 0x017c3a70 in Run (obj=0xb4727288) at input/input.c:521
#10 0x01488d4c in start_thread () from /lib/i386-linux-gnu/libpthread.so.0
#11 0x016bbbae in clone () from /lib/i386-linux-gnu/libc.so.6
#0 0x00132416 in __kernel_vsyscall ()
#1 0x01489e1c in pthread_join () from /lib/i386-linux-gnu/libpthread.so.0
#2 0x01814e23 in vlc_join (handle=2971892544, result=0x0) at posix/thread.c:749
#3 0x017bd8e5 in input_Join (p_input=0xb4727288) at input/input.c:256
#4 0x017bd932 in input_Close (p_input=0xb4727288) at input/input.c:271
#5 0x0015ac9e in release_input_thread (p_mi=0xb4719290, b_input_abort=<optimized out>) at media_player.c:124
#6 0x0015d273 in libvlc_media_player_stop (p_mi=0xb4719290) at media_player.c:789 [this is where our app seems to start blocking. I notice after this point that no other commands are processed by our vlcworker object]
#7 0x0811e7b2 in VLCWorker::doStop (this=0x8343f40) at vlcworker.cpp:719
#8 0x08124069 in VLCWorker::doSetMrl (this=0x8343f40, mrl=...) at vlcworker.cpp:553
#9 0x08125f5e in VLCWorker::doCommand (this=0x8343f40, cmd=6, arg1=...) at vlcworker.cpp:110
#10 0x0815fedd in VLCWorker::qt_static_metacall (_o=0x8343f40, _c=QMetaObject::InvokeMetaMethod, _id=38, _a=0x9fb6cc0)
at moc_vlcworker.cpp:158
#11 0x0132c8e1 in QMetaCallEvent::placeMetaCall(QObject*) () from /usr/lib/i386-linux-gnu/libQtCore.so.4
#12 0x01335abb in QObject::event(QEvent*) () from /usr/lib/i386-linux-gnu/libQtCore.so.4
#13 0x006b2f74 in QApplicationPrivate::notify_helper(QObject*, QEvent*) () from /usr/lib/i386-linux-gnu/libQtGui.so.4
#14 0x006b82dd in QApplication::notify(QObject*, QEvent*) () from /usr/lib/i386-linux-gnu/libQtGui.so.4
#15 0x0131a67e in QCoreApplication::notifyInternal(QObject*, QEvent*) () from /usr/lib/i386-linux-gnu/libQtCore.so.4
#16 0x0131e7d8 in QCoreApplicationPrivate::sendPostedEvents(QObject*, int, QThreadData*) ()
from /usr/lib/i386-linux-gnu/libQtCore.so.4
#17 0x0131eb0c in QCoreApplication::sendPostedEvents(QObject*, int) () from /usr/lib/i386-linux-gnu/libQtCore.so.4
#18 0x0134d2e4 in ?? () from /usr/lib/i386-linux-gnu/libQtCore.so.4
#19 0x0204bd86 in g_main_context_dispatch () from /lib/i386-linux-gnu/libglib-2.0.so.0
#20 0x0204c125 in ?? () from /lib/i386-linux-gnu/libglib-2.0.so.0
#21 0x0204c201 in g_main_context_iteration () from /lib/i386-linux-gnu/libglib-2.0.so.0
#22 0x0134d6d7 in QEventDispatcherGlib::processEvents(QFlags<QEventLoop::ProcessEventsFlag>) ()
from /usr/lib/i386-linux-gnu/libQtCore.so.4
#23 0x01318f1d in QEventLoop::processEvents(QFlags<QEventLoop::ProcessEventsFlag>) () from /usr/lib/i386-linux-gnu/libQtCore.so.4
#24 0x013191b9 in QEventLoop::exec(QFlags<QEventLoop::ProcessEventsFlag>) () from /usr/lib/i386-linux-gnu/libQtCore.so.4
#25 0x08121e9b in VLCWorker::mainLoop (this=0x8343f40) at vlcworker.cpp:83
#26 0x0815fe60 in VLCWorker::qt_static_metacall (_o=0x8343f40, _c=QMetaObject::InvokeMetaMethod, _id=32, _a=0xb50ff250)
at moc_vlcworker.cpp:152
#27 0x01331401 in QMetaObject::activate(QObject*, QMetaObject const*, int, void**) () from /usr/lib/i386-linux-gnu/libQtCore.so.4
#28 0x013811c5 in QThread::started() () from /usr/lib/i386-linux-gnu/libQtCore.so.4
#29 0x01203fe7 in ?? () from /usr/lib/i386-linux-gnu/libQtCore.so.4
#30 0x01488d4c in start_thread () from /lib/i386-linux-gnu/libpthread.so.0
#31 0x016bbbae in clone () from /lib/i386-linux-gnu/libc.so.6
And I've dug some more. It seems like dvb_read() isn't able to get any data (because it's a bogus frequency) and I think that's part of the problem. For some reason, libvlc_media_player_stop() isn't able to kill the input thread. It just keeps running. I added some print statements before the poll() call in the first backtrace and I can see the poll() line is running over and over again.
As noted, the problem doesn't occur if you wait a couple seconds, but that's not an option because the user can hit stop at any time.
I'm wondering if this is familiar to anyone. Why wouldn't libvlc_media_player_stop work? I took a stroll through input.c -> stream.c -> dtv/access.c -> dtv/linux.c but I didn't see anything obvious, but of course it gets abstract pretty quickly.
We have an app using libvlc to play TV streams. In this case it is playing an MRL like "dvb-t://frequency=177500000". This generally works but there's an annoying case, with the new tv tuner driver we have, where libvlc will stop playing any streams (tv or not) until you restart the app. To reproduce it, I:
1) Start trying to play a BOGUS frequency, i.e. one with no data on it.
2) Shortly after... call libvlc_media_player_stop(). The key is that it must be done quickly, within a couple seconds.
3) Now, no MRLs will play, including ones on the filesystem (e.g. foo.mpg).
I have gathered some info. When the problem happens, I can stop the program in gdb and see
(gdb) bt
#0 0x00132416 in __kernel_vsyscall ()
#1 0x016ad460 in poll () from /lib/i386-linux-gnu/libc.so.6
#2 0x045c3327 in dvb_read (d=0xae609b20, buf=0xae60afa0, len=3760) at dtv/linux.c:328
#3 0x045be610 in Read (access=0xae609aa8) at dtv/access.c:512
#4 0x017c75ee in AReadBlock (s=<optimized out>, pb_eof=0xb1236f9f) at input/stream.c:1725
#5 0x017c79ad in AStreamPrebufferBlock (s=0xae60a3c0) at input/stream.c:684
#6 0x017ca79a in stream_AccessNew (p_access=0xae609aa8, ppsz_list=0x0) at input/stream.c:378
#7 0x017be3a5 in InputSourceInit (p_input=0xb4727288, in=<optimized out>, psz_mrl=0xae83f718 "dvb-c://:frequency=330000000",
psz_forced_demux=0x0, b_in_can_fail=false) at input/input.c:2486
#8 0x017bf56f in Init (p_input=0xb4727288) at input/input.c:1225
#9 0x017c3a70 in Run (obj=0xb4727288) at input/input.c:521
#10 0x01488d4c in start_thread () from /lib/i386-linux-gnu/libpthread.so.0
#11 0x016bbbae in clone () from /lib/i386-linux-gnu/libc.so.6
#0 0x00132416 in __kernel_vsyscall ()
#1 0x01489e1c in pthread_join () from /lib/i386-linux-gnu/libpthread.so.0
#2 0x01814e23 in vlc_join (handle=2971892544, result=0x0) at posix/thread.c:749
#3 0x017bd8e5 in input_Join (p_input=0xb4727288) at input/input.c:256
#4 0x017bd932 in input_Close (p_input=0xb4727288) at input/input.c:271
#5 0x0015ac9e in release_input_thread (p_mi=0xb4719290, b_input_abort=<optimized out>) at media_player.c:124
#6 0x0015d273 in libvlc_media_player_stop (p_mi=0xb4719290) at media_player.c:789 [this is where our app seems to start blocking. I notice after this point that no other commands are processed by our vlcworker object]
#7 0x0811e7b2 in VLCWorker::doStop (this=0x8343f40) at vlcworker.cpp:719
#8 0x08124069 in VLCWorker::doSetMrl (this=0x8343f40, mrl=...) at vlcworker.cpp:553
#9 0x08125f5e in VLCWorker::doCommand (this=0x8343f40, cmd=6, arg1=...) at vlcworker.cpp:110
#10 0x0815fedd in VLCWorker::qt_static_metacall (_o=0x8343f40, _c=QMetaObject::InvokeMetaMethod, _id=38, _a=0x9fb6cc0)
at moc_vlcworker.cpp:158
#11 0x0132c8e1 in QMetaCallEvent::placeMetaCall(QObject*) () from /usr/lib/i386-linux-gnu/libQtCore.so.4
#12 0x01335abb in QObject::event(QEvent*) () from /usr/lib/i386-linux-gnu/libQtCore.so.4
#13 0x006b2f74 in QApplicationPrivate::notify_helper(QObject*, QEvent*) () from /usr/lib/i386-linux-gnu/libQtGui.so.4
#14 0x006b82dd in QApplication::notify(QObject*, QEvent*) () from /usr/lib/i386-linux-gnu/libQtGui.so.4
#15 0x0131a67e in QCoreApplication::notifyInternal(QObject*, QEvent*) () from /usr/lib/i386-linux-gnu/libQtCore.so.4
#16 0x0131e7d8 in QCoreApplicationPrivate::sendPostedEvents(QObject*, int, QThreadData*) ()
from /usr/lib/i386-linux-gnu/libQtCore.so.4
#17 0x0131eb0c in QCoreApplication::sendPostedEvents(QObject*, int) () from /usr/lib/i386-linux-gnu/libQtCore.so.4
#18 0x0134d2e4 in ?? () from /usr/lib/i386-linux-gnu/libQtCore.so.4
#19 0x0204bd86 in g_main_context_dispatch () from /lib/i386-linux-gnu/libglib-2.0.so.0
#20 0x0204c125 in ?? () from /lib/i386-linux-gnu/libglib-2.0.so.0
#21 0x0204c201 in g_main_context_iteration () from /lib/i386-linux-gnu/libglib-2.0.so.0
#22 0x0134d6d7 in QEventDispatcherGlib::processEvents(QFlags<QEventLoop::ProcessEventsFlag>) ()
from /usr/lib/i386-linux-gnu/libQtCore.so.4
#23 0x01318f1d in QEventLoop::processEvents(QFlags<QEventLoop::ProcessEventsFlag>) () from /usr/lib/i386-linux-gnu/libQtCore.so.4
#24 0x013191b9 in QEventLoop::exec(QFlags<QEventLoop::ProcessEventsFlag>) () from /usr/lib/i386-linux-gnu/libQtCore.so.4
#25 0x08121e9b in VLCWorker::mainLoop (this=0x8343f40) at vlcworker.cpp:83
#26 0x0815fe60 in VLCWorker::qt_static_metacall (_o=0x8343f40, _c=QMetaObject::InvokeMetaMethod, _id=32, _a=0xb50ff250)
at moc_vlcworker.cpp:152
#27 0x01331401 in QMetaObject::activate(QObject*, QMetaObject const*, int, void**) () from /usr/lib/i386-linux-gnu/libQtCore.so.4
#28 0x013811c5 in QThread::started() () from /usr/lib/i386-linux-gnu/libQtCore.so.4
#29 0x01203fe7 in ?? () from /usr/lib/i386-linux-gnu/libQtCore.so.4
#30 0x01488d4c in start_thread () from /lib/i386-linux-gnu/libpthread.so.0
#31 0x016bbbae in clone () from /lib/i386-linux-gnu/libc.so.6
And I've dug some more. It seems like dvb_read() isn't able to get any data (because it's a bogus frequency) and I think that's part of the problem. For some reason, libvlc_media_player_stop() isn't able to kill the input thread. It just keeps running. I added some print statements before the poll() call in the first backtrace and I can see the poll() line is running over and over again.
As noted, the problem doesn't occur if you wait a couple seconds, but that's not an option because the user can hit stop at any time.
I'm wondering if this is familiar to anyone. Why wouldn't libvlc_media_player_stop work? I took a stroll through input.c -> stream.c -> dtv/access.c -> dtv/linux.c but I didn't see anything obvious, but of course it gets abstract pretty quickly.