[mythtv-commits] Ticket #6305: Incorrect QWaitCondition & mutex usage in multiple places

MythTV mythtv at cvs.mythtv.org
Wed Feb 25 20:07:27 UTC 2009


#6305: Incorrect QWaitCondition & mutex usage in multiple places
---------------------------------------+------------------------------------
 Reporter:  tomimo at ncircle.nullnet.fi  |       Owner:  ijr    
     Type:  defect                     |      Status:  new    
 Priority:  minor                      |   Milestone:  unknown
Component:  MythTV - General           |     Version:  head   
 Severity:  medium                     |     Mlocked:  0      
---------------------------------------+------------------------------------
 I've noticed a quite frequent hang due to frequent status queries:

 Example:

 Thread 12 (Thread 0x49396950 (LWP 11152)):
 #0  0x00007fdd7ee1c2d9 in pthread_cond_wait@@GLIBC_2.3.2 () from
 /lib/libpthread.so.0
 #1  0x00007fdd7d4ebb5b in ?? () from /usr/lib/libQtCore.so.4
 #2  0x00007fdd7d4e73cd in QMutex::lock () from /usr/lib/libQtCore.so.4
 #3  0x0000000000438e31 in QMutexLocker::relock (this=0x49393780) at
 /usr/include/qt4/QtCore/qmutex.h:116
 #4  0x000000000043bdd9 in QMutexLocker (this=0x49393780, m=0xa77af8) at
 /usr/include/qt4/QtCore/qmutex.h:98
 #5  0x00007fdd833642a5 in TVRec::IsBusy (this=0xa77a20, busy_input=0x0,
 time_buffer=5) at tv_rec.cpp:2466
 #6  0x00000000004422a7 in EncoderLink::IsBusy (this=0xa9a530,
 busy_input=0x0, time_buffer=5) at encoderlink.cpp:102
 #7  0x00000000004ff7fa in GetCurrentMaxBitrate (encoderList=0x776cc8) at
 backendutil.cpp:47
 #8  0x00000000005012e8 in BackendQueryDiskSpace (strlist=@0x49394ba0,
 encoderList=0x776cc8, consolidated=true, allHosts=true) at
 backendutil.cpp:193
 #9  0x0000000000453e96 in HttpStatus::FillStatusXML (this=0x7fdd70029170,
 pDoc=0x493952d0) at httpstatus.cpp:337
 #10 0x0000000000456fd3 in HttpStatus::GetStatusHTML (this=0x7fdd70029170,
 pRequest=0x7fdd7052ce10) at httpstatus.cpp:134
 #11 0x0000000000457236 in HttpStatus::ProcessRequest (this=0x7fdd70029170,
 pRequest=0x7fdd7052ce10) at httpstatus.cpp:88
 #12 0x00007fdd81a049be in HttpServer::DelegateRequest
 (this=0x7fdd7001d600, pThread=0x7fdd70009170, pRequest=0x7fdd7052ce10) at
 httpserver.cpp:171
 #13 0x00007fdd81a05196 in HttpWorkerThread::ProcessWork
 (this=0x7fdd70009170) at httpserver.cpp:297
 #14 0x00007fdd81a01879 in WorkerThread::WakeForWork (this=0x7fdd70009170)
 at threadpool.cpp:218
 #15 0x00007fdd81a01c88 in WorkerEvent::customEvent (this=0xa968a0,
 e=0x7fdd68830530) at threadpool.cpp:135
 #16 0x00007fdd7d5e3dfd in QObject::event () from /usr/lib/libQtCore.so.4
 #17 0x00007fdd7dd8fc3d in QApplicationPrivate::notify_helper () from
 /usr/lib/libQtGui.so.4
 #18 0x00007fdd7dd979ba in QApplication::notify () from
 /usr/lib/libQtGui.so.4
 #19 0x00007fdd7d5d4d61 in QCoreApplication::notifyInternal () from
 /usr/lib/libQtCore.so.4
 #20 0x00007fdd7d5d59fa in QCoreApplicationPrivate::sendPostedEvents ()
 from /usr/lib/libQtCore.so.4
 #21 0x00007fdd7d5fd4d3 in ?? () from /usr/lib/libQtCore.so.4
 #22 0x00007fdd79e14d3b in g_main_context_dispatch () from
 /usr/lib/libglib-2.0.so.0
 #23 0x00007fdd79e1850d in ?? () from /usr/lib/libglib-2.0.so.0
 #24 0x00007fdd79e186cb in g_main_context_iteration () from
 /usr/lib/libglib-2.0.so.0
 #25 0x00007fdd7d5fd15f in QEventDispatcherGlib::processEvents () from
 /usr/lib/libQtCore.so.4
 #26 0x00007fdd7d5d3682 in QEventLoop::processEvents () from
 /usr/lib/libQtCore.so.4
 #27 0x00007fdd7d5d380d in QEventLoop::exec () from /usr/lib/libQtCore.so.4
 #28 0x00007fdd7d4e93f8 in QThread::exec () from /usr/lib/libQtCore.so.4
 #29 0x00007fdd81a0146d in WorkerThread::run (this=0x7fdd70009170) at
 threadpool.cpp:265
 #30 0x00007fdd7d4ec362 in ?? () from /usr/lib/libQtCore.so.4
 #31 0x00007fdd7ee183ea in start_thread () from /lib/libpthread.so.0
 #32 0x00007fdd7ca4acbd in clone () from /lib/libc.so.6
 #33 0x0000000000000000 in ?? ()

 It looks there is multiple places where the QWaitCondition.wait/wakeall
 have been implemented incorrectly and therefore the code doesn't work as
 intended.

 Example:

 // Qt4 requires a QMutex as a parameter...
 // not sure if this is the best solution.  Mutex Must be locked before
 wait.
      QMutex mutex;
      mutex.lock();

      while (encoding)
      {
          if (request_pause)
          {
             mainpaused = true;
             pauseWait.wakeAll();
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 No locks around this and no predicative set
 to make sure that the signal is detected in the receiver

             if (IsPaused() && tvrec)
                 tvrec->RecorderPaused();

             unpauseWait.wait(&mutex, 100);
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 Uses a bogus mutex, doesn't have a proper locking around
 the wait-call and no predicative checking in order to detect
 if the wake-call has already been sent before we come to the wait()-call.

             if (cleartimeonpause)
                 gettimeofday(&stm, &tzone);
             continue;
 ------------------------------------------------------------

 I'll attach a patch file which shows how I fixed the problem in
 recorderbase.cpp and .h. Because these pauseWait's and unpauseWait's are
 being used in several places, I'll upload a full patch after I've verified
 that my fix doesn't have anmy additional bugs.

-- 
Ticket URL: <http://svn.mythtv.org/trac/ticket/6305>
MythTV <http://www.mythtv.org/>
MythTV


More information about the mythtv-commits mailing list