[mythtv-commits] Ticket #13571: Crash of backend on delete of program being recorded
MythTV
noreply at mythtv.org
Sat Apr 4 21:33:14 UTC 2020
#13571: Crash of backend on delete of program being recorded
--------------------------------+-------------------------------
Reporter: Klaas de Waal | Owner: Klaas de Waal
Type: Bug Report - Crash | Status: assigned
Priority: minor | Milestone: 32.0
Component: MythTV - General | Version: Master Head
Severity: medium | Resolution:
Keywords: | Ticket locked: 0
--------------------------------+-------------------------------
Comment (by Klaas de Waal):
The crash can now be reproduced easily by accessing the m_encoderList
repeatedly right after StopRecording in line mainserver.cpp:2920 as shown
in the following code fragment:
{{{
elink->StopRecording();
// Repeated access of m_encoderList after StopRecording causes
crash
for (int i=0; i<100000; i++)
{
int j = 0;
for (auto iter2 = m_encoderList->begin(); iter2 !=
m_encoderList->end(); ++iter2)
{
j++;
EncoderLink *elink2 = *iter2;
if (elink2->IsLocal())
{
(void) iter2.key();
}
}
}
}}}
The backtrace is usually similar to that in the initial post but
incidentally the crash is in the QMap code, as shown here:
{{{
Thread 50 "PT3" received signal SIGSEGV, Segmentation fault.
[Switching to Thread 0x7ffe9f7fe700 (LWP 2029089)]
0x00007ffff20caa43 in QMapNodeBase::nextNode (this=0x8c3df0) at
tools/qmap.cpp:58
58 while (n->left)
(gdb) bt
#0 0x00007ffff20caa43 in QMapNodeBase::nextNode() const (this=0x8c3df0)
at tools/qmap.cpp:58
#1 0x0000000000446a66 in QMapNodeBase::nextNode() (this=0x8c3df0) at
/usr/include/qt5/QtCore/qmap.h:92
#2 0x000000000044b102 in QMapNode<int, EncoderLink*>::nextNode()
(this=0x8c3df0) at /usr/include/qt5/QtCore/qmap.h:120
#3 0x00000000004c6859 in QMap<int, EncoderLink*>::iterator::operator++()
(this=0x7ffe9f7fd0b8) at /usr/include/qt5/QtCore/qmap.h:430
#4 0x00000000004875fa in
MainServer::DoHandleStopRecording(RecordingInfo&, PlaybackSock*)
(this=0x714690, recinfo=..., pbs=0x0) at mainserver.cpp:2926
#5 0x00000000004880c6 in
MainServer::DoHandleDeleteRecording(RecordingInfo&, PlaybackSock*, bool,
bool, bool)
(this=0x714690, recinfo=..., pbs=0x7ffe98005440,
forceMetadataDelete=false, lexpirer=false, forgetHistory=false) at
mainserver.cpp:3038
#6 0x00000000004879f3 in MainServer::HandleDeleteRecording(QString&,
QString&, PlaybackSock*, bool, bool)
(this=0x714690, chanid=..., starttime=..., pbs=0x7ffe98005440,
forceMetadataDelete=false, forgetHistory=false) at mainserver.cpp:2987
#7 0x000000000046fda7 in MainServer::ProcessRequestWork(MythSocket*)
(this=0x714690, sock=0xa7a200) at mainserver.cpp:641
#8 0x000000000046ea30 in MainServer::ProcessRequest(MythSocket*)
(this=0x714690, sock=0xa7a200) at mainserver.cpp:456
#9 0x00000000004c38d6 in ProcessRequestRunnable::run()
(this=0x7ffea400b830) at mainserver.cpp:160
#10 0x00007ffff5412909 in MPoolThread::run() (this=0x7ffe940036a0) at
mthreadpool.cpp:140
#11 0x00007ffff540f284 in MThreadInternal::run() (this=0x70de00) at
mthread.cpp:79
#12 0x00007ffff2067d96 in QThreadPrivate::start(void*) (arg=0x70de00) at
thread/qthread_unix.cpp:360
#13 0x00007ffff35d04e2 in start_thread () at /lib64/libpthread.so.0
#14 0x00007ffff1b836d3 in clone () at /lib64/libc.so.6
(gdb) l
53 const QMapNodeBase *QMapNodeBase::nextNode() const
54 {
55 const QMapNodeBase *n = this;
56 if (n->right) {
57 n = n->right;
58 while (n->left)
59 n = n->left;
60 } else {
61 const QMapNodeBase *y = n->parent();
62 while (y && n == y->right) {
(gdb)
}}}
It can take a few thousand loops across the m_encoderLink before the crash
happens:
{{{
(gdb) fr 4
#4 0x00000000004875fa in MainServer::DoHandleStopRecording
(this=0x714690, recinfo=..., pbs=0x0) at mainserver.cpp:2926
2926 for (auto iter2 = m_encoderList->begin(); iter2 !=
m_encoderList->end(); ++iter2)
(gdb) l
2921
2922 // Repeated access of m_encoderList after
stopRecording causes crash
2923 for (int i=0; i<100000; i++)
2924 {
2925 int j = 0;
2926 for (auto iter2 = m_encoderList->begin(); iter2 !=
m_encoderList->end(); ++iter2)
2927 {
2928 j++;
2929 EncoderLink *elink2 = *iter2;
2930 if (elink2->IsLocal())
(gdb) p i
$13 = 6000
(gdb) p j
$14 = 14
}}}
The crash can also happen when stopping a recording. Deleting is not
essential.
The crash can also happen when creating and deleting recordings via the
Services API with the script vcr.py from Bill Meek but then still a large
number of deletes are needed. With the GUI it takes now only one or two
deletes to produce the crash in the backend.
Having a large m_encoderList, so having a lot of tuners and a lot of
multirec virtual tuners, and making more recordings at the same time
definitely increases the chance of crashing to, on my system, close to
certain.
The critical point is accessing the m_encoderList after the StopRecording
is done which is what the patch is doing repeatedly. Therefore the patch
20200325_stop_one_recording.patch does actually work because then the
m_encoderList is not accessed anymore after the StopRecording.
A patch with the "repeated access" code is attached.
--
Ticket URL: <https://code.mythtv.org/trac/ticket/13571#comment:11>
MythTV <http://www.mythtv.org>
MythTV Media Center
More information about the mythtv-commits
mailing list