Ticket #11306: slave_shutdown_deadlock_for.v0.27.patch

File slave_shutdown_deadlock_for.v0.27.patch, 17.4 KB (added by Tomi Orava <tomi.orava@…>, 11 years ago)

Updated slave backend deadlock patch for the mythtv v0.27

  • mythtv/programs/mythbackend/encoderlink.cpp

    diff --git a/mythtv/programs/mythbackend/encoderlink.cpp b/mythtv/programs/mythbackend/encoderlink.cpp
    index ff8724d..351ae1e 100644
    a b EncoderLink::EncoderLink(int capturecardnum, PlaybackSock *lsock, 
    4141                         QString lhostname)
    4242    : m_capturecardnum(capturecardnum), sock(lsock), hostname(lhostname),
    4343      tv(NULL), local(false), locked(false),
     44      disconnected(false),
    4445      sleepStatus(sStatus_Undefined), chanid(0)
    4546{
    4647    endRecordingTime = MythDate::current().addDays(-2);
    EncoderLink::EncoderLink(int capturecardnum, PlaybackSock *lsock, 
    5051    lastSleepTime   = MythDate::current();
    5152    lastWakeTime    = MythDate::current();
    5253
     54    QMutexLocker locker(&sockLock);
    5355    if (sock)
    5456        sock->IncrRef();
    5557}
    EncoderLink::EncoderLink(int capturecardnum, PlaybackSock *lsock, 
    6062EncoderLink::EncoderLink(int capturecardnum, TVRec *ltv)
    6163    : m_capturecardnum(capturecardnum), sock(NULL),
    6264      tv(ltv), local(true), locked(false),
     65      disconnected(false),
    6366      sleepStatus(sStatus_Undefined), chanid(0)
    6467{
    6568    endRecordingTime = MythDate::current().addDays(-2);
    EncoderLink::~EncoderLink(void) 
    9194 */
    9295void EncoderLink::SetSocket(PlaybackSock *lsock)
    9396{
     97    QMutexLocker locker(&sockLock);
    9498    if (lsock)
    9599    {
    96100        lsock->IncrRef();
    void EncoderLink::SetSocket(PlaybackSock *lsock) 
    100104        else
    101105            SetSleepStatus(sStatus_Awake);
    102106    }
    103     else
    104     {
    105         if (IsFallingAsleep())
    106             SetSleepStatus(sStatus_Asleep);
    107         else
    108             SetSleepStatus(sStatus_Undefined);
    109     }
    110107
    111     if (sock)
    112         sock->DecrRef();
    113108    sock = lsock;
     109    disconnected = false;
     110}
     111
     112void EncoderLink::Disconnect()
     113{
     114  QMutexLocker locker(&sockLock);
     115
     116  disconnected = true;
     117
     118  if (IsFallingAsleep())
     119      SetSleepStatus(sStatus_Asleep);
     120  else
     121      SetSleepStatus(sStatus_Undefined);
     122
     123  if (sock)
     124      sock->DecrRef();
    114125}
    115126
     127
    116128/** \fn EncoderLink::SetSleepStatus(SleepStatus)
    117129 *  \brief Sets the sleep status of a recorder
    118130 */
    void EncoderLink::SetSleepStatus(SleepStatus newStatus) 
    129141 */
    130142bool EncoderLink::IsBusy(TunedInputInfo *busy_input, int time_buffer)
    131143{
     144    if (disconnected)
     145        return false;
     146
    132147    if (local)
    133148        return tv->IsBusy(busy_input, time_buffer);
    134149
     150    QMutexLocker locker(&sockLock);
    135151    if (sock)
    136152        return sock->IsBusy(m_capturecardnum, busy_input, time_buffer);
    137153
    bool EncoderLink::IsBusyRecording(void) 
    150166{
    151167    bool retval = false;
    152168
     169    if (disconnected)
     170        return retval;
     171
    153172    TVState state = GetState();
    154173
    155174    if (state == kState_RecordingOnly || state == kState_WatchingRecording ||
    TVState EncoderLink::GetState(void) 
    175194    if (local)
    176195        retval = tv->GetState();
    177196    else if (sock)
    178         retval = (TVState)sock->GetEncoderState(m_capturecardnum);
     197    {
     198        QMutexLocker locker(&sockLock);
     199        if (sock)
     200            retval = (TVState)sock->GetEncoderState(m_capturecardnum);
     201    }
    179202    else
    180203        LOG(VB_GENERAL, LOG_ERR, QString("Broken for card: %1")
    181204            .arg(m_capturecardnum));
    TVState EncoderLink::GetState(void) 
    187210 *  \brief Returns the flag state of the recorder.
    188211 *  \sa TVRec::GetFlags(void) const, \ref recorder_subsystem
    189212 */
    190 uint EncoderLink::GetFlags(void) const
     213uint EncoderLink::GetFlags(void)
    191214{
    192215    uint retval = 0;
    193216
    uint EncoderLink::GetFlags(void) const 
    197220    if (local)
    198221        retval = tv->GetFlags();
    199222    else if (sock)
    200         retval = sock->GetEncoderState(m_capturecardnum);
     223    {
     224        QMutexLocker locker(&sockLock);
     225        if (sock)
     226            retval = sock->GetEncoderState(m_capturecardnum);
     227    }
    201228    else
    202229        LOG(VB_GENERAL, LOG_ERR, LOC + "GetFlags failed");
    203230
    uint EncoderLink::GetFlags(void) const 
    211238 */
    212239bool EncoderLink::IsRecording(const ProgramInfo *rec)
    213240{
     241    if (!IsConnected())
     242        return false;
     243
    214244    return (rec->GetChanID() == chanid &&
    215245            rec->GetRecordingStartTime() == startRecordingTime);
    216246}
    bool EncoderLink::MatchesRecording(const ProgramInfo *rec) 
    228258    bool retval = false;
    229259    ProgramInfo *tvrec = NULL;
    230260
     261    if (!IsConnected())
     262        return retval;
     263
    231264    if (local)
    232265    {
    233266        while (kState_ChangingState == GetState())
    bool EncoderLink::MatchesRecording(const ProgramInfo *rec) 
    244277    }
    245278    else
    246279    {
     280        QMutexLocker locker(&sockLock);
    247281        if (sock)
    248282            retval = sock->EncoderIsRecording(m_capturecardnum, rec);
    249283    }
    bool EncoderLink::MatchesRecording(const ProgramInfo *rec) 
    262296void EncoderLink::RecordPending(const ProgramInfo *rec, int secsleft,
    263297                                bool hasLater)
    264298{
     299    if (!IsConnected())
     300        return;
     301
    265302    if (local)
    266303        tv->RecordPending(rec, secsleft, hasLater);
    267     else if (sock)
    268         sock->RecordPending(m_capturecardnum, rec, secsleft, hasLater);
     304    else
     305    {
     306        QMutexLocker locker(&sockLock);
     307        if (sock)
     308            sock->RecordPending(m_capturecardnum, rec, secsleft, hasLater);
     309    }
    269310}
    270311
    271312/** \fn EncoderLink::WouldConflict(const ProgramInfo*)
    bool EncoderLink::WouldConflict(const ProgramInfo *rec) 
    278319    if (!IsConnected())
    279320        return true;
    280321
     322    QMutexLocker locker(&sockLock);
    281323    if (rec->GetRecordingStartTime() < endRecordingTime)
    282324        return true;
    283325
    bool EncoderLink::WouldConflict(const ProgramInfo *rec) 
    287329/// Checks if program is stored locally
    288330bool EncoderLink::CheckFile(ProgramInfo *pginfo)
    289331{
     332    if (!IsConnected())
     333        return false;
     334
     335    QMutexLocker locker(&sockLock);
    290336    if (sock)
    291337        return sock->CheckFile(pginfo);
    292338
    bool EncoderLink::CheckFile(ProgramInfo *pginfo) 
    301347 */
    302348void EncoderLink::GetDiskSpace(QStringList &o_strlist)
    303349{
     350    if (!IsConnected())
     351        return;
     352
     353    QMutexLocker locker(&sockLock);
    304354    if (sock)
    305355        sock->GetDiskSpace(o_strlist);
    306356}
    void EncoderLink::GetDiskSpace(QStringList &o_strlist) 
    313363 */
    314364long long EncoderLink::GetMaxBitrate()
    315365{
     366    if (!IsConnected())
     367        return -1;
     368   
    316369    if (local)
    317370        return tv->GetMaxBitrate();
    318     else if (sock)
    319         return sock->GetMaxBitrate(m_capturecardnum);
    320 
     371    else
     372    {
     373        QMutexLocker locker(&sockLock);
     374        if (sock)
     375            return sock->GetMaxBitrate(m_capturecardnum);
     376    }
    321377    return -1;
    322378}
    323379
    int EncoderLink::SetSignalMonitoringRate(int rate, int notifyFrontend) 
    339395{
    340396    if (local)
    341397        return tv->SetSignalMonitoringRate(rate, notifyFrontend);
    342     else if (sock)
    343         return sock->SetSignalMonitoringRate(m_capturecardnum, rate,
    344                                              notifyFrontend);
     398    else
     399    {
     400        QMutexLocker locker(&sockLock);
     401        if (sock)
     402            return sock->SetSignalMonitoringRate(m_capturecardnum, rate,
     403                                                 notifyFrontend);
     404    }
    345405    return -1;
    346406}
    347407
    int EncoderLink::SetSignalMonitoringRate(int rate, int notifyFrontend) 
    349409 */
    350410bool EncoderLink::GoToSleep(void)
    351411{
    352     if (IsLocal() || !sock)
     412    if (!IsConnected())
     413        return false;
     414 
     415    if (IsLocal())
     416        return false;
     417
     418    QMutexLocker locker(&sockLock);
     419    if (!sock)
    353420        return false;
    354421
    355422    lastSleepTime = MythDate::current();
    bool EncoderLink::GoToSleep(void) 
    363430 */
    364431int EncoderLink::LockTuner()
    365432{
     433    if (!IsConnected())
     434        return -2;
     435
    366436    if (locked)
    367437        return -2;
    368438
    RecStatusType EncoderLink::StartRecording(const ProgramInfo *rec) 
    381451{
    382452    RecStatusType retval = rsAborted;
    383453
     454    if (!IsConnected())
     455        return retval;
     456
    384457    endRecordingTime = rec->GetRecordingEndTime();
    385458    startRecordingTime = rec->GetRecordingStartTime();
    386459    chanid = rec->GetChanID();
    387460
    388461    if (local)
    389462        retval = tv->StartRecording(rec);
    390     else if (sock)
    391         retval = sock->StartRecording(m_capturecardnum, rec);
    392463    else
    393         LOG(VB_GENERAL, LOG_ERR,
    394             QString("Wanted to start recording on recorder %1,\n\t\t\t"
    395                     "but the backend is not there anymore\n")
    396                 .arg(m_capturecardnum));
     464    {
     465        QMutexLocker locker(&sockLock);
     466        if (sock)
     467            retval = sock->StartRecording(m_capturecardnum, rec);
     468        else
     469            LOG(VB_GENERAL, LOG_ERR,
     470                QString("Wanted to start recording on recorder %1,\n\t\t\t"
     471                        "but the backend is not there anymore\n")
     472                    .arg(m_capturecardnum));
     473    }
    397474
    398475    if (retval != rsRecording && retval != rsTuning)
    399476    {
    RecStatusType EncoderLink::GetRecordingStatus(void) 
    409486{
    410487    RecStatusType retval = rsAborted;
    411488
     489    if (!IsConnected())
     490        return retval;
     491
    412492    if (local)
    413493        retval = tv->GetRecordingStatus();
    414     else if (sock)
    415         retval = sock->GetRecordingStatus(m_capturecardnum);
    416494    else
    417         LOG(VB_GENERAL, LOG_ERR,
    418             QString("Wanted to get status on recorder %1,\n\t\t\t"
    419                     "but the backend is not there anymore\n")
    420                 .arg(m_capturecardnum));
     495    {
     496        QMutexLocker locker(&sockLock);
     497        if (sock)
     498            retval = sock->GetRecordingStatus(m_capturecardnum);
     499        else
     500            LOG(VB_GENERAL, LOG_ERR,
     501                QString("Wanted to get status on recorder %1,\n\t\t\t"
     502                        "but the backend is not there anymore\n")
     503                    .arg(m_capturecardnum));
     504    }
    421505
    422506    if (retval != rsRecording && retval != rsTuning)
    423507    {
    ProgramInfo *EncoderLink::GetRecording(void) 
    439523{
    440524    ProgramInfo *info = NULL;
    441525
     526    if (!IsConnected())
     527        return info;
     528
    442529    if (local)
    443530        info = tv->GetRecording();
    444     else if (sock)
    445         info = sock->GetRecording(m_capturecardnum);
     531    else
     532    {
     533        QMutexLocker locker(&sockLock);
     534        if (sock)
     535            info = sock->GetRecording(m_capturecardnum);
    446536
     537    }
    447538    return info;
    448539}
    449540
    ProgramInfo *EncoderLink::GetRecording(void) 
    454545 */
    455546void EncoderLink::StopRecording(bool killFile)
    456547{
     548    if (!IsConnected())
     549        return;
     550
    457551    endRecordingTime = MythDate::current().addDays(-2);
    458552    startRecordingTime = endRecordingTime;
    459553    chanid = 0;
    void EncoderLink::FinishRecording(void) 
    490584 */
    491585bool EncoderLink::IsReallyRecording(void)
    492586{
     587    if (!IsConnected())
     588        return false;
     589
    493590    if (local)
    494591        return tv->IsReallyRecording();
    495592
    bool EncoderLink::IsReallyRecording(void) 
    506603 */
    507604float EncoderLink::GetFramerate(void)
    508605{
     606    if (!IsConnected())
     607        return -1;
     608
    509609    if (local)
    510610        return tv->GetFramerate();
    511611
    void EncoderLink::CancelNextRecording(bool cancel) 
    611711    if (local)
    612712        tv->CancelNextRecording(cancel);
    613713    else
    614         sock->CancelNextRecording(m_capturecardnum, cancel);
     714    {
     715        if (!IsConnected())
     716            return;
     717
     718        QMutexLocker locker(&sockLock);
     719        if (sock)
     720            sock->CancelNextRecording(m_capturecardnum, cancel);
     721    }
    615722}
    616723
    617724/** \fn EncoderLink::SpawnLiveTV(LiveTVChain*, bool, QString)
    void EncoderLink::SetNextLiveTVDir(QString dir) 
    694801    if (local)
    695802        tv->SetNextLiveTVDir(dir);
    696803    else
    697         sock->SetNextLiveTVDir(m_capturecardnum, dir);
     804    {
     805        if (!IsConnected())
     806            return;
     807
     808        QMutexLocker locker(&sockLock);
     809        if (sock)
     810            sock->SetNextLiveTVDir(m_capturecardnum, dir);
     811    }
    698812}
    699813
    700814/** \fn EncoderLink::GetFreeInputs(const vector<uint>&) const
    void EncoderLink::SetNextLiveTVDir(QString dir) 
    703817 *  \sa TVRec::GetFreeInputs(const vector<uint>&) const
    704818 */
    705819vector<InputInfo> EncoderLink::GetFreeInputs(
    706     const vector<uint> &excluded_cardids) const
     820    const vector<uint> &excluded_cardids)
    707821{
    708822    vector<InputInfo> list;
    709823
    710824    if (local)
    711825        list = tv->GetFreeInputs(excluded_cardids);
    712826    else
     827    {
     828        if (!IsConnected())
     829            return list;
     830
     831        QMutexLocker locker(&sockLock);
    713832        list = sock->GetFreeInputs(m_capturecardnum, excluded_cardids);
    714833
     834    }
    715835    return list;
    716836}
    717837
  • mythtv/programs/mythbackend/encoderlink.h

    diff --git a/mythtv/programs/mythbackend/encoderlink.h b/mythtv/programs/mythbackend/encoderlink.h
    index 35707c0..3ff0da6 100644
    a b  
    33
    44#include <QString>
    55#include <QMap>
     6#include <QMutex>
     7
    68
    79#include "tv.h"
    810#include "programinfo.h"
    class EncoderLink 
    2325
    2426    /// \brief Used to set the socket for a non-local EncoderLink.
    2527    void SetSocket(PlaybackSock *lsock);
     28
     29    /// \brief Used to unset the socket for a non-local EncoderLink.
     30    void Disconnect();
    2631    /// \brief Returns the socket, if set, for a non-local EncoderLink.
    2732    PlaybackSock *GetSocket(void) { return sock; }
    2833
    class EncoderLink 
    4247    /// \brief Returns true for a local EncoderLink.
    4348    bool IsLocal(void) const { return local; }
    4449    /// \brief Returns true if the EncoderLink instance is usable.
    45     bool IsConnected(void) const { return (IsLocal() || sock!=NULL); }
     50    bool IsConnected(void) { bool value;
     51                             if (disconnected)
     52                                 return false;
     53                             value = IsLocal();
     54                             if (value)
     55                                 return value;
     56                             if (sock)
     57                                 return true;
     58                             return false;
     59                           }
    4660    /// \brief Returns true if the encoder is awake.
    4761    bool IsAwake(void) const { return (sleepStatus == sStatus_Awake); }
    4862    /// \brief Returns true if the encoder is asleep.
    class EncoderLink 
    8296    bool IsBusyRecording(void);
    8397
    8498    TVState GetState();
    85     uint GetFlags(void) const;
     99    uint GetFlags(void);
    86100    bool IsRecording(const ProgramInfo *rec); // scheduler call only.
    87101
    88102    bool MatchesRecording(const ProgramInfo *rec);
    class EncoderLink 
    109123    void PauseRecorder(void);
    110124    void SetLiveRecording(int);
    111125    void SetNextLiveTVDir(QString dir);
    112     vector<InputInfo> GetFreeInputs(const vector<uint> &excluded_cards) const;
     126    vector<InputInfo> GetFreeInputs(const vector<uint> &excluded_cards);
    113127    QString GetInput(void) const;
    114128    QString SetInput(QString);
    115129    void ToggleChannelFavorite(QString);
    class EncoderLink 
    139153  private:
    140154    int m_capturecardnum;
    141155
     156    QMutex sockLock;
     157
    142158    PlaybackSock *sock;
    143159    QString hostname;
    144160
    class EncoderLink 
    146162
    147163    bool local;
    148164    bool locked;
     165    bool disconnected;
    149166
    150167    SleepStatus sleepStatus;
    151168    QDateTime sleepStatusTime;
  • mythtv/programs/mythbackend/mainserver.cpp

    diff --git a/mythtv/programs/mythbackend/mainserver.cpp b/mythtv/programs/mythbackend/mainserver.cpp
    index 11332e3..1195a94 100644
    a b void MainServer::connectionClosed(MythSocket *socket) 
    58245824                        if (!elink->IsFallingAsleep())
    58255825                            isFallingAsleep = false;
    58265826
    5827                         elink->SetSocket(NULL);
     5827                        elink->Disconnect();
    58285828                        if (m_sched)
    58295829                            disconnectedSlaves.push_back(elink->GetCardID());
    58305830                    }
  • mythtv/programs/mythbackend/playbacksock.cpp

    diff --git a/mythtv/programs/mythbackend/playbacksock.cpp b/mythtv/programs/mythbackend/playbacksock.cpp
    index 549a89c..e7bf6c2 100644
    a b using namespace std; 
    1717PlaybackSock::PlaybackSock(
    1818    MainServer *parent, MythSocket *lsock,
    1919    QString lhostname, PlaybackSockEventsMode eventsMode) :
    20     ReferenceCounter("PlaybackSock")
     20    ReferenceCounter("PlaybackSock"),
     21    sockLock(QMutex::Recursive)
    2122{
    2223    m_parent = parent;
    2324    QString localhostname = gCoreContext->GetHostName();
    bool PlaybackSock::SendReceiveStringList( 
    7778{
    7879    bool ok = false;
    7980
     81    QMutexLocker locker(&sockLock);
     82    if (!sock)
     83        return false;
     84
    8085    sock->IncrRef();
    8186
    8287    {
    83         QMutexLocker locker(&sockLock);
    8488        expectingreply = true;
    8589
    8690        ok = sock->SendReceiveStringList(strlist);
    bool PlaybackSock::IsBusy(int capturecardnum, InputInfo *busy_input, 
    318322{
    319323    QStringList strlist(QString("QUERY_REMOTEENCODER %1").arg(capturecardnum));
    320324
     325    QMutexLocker locker(&sockLock);
     326    if (disconnected)
     327        return true;
     328
    321329    strlist << "IS_BUSY";
    322330    strlist << QString::number(time_buffer);
    323331
  • mythtv/programs/mythbackend/playbacksock.h

    diff --git a/mythtv/programs/mythbackend/playbacksock.h b/mythtv/programs/mythbackend/playbacksock.h
    index c273604..a74d43b 100644
    a b class PlaybackSock : public ReferenceCounter 
    3131                 QString lhostname, PlaybackSockEventsMode eventsMode);
    3232    virtual ~PlaybackSock();
    3333
    34     void SetDisconnected(void) { disconnected = true; }
     34    void SetDisconnected(void) { QMutexLocker locker(&sockLock); disconnected = true; }
    3535    bool IsDisconnected(void) const { return disconnected; }
    3636
    3737    MythSocket *getSocket(void) const { return sock; }