Ticket #11306: protect_pbs_with_proper_refcounting.patch

File protect_pbs_with_proper_refcounting.patch, 9.5 KB (added by Cédric Schieli <cschieli@…>, 10 years ago)

Protect pbs with proper refcounting

  • mythtv/programs/mythbackend/encoderlink.cpp

    Protect pbs with proper (aka locked) refcounting.
     
    The PlaybackSock must not be immediatly deleted on connectionClosed()
    if some other requests are still using it. This leads to segfaults in
    the MBE when the SBE disconnects (#11306).
    
    diff --git a/mythtv/programs/mythbackend/encoderlink.cpp b/mythtv/programs/mythbackend/encoderlink.cpp
    index ff8724d..feef450 100644
    a b using namespace std; 
    1515#include "storagegroup.h"
    1616#include "backendutil.h"
    1717#include "compat.h"
     18#include "referencecounter.h"
    1819
    1920#define LOC QString("EncoderLink(%1): ").arg(m_capturecardnum)
    2021#define LOC_ERR QString("EncoderLink(%1) Error: ").arg(m_capturecardnum)
    EncoderLink::EncoderLink(int capturecardnum, PlaybackSock *lsock, 
    5051    lastSleepTime   = MythDate::current();
    5152    lastWakeTime    = MythDate::current();
    5253
    53     if (sock)
    54         sock->IncrRef();
     54    HasSockAndIncrRef();
    5555}
    5656
    5757/** \fn EncoderLink::EncoderLink(int, TVRec *)
    EncoderLink::~EncoderLink(void) 
    8484    SetSocket(NULL);
    8585}
    8686
     87/** \fn Encoder::HasSockAndIncrRef()
     88 *  \brief Atomicly checks if sock is not null and increases its refcount.
     89 */
     90bool EncoderLink::HasSockAndIncrRef()
     91{
     92    QMutexLocker locker(&sockLock);
     93    if (sock)
     94    {
     95        sock->IncrRef();
     96        return true;
     97    }
     98    return false;
     99}
     100
     101/** \fn Encoder::HasSockAndDecrRef()
     102 *  \brief Atomicly checks if sock is not null and decreases its refcount.
     103 */
     104bool EncoderLink::HasSockAndDecrRef()
     105{
     106    QMutexLocker locker(&sockLock);
     107    if (sock)
     108    {
     109        sock->DecrRef();
     110        return true;
     111    }
     112    return false;
     113}
     114
    87115/** \fn EncoderLink::SetSocket(PlaybackSock *lsock)
    88116 *  \brief Used to set the socket for a non-local EncoderLink
    89117 *
    void EncoderLink::SetSocket(PlaybackSock *lsock) 
    108136            SetSleepStatus(sStatus_Undefined);
    109137    }
    110138
    111     if (sock)
    112         sock->DecrRef();
     139    HasSockAndDecrRef();
    113140    sock = lsock;
    114141}
    115142
    bool EncoderLink::IsBusy(TunedInputInfo *busy_input, int time_buffer) 
    132159    if (local)
    133160        return tv->IsBusy(busy_input, time_buffer);
    134161
    135     if (sock)
     162    if (HasSockAndIncrRef())
     163    {
     164        ReferenceLocker rlocker(sock);
    136165        return sock->IsBusy(m_capturecardnum, busy_input, time_buffer);
     166    }
    137167
    138168    return false;
    139169}
    TVState EncoderLink::GetState(void) 
    174204
    175205    if (local)
    176206        retval = tv->GetState();
    177     else if (sock)
     207    else if (HasSockAndIncrRef())
     208    {
     209        ReferenceLocker rlocker(sock);
    178210        retval = (TVState)sock->GetEncoderState(m_capturecardnum);
     211    }
    179212    else
    180213        LOG(VB_GENERAL, LOG_ERR, QString("Broken for card: %1")
    181214            .arg(m_capturecardnum));
    TVState EncoderLink::GetState(void) 
    187220 *  \brief Returns the flag state of the recorder.
    188221 *  \sa TVRec::GetFlags(void) const, \ref recorder_subsystem
    189222 */
    190 uint EncoderLink::GetFlags(void) const
     223uint EncoderLink::GetFlags(void)
    191224{
    192225    uint retval = 0;
    193226
    uint EncoderLink::GetFlags(void) const 
    196229
    197230    if (local)
    198231        retval = tv->GetFlags();
    199     else if (sock)
     232    else if (HasSockAndIncrRef())
     233    {
     234        ReferenceLocker rlocker(sock);
    200235        retval = sock->GetEncoderState(m_capturecardnum);
     236    }
    201237    else
    202238        LOG(VB_GENERAL, LOG_ERR, LOC + "GetFlags failed");
    203239
    bool EncoderLink::MatchesRecording(const ProgramInfo *rec) 
    244280    }
    245281    else
    246282    {
    247         if (sock)
     283        if (HasSockAndIncrRef())
     284        {
     285            ReferenceLocker rlocker(sock);
    248286            retval = sock->EncoderIsRecording(m_capturecardnum, rec);
     287        }
    249288    }
    250289
    251290    return retval;
    void EncoderLink::RecordPending(const ProgramInfo *rec, int secsleft, 
    264303{
    265304    if (local)
    266305        tv->RecordPending(rec, secsleft, hasLater);
    267     else if (sock)
     306    else if (HasSockAndIncrRef())
     307    {
     308        ReferenceLocker rlocker(sock);
    268309        sock->RecordPending(m_capturecardnum, rec, secsleft, hasLater);
     310    }
    269311}
    270312
    271313/** \fn EncoderLink::WouldConflict(const ProgramInfo*)
    bool EncoderLink::WouldConflict(const ProgramInfo *rec) 
    287329/// Checks if program is stored locally
    288330bool EncoderLink::CheckFile(ProgramInfo *pginfo)
    289331{
    290     if (sock)
     332    if (HasSockAndIncrRef())
     333    {
     334        ReferenceLocker rlocker(sock);
    291335        return sock->CheckFile(pginfo);
     336    }
    292337
    293338    pginfo->SetPathname(GetPlaybackURL(pginfo));
    294339    return pginfo->IsLocal();
    bool EncoderLink::CheckFile(ProgramInfo *pginfo) 
    301346 */
    302347void EncoderLink::GetDiskSpace(QStringList &o_strlist)
    303348{
    304     if (sock)
     349    if (HasSockAndIncrRef())
     350    {
     351        ReferenceLocker rlocker(sock);
    305352        sock->GetDiskSpace(o_strlist);
     353    }
    306354}
    307355
    308356/** \fn EncoderLink::GetMaxBitrate()
    long long EncoderLink::GetMaxBitrate() 
    315363{
    316364    if (local)
    317365        return tv->GetMaxBitrate();
    318     else if (sock)
     366    else if (HasSockAndIncrRef())
     367    {
     368        ReferenceLocker rlocker(sock);
    319369        return sock->GetMaxBitrate(m_capturecardnum);
     370    }
    320371
    321372    return -1;
    322373}
    int EncoderLink::SetSignalMonitoringRate(int rate, int notifyFrontend) 
    339390{
    340391    if (local)
    341392        return tv->SetSignalMonitoringRate(rate, notifyFrontend);
    342     else if (sock)
     393    else if (HasSockAndIncrRef())
     394    {
     395        ReferenceLocker rlocker(sock);
    343396        return sock->SetSignalMonitoringRate(m_capturecardnum, rate,
    344397                                             notifyFrontend);
     398    }
    345399    return -1;
    346400}
    347401
    int EncoderLink::SetSignalMonitoringRate(int rate, int notifyFrontend) 
    349403 */
    350404bool EncoderLink::GoToSleep(void)
    351405{
    352     if (IsLocal() || !sock)
     406    if (IsLocal() || !HasSockAndIncrRef())
    353407        return false;
     408    ReferenceLocker rlocker(sock);
    354409
    355410    lastSleepTime = MythDate::current();
    356411
    RecStatusType EncoderLink::StartRecording(const ProgramInfo *rec) 
    387442
    388443    if (local)
    389444        retval = tv->StartRecording(rec);
    390     else if (sock)
     445    else if (HasSockAndIncrRef())
     446    {
     447        ReferenceLocker rlocker(sock);
    391448        retval = sock->StartRecording(m_capturecardnum, rec);
     449    }
    392450    else
    393451        LOG(VB_GENERAL, LOG_ERR,
    394452            QString("Wanted to start recording on recorder %1,\n\t\t\t"
    RecStatusType EncoderLink::GetRecordingStatus(void) 
    411469
    412470    if (local)
    413471        retval = tv->GetRecordingStatus();
    414     else if (sock)
     472    else if (HasSockAndIncrRef())
     473    {
     474        ReferenceLocker rlocker(sock);
    415475        retval = sock->GetRecordingStatus(m_capturecardnum);
     476    }
    416477    else
    417478        LOG(VB_GENERAL, LOG_ERR,
    418479            QString("Wanted to get status on recorder %1,\n\t\t\t"
    ProgramInfo *EncoderLink::GetRecording(void) 
    441502
    442503    if (local)
    443504        info = tv->GetRecording();
    444     else if (sock)
     505    else if (HasSockAndIncrRef())
     506    {
     507        ReferenceLocker rlocker(sock);
    445508        info = sock->GetRecording(m_capturecardnum);
     509    }
    446510
    447511    return info;
    448512}
    void EncoderLink::CancelNextRecording(bool cancel) 
    610674{
    611675    if (local)
    612676        tv->CancelNextRecording(cancel);
    613     else
     677    else if (HasSockAndIncrRef())
     678    {
     679        ReferenceLocker rlocker(sock);
    614680        sock->CancelNextRecording(m_capturecardnum, cancel);
     681    }
    615682}
    616683
    617684/** \fn EncoderLink::SpawnLiveTV(LiveTVChain*, bool, QString)
    void EncoderLink::SetNextLiveTVDir(QString dir) 
    693760{
    694761    if (local)
    695762        tv->SetNextLiveTVDir(dir);
    696     else
     763    else if (HasSockAndIncrRef())
     764    {
     765        ReferenceLocker rlocker(sock);
    697766        sock->SetNextLiveTVDir(m_capturecardnum, dir);
     767    }
    698768}
    699769
    700770/** \fn EncoderLink::GetFreeInputs(const vector<uint>&) const
    void EncoderLink::SetNextLiveTVDir(QString dir) 
    703773 *  \sa TVRec::GetFreeInputs(const vector<uint>&) const
    704774 */
    705775vector<InputInfo> EncoderLink::GetFreeInputs(
    706     const vector<uint> &excluded_cardids) const
     776    const vector<uint> &excluded_cardids)
    707777{
    708778    vector<InputInfo> list;
    709779
    710780    if (local)
    711781        list = tv->GetFreeInputs(excluded_cardids);
    712     else
     782    else if (HasSockAndIncrRef())
     783    {
     784        ReferenceLocker rlocker(sock);
    713785        list = sock->GetFreeInputs(m_capturecardnum, excluded_cardids);
     786    }
    714787
    715788    return list;
    716789}
  • mythtv/programs/mythbackend/encoderlink.h

    diff --git a/mythtv/programs/mythbackend/encoderlink.h b/mythtv/programs/mythbackend/encoderlink.h
    index 35707c0..77a3e76 100644
    a b  
    33
    44#include <QString>
    55#include <QMap>
     6#include <QMutex>
    67
    78#include "tv.h"
    89#include "programinfo.h"
    class EncoderLink 
    8283    bool IsBusyRecording(void);
    8384
    8485    TVState GetState();
    85     uint GetFlags(void) const;
     86    uint GetFlags(void);
    8687    bool IsRecording(const ProgramInfo *rec); // scheduler call only.
    8788
    8889    bool MatchesRecording(const ProgramInfo *rec);
    class EncoderLink 
    109110    void PauseRecorder(void);
    110111    void SetLiveRecording(int);
    111112    void SetNextLiveTVDir(QString dir);
    112     vector<InputInfo> GetFreeInputs(const vector<uint> &excluded_cards) const;
     113    vector<InputInfo> GetFreeInputs(const vector<uint> &excluded_cards);
    113114    QString GetInput(void) const;
    114115    QString SetInput(QString);
    115116    void ToggleChannelFavorite(QString);
    class EncoderLink 
    137138                        QString channame, QString xmltv);
    138139
    139140  private:
     141    bool HasSockAndIncrRef();
     142    bool HasSockAndDecrRef();
     143
    140144    int m_capturecardnum;
    141145
    142146    PlaybackSock *sock;
     147    QMutex sockLock;
    143148    QString hostname;
    144149
    145150    TVRec *tv;