Ticket #6363: tv_rec.patch

File tv_rec.patch, 7.7 KB (added by tomimo@…, 11 years ago)

This patch seems to fix the deadlocks for me.

  • libs/libmythtv/tv_rec.cpp

    TVRec::TVRec(int capturecardnum) 
    125125      internalState(kState_None), desiredNextState(kState_None),
    126126      changeState(false), pauseNotify(true),
    127127      stateFlags(0), lastTuningRequest(0),
     128      triggerEventLoopSignal(false),
     129      triggerEventSleepSignal(false),
    128130      m_switchingBuffer(false),
    129131      // Current recording info
    130132      curRecording(NULL), autoRunJobs(JOB_NONE),
    void TVRec::TeardownAll(void) 
    309311    SetRingBuffer(NULL);
    310312}
    311313
     314/** \fn TVRec::wakeEventLoop(void)
     315 *  \brief Trigger the EventLoopThread.
     316 *
     317 *
     318 */
     319void TVRec::wakeEventLoop(void)
     320{
     321    triggerEventLoopMutex.lock();
     322    triggerEventLoopSignal = true;
     323    triggerEventLoop.wakeAll();
     324    triggerEventLoopMutex.unlock();
     325}
     326
    312327/** \fn TVRec::GetState() const
    313328 *  \brief Returns the TVState of the recorder.
    314329 *
    QDateTime TVRec::GetRecordEndTime(const ProgramInf 
    437452 */
    438453void TVRec::CancelNextRecording(bool cancel)
    439454{
     455    QMutexLocker lock(&stateChangeLock);
     456
    440457    VERBOSE(VB_RECORD, LOC + "CancelNextRecording("<<cancel<<") -- begin");
    441458
    442459    PendingMap::iterator it = pendingRecordings.find(cardid);
    void TVRec::ChangeState(TVState nextState) 
    951968
    952969    desiredNextState = nextState;
    953970    changeState = true;
    954     triggerEventLoop.wakeAll();
     971    lock.unlock();
     972    wakeEventLoop();
    955973}
    956974
    957975/** \fn TVRec::SetupRecorder(RecordingProfile&)
    void TVRec::RunTV(void) 
    13711389    else
    13721390        eitScanStartTime = eitScanStartTime.addYears(1);
    13731391
    1374     // Qt4 requires a QMutex as a parameter...
    1375     // not sure if this is the best solution.  Mutex Must be locked before wait.
    1376     QMutex mutex;
    1377     mutex.lock();
    1378 
    13791392    while (HasFlags(kFlagRunMainLoop))
    13801393    {
    13811394        // If there is a state change queued up, do it...
    void TVRec::RunTV(void) 
    15261539        // WaitforEventThreadSleep() will still work...
    15271540        if (tuningRequests.empty() && !changeState)
    15281541        {
     1542            lock.mutex()->unlock();
     1543
     1544            triggerEventSleepMutex.lock();
     1545            triggerEventSleepSignal = true;
    15291546            triggerEventSleep.wakeAll();
    1530             lock.mutex()->unlock();
     1547            triggerEventSleepMutex.unlock();
     1548
    15311549            sched_yield();
    1532             triggerEventSleep.wakeAll();
    1533             triggerEventLoop.wait(&mutex, 1000 /* ms */);
     1550
     1551            triggerEventLoopMutex.lock();
     1552            if (triggerEventLoopSignal == false)
     1553                triggerEventLoop.wait(&triggerEventLoopMutex, 1000 /* ms */);
     1554            triggerEventLoopSignal = false;
     1555            triggerEventLoopMutex.unlock();
     1556
    15341557            lock.mutex()->lock();
    15351558        }
    15361559    }
    void TVRec::RunTV(void) 
    15421565    }
    15431566}
    15441567
     1568/** \fn TVRec::WaitForEventThreadSleep(bool wake, ulong time)
     1569 *
     1570 *  You MUST HAVE the stateChange-lock locked when you call this method!
     1571 */
     1572
    15451573bool TVRec::WaitForEventThreadSleep(bool wake, ulong time)
    15461574{
    1547     // Qt4 requires a QMutex as a parameter...
    1548     // not sure if this is the best solution.  Mutex Must be locked before wait.
    1549     QMutex mutex;
    1550     mutex.lock();
    1551 
    15521575    bool ok = false;
    15531576    MythTimer t;
    15541577    t.start();
    15551578
    15561579    while (!ok && ((unsigned long) t.elapsed()) < time)
    15571580    {
     1581        stateChangeLock.unlock();
    15581582        if (wake)
    1559             triggerEventLoop.wakeAll();
     1583            wakeEventLoop();
    15601584
    1561         stateChangeLock.unlock();
    1562         // It is possible for triggerEventSleep.wakeAll() to be sent
    1563         // before we enter wait so we only wait 100 ms so we can try
    1564         // again a few times before 15 second timeout on frontend...
    1565         triggerEventSleep.wait(&mutex, 100);
     1585        VERBOSE(VB_IMPORTANT, QString("changeState=%1, tuningRequests=%2, time=%3")
     1586                .arg(changeState).arg(tuningRequests.size()).arg((unsigned long) t.elapsed() < time));
     1587
     1588
     1589        triggerEventSleepMutex.lock();
     1590        if (triggerEventSleepSignal == false)
     1591            triggerEventSleep.wait(&triggerEventSleepMutex);
     1592        triggerEventSleepSignal = false;
     1593        triggerEventSleepMutex.unlock();
     1594
    15661595        stateChangeLock.lock();
    15671596
    15681597        // verify that we were triggered.
    bool TVRec::CheckChannelPrefix(const QString &pref 
    24402469bool TVRec::SetVideoFiltersForChannel(uint  sourceid,
    24412470                                      const QString &channum)
    24422471{
     2472    QMutexLocker lock(&stateChangeLock);
    24432473    if (!recorder)
    24442474        return false;
    24452475
    bool TVRec::SetVideoFiltersForChannel(uint source 
    24592489 */
    24602490bool TVRec::IsReallyRecording(void)
    24612491{
     2492    QMutexLocker lock(&stateChangeLock);
    24622493    return ((recorder && recorder->IsRecording()) ||
    24632494            HasFlags(kFlagDummyRecorderRunning));
    24642495}
    static uint get_input_id(uint cardid, const QStrin 
    27382769 */
    27392770void TVRec::NotifySchedulerOfRecording(ProgramInfo *rec)
    27402771{
     2772    QMutexLocker locker(&stateChangeLock);
     2773
    27412774    if (!channel)
    27422775        return;
    27432776
    void TVRec::RecorderPaused(void) 
    29102943{
    29112944    if (pauseNotify)
    29122945    {
    2913         QMutexLocker lock(&stateChangeLock);
    2914         triggerEventLoop.wakeAll();
     2946        wakeEventLoop();
    29152947    }
    29162948}
    29172949
    bool TVRec::TuningOnSameMultiplex(TuningRequest &r 
    34633495    return false;
    34643496}
    34653497
    3466 /** \fn TVRec::HandleTuning(void)
     3498/** \fn TVRecHleTuning(void)
    34673499 *  \brief Handles all tuning events.
    34683500 *
    34693501 *   This method pops tuning events off the tuningState queue
    void TVRec::SetFlags(uint f) 
    42164248    stateFlags |= f;
    42174249    VERBOSE(VB_RECORD, LOC + QString("SetFlags(%1) -> %2")
    42184250            .arg(FlagToString(f)).arg(FlagToString(stateFlags)));
    4219     triggerEventLoop.wakeAll();
     4251    lock.unlock();
     4252    wakeEventLoop();
    42204253}
    42214254
    42224255void TVRec::ClearFlags(uint f)
    void TVRec::ClearFlags(uint f) 
    42254258    stateFlags &= ~f;
    42264259    VERBOSE(VB_RECORD, LOC + QString("ClearFlags(%1) -> %2")
    42274260            .arg(FlagToString(f)).arg(FlagToString(stateFlags)));
    4228     triggerEventLoop.wakeAll();
     4261    lock.unlock();
     4262    wakeEventLoop();
    42294263}
    42304264
    42314265QString TVRec::FlagToString(uint f)
  • libs/libmythtv/tv_rec.h

    class MPUBLIC TVRec : public SignalMonitorListener 
    251251
    252252    static TVRec *GetTVRec(uint cardid);
    253253
    254     virtual void AllGood(void) { triggerEventLoop.wakeAll(); }
     254    virtual void AllGood(void) { wakeEventLoop(); }
    255255    virtual void StatusSignalLock(const SignalMonitorValue&) { }
    256256    virtual void StatusSignalStrength(const SignalMonitorValue&) { }
    257257
    258258  protected:
    259259    void RunTV(void);
     260
    260261    bool WaitForEventThreadSleep(bool wake = true, ulong time = ULONG_MAX);
    261262    static void *EventThread(void *param);
    262263    static void *RecorderThread(void *param);
    class MPUBLIC TVRec : public SignalMonitorListener 
    265266    void SetRingBuffer(RingBuffer *);
    266267    void SetPseudoLiveTVRecording(ProgramInfo*);
    267268    void TeardownAll(void);
     269    void wakeEventLoop(void);
    268270
    269271    static bool GetDevices(int cardid,
    270272                           GeneralDBOptions   &general_opts,
    class MPUBLIC TVRec : public SignalMonitorListener 
    378380    TuningQueue    tuningRequests;
    379381    TuningRequest  lastTuningRequest;
    380382    QDateTime      eitScanStartTime;
     383
    381384    QWaitCondition triggerEventLoop;
     385    QMutex         triggerEventLoopMutex;
     386    bool           triggerEventLoopSignal;
     387
    382388    QWaitCondition triggerEventSleep;
     389    QMutex         triggerEventSleepMutex;
     390    bool           triggerEventSleepSignal;
     391
    383392    bool           m_switchingBuffer;
    384393
    385394    // Current recording info