Ticket #7691: 7691-mythobservable-fix-v1.patch

File 7691-mythobservable-fix-v1.patch, 11.1 KB (added by danielk, 10 years ago)

fix for a segfault

  • libs/libmyth/mythcontext.h

     
    197197    MythPrivRequest popPrivRequest();
    198198
    199199    void dispatch(const MythEvent &event);
    200     void dispatchNow(const MythEvent &event);
     200    void dispatchNow(const MythEvent &event) MDEPRECATED;
    201201
    202202    void sendPlaybackStart(void);
    203203    void sendPlaybackEnd(void);
  • libs/libmyth/output.cpp

     
    2525}
    2626
    2727
    28 void OutputListeners::error(const QString &e) {
    29     QObject *object = firstListener();
    30     while (object)
    31     {
    32         QCoreApplication::postEvent(object, new OutputEvent(e));
    33         object = nextListener();
    34     }
     28void OutputListeners::error(const QString &e)
     29{
     30    dispatch(OutputEvent(e));
    3531}
    3632
    3733void OutputListeners::addVisual(MythTV::Visual *v)
  • libs/libmythdb/mythexp.h

     
    44#if (__GNUC__ >= 4)
    55#define MHIDDEN __attribute__((visibility("hidden")))
    66#define MPUBLIC __attribute__((visibility("default")))
     7#define MUNUSED __attribute__((unused))
     8#define MDEPRECATED __attribute__((deprecated))
    79#else
    810#define MHIDDEN
    911#define MPUBLIC
     12#define MUNUSED
     13#define MDEPRECATED
    1014#endif
    1115
     16
    1217#endif // MYTHEXP_H_
  • libs/libmythdb/mythobservable.cpp

     
    11#include <QCoreApplication>
    22#include <QObject>
     3#include <QMutex>
    34
    45#include "mythobservable.h"
    56
    6 MythObservable::MythObservable()
     7/** \class MythObservable
     8 *  \brief Superclass for making an object have a set of listeners
     9 *
     10 *  This superclass provides the basic API for adding and removing
     11 *  listeners and iterating across them. It is typically used to post
     12 *  events to listening QObjects.
     13 *
     14 *  MythEvents can be dispatched to all listeners by calling dispatch
     15 *  or dispatchNow. The former is much preferred as it uses
     16 *  QCoreApplication::postEvent() while the latter uses the blocking
     17 *  QCoreApplication::sendEvent().
     18 *
     19 *  The name MythObservable is 'wrong', since all the methods refer to
     20 *  the observers as listeners (ie. addListener), however,
     21 *  MythListenable just doesn't sound right, and fixing all the calls
     22 *  to addListener was too big a patch.
     23 */
     24
     25MythObservable::MythObservable() : m_lock(new QMutex())
    726{
    827}
    928
    1029MythObservable::~MythObservable()
    1130{
     31    delete m_lock;
     32    m_lock = NULL;
    1233}
    1334
     35/** \brief Add a listener to the observable
     36 *
     37 *  Adds the given QObject to the list of objects that observe
     38 *  this observable.
     39 *
     40 *  \param listener the QObject that will listen to this observable
     41 */
    1442void MythObservable::addListener(QObject *listener)
    1543{
    16     if (m_listeners.indexOf(listener) == -1)
    17         m_listeners.append(listener);
     44    if (listener)
     45    {
     46        QMutexLocker locker(m_lock);
     47        m_listeners.insert(listener);
     48    }
    1849}
    1950
     51
     52/** \brief Remove a listener to the observable
     53 *
     54 *  Remove the given QObject from the list of objects that
     55 *  observe this observable.
     56 *
     57 *  \param listener the QObject that already listens to this observable
     58 */
    2059void MythObservable::removeListener(QObject *listener)
    2160{
    22     if (m_listeners.indexOf(listener) != -1)
    23         m_listeners.removeAll(listener);
     61    if (listener)
     62    {
     63        QMutexLocker locker(m_lock);
     64        m_listeners.remove(listener);
     65        QCoreApplication::removePostedEvents(listener);
     66    }
    2467}
    2568
    26 QObject* MythObservable::firstListener()
     69/** \brief Dispatch an event to all listeners
     70 *
     71 *  Makes a copy of the event on the heap by calling
     72 *  MythEvent::clone() and dispatches is by calling
     73 *  QCoreApplication::postEvent().
     74 *
     75 *  \param event MythEvent to dispatch.
     76 */
     77void MythObservable::dispatch(const MythEvent &event)
    2778{
    28     m_listener_it = m_listeners.begin();
    29     return m_listeners.first();
    30 }
     79    QMutexLocker locker(m_lock);
    3180
    32 QObject* MythObservable::nextListener()
    33 {
    34     ++m_listener_it;
    35     if (m_listener_it != m_listeners.end())
    36         return *m_listener_it;
    37     else
    38         return NULL;
    39 }
    40 
    41 QList<QObject*> MythObservable::getListeners()
    42 {
    43     return m_listeners;
    44 }
    45 
    46 void MythObservable::dispatch(const MythEvent &event)
    47 {
    48     QList<QObject*>::const_iterator it = m_listeners.begin();
    49     while (it != m_listeners.end())
    50     {
     81    QSet<QObject*>::const_iterator it = m_listeners.begin();
     82    for (; it != m_listeners.end() ; ++it)
    5183        QCoreApplication::postEvent(*it, event.clone());
    52         ++it;
    53     }
    5484}
    5585
     86/** \brief Dispatch an event to all listeners
     87 *
     88 *  This sends an event using the current thread, this is
     89 *  almost always unsafe.
     90 *
     91 *  \param event a MythEvent to dispatch.
     92 */
    5693void MythObservable::dispatchNow(const MythEvent &event)
    5794{
    58     QList<QObject*>::const_iterator it = m_listeners.begin();
    59     while (it != m_listeners.end())
    60     {
     95    QMutexLocker locker(m_lock);
     96
     97    QSet<QObject*>::const_iterator it = m_listeners.begin();
     98    for (; it != m_listeners.end() ; ++it)
    6199        QCoreApplication::sendEvent(*it, event.clone());
    62         ++it;
    63     }
    64100}
    65101
  • libs/libmythdb/mythversion.h

     
    88/// Update this whenever the plug-in API changes.
    99/// Including changes in the libmythdb, libmyth and libmythui class methods
    1010/// used by plug-ins.
    11 #define MYTH_BINARY_VERSION "0.23.20091208-1"
     11#define MYTH_BINARY_VERSION "0.23.20091217-1"
    1212
    1313/** \brief Increment this whenever the MythTV network protocol changes.
    1414 *
  • libs/libmythdb/mythobservable.h

     
    11#ifndef MYTHOBSERVABLE_H_
    22#define MYTHOBSERVABLE_H_
    33
    4 #include <QList>
     4#include <QSet>
    55#include "mythevent.h"
    66#include "mythexp.h"
    77
    88class QObject;
     9class QMutex;
    910
    10 /** \class MythObservable
    11     \brief Superclass for making an object have a set of listeners
    12 
    13     This superclass provides the basic API for adding and removing
    14     listeners and iterating across them. It is typically used to post
    15     events to listening QObjects.
    16 
    17        For example, to post a custom event with event id 100 to all listeners :
    18 
    19        \code
    20        void dispatch()
    21        {
    22            QObject *listener = firstListener();
    23                while (listener) {
    24                    QCoreApplication::postEvent (listener, new QEvent(100));
    25                listener = nextListener();
    26            }
    27        }
    28        \endcode
    29 
    30     MythEvents can be dispatched to all listeners by calling dispatch
    31     or dispatchNow. The former is much preferred as it uses
    32     QCoreApplication::postEvent() while the latter uses the blocking
    33     QCoreApplication::sendEvent().
    34 
    35     The name MythObservable is 'wrong', since all the methods refer to
    36     the observers as listeners (ie. addListener), however,
    37     MythListenable just doesn't sound right, and fixing all the calls
    38     to addListener was too big a patch.
    39 */
    4011class MPUBLIC MythObservable
    4112{
    4213  public:
    4314    MythObservable();
    4415    virtual ~MythObservable();
    4516
    46     /** \brief Add a listener to the observable
    47 
    48         Adds the given QObject to the list of objects that observe
    49         this observable.
    50 
    51         \param listener the QObject that will listen to this observable
    52     */
    5317    void addListener(QObject *listener);
    54 
    55     /** \brief Remove a listener to the observable
    56 
    57          Remove the given QObject from the list of objects that
    58          observe this observable.
    59 
    60          \param listener the QObject that already listens to this observable
    61     */
    6218    void removeListener(QObject *listener);
    6319
    64     /** \brief Begin iteration across listeners
    65 
    66         If you simply need to iterate across the listeners, use \p
    67         firstListener and \p nextListener to iterate across the
    68         listeners. Ie. instead of
    69 
    70         \code
    71         {
    72             QPtrList<QObject> listeners = getListeners();
    73             QObject *listener = listeners.first();
    74             while (listener) {
    75                 // use listener...
    76                 listener = listeners.next();
    77             }
    78         }
    79         \endcode
    80 
    81         you can avoid the copy and just do
    82 
    83         \code
    84         {
    85             QObject *listener = firstListener();
    86             while (listener) {
    87                 // use listener...
    88                 listener = nextListener();
    89             }
    90         }
    91         \endcode
    92 
    93         \returns pointer to the first listener, NULL if there are no listeners
    94     */
    95     QObject* firstListener();
    96 
    97     /** \brief Continue iteration to the next listener
    98 
    99         See firstListener. Returns NULL if there are no more listeners.
    100 
    101         \returns pointer to the next listener, NULL if there are no more listeners
    102     */
    103     QObject* nextListener();
    104 
    105     /** \brief Get a copy of the list of listener
    106 
    107         If you need access to more than just iteration via
    108         firstListener/nextListerner, you can call this to obtain a
    109         QPtrList with all the listeners.
    110 
    111         \returns a copy of the list of listener
    112     */
    113     QList<QObject*> getListeners(void);
    114 
    115     /** \brief Dispatch an event to all listeners
    116 
    117         Makes a copy of the event on the heap by calling
    118         MythEvent::clone and dispatches is by calling
    119         QCoreApplication::postEvent.
    120 
    121         \param event a MythEvent to dispatch.
    122     */
    12320    void dispatch(const MythEvent &event);
     21    void dispatchNow(const MythEvent &event) MDEPRECATED;
    12422
    125     /** \brief Dispatch an event to all listeners
    126 
    127         See dispatch.
    128 
    129         \note This uses QCoreApplication::sendEvent, which is
    130         blocking. It's preferred to use dispatch instead.
    131 
    132         \param event a MythEvent to dispatch.
    133     */
    134     void dispatchNow(const MythEvent &event);
    135 
    13623  private:
    137     QList<QObject*> m_listeners;
    138     QList<QObject*>::const_iterator m_listener_it;
     24    QMutex         *m_lock;
     25    QSet<QObject*>  m_listeners;
    13926};
    14027
    14128#endif /* MYTHOBSERVABLE_H */
  • programs/mythfrontend/playbackbox.cpp

     
    471471        m_freeSpaceTimer = NULL;
    472472    }
    473473
    474     clearProgramCache();
    475 
    476     delete m_currentItem;
    477 
    478474    // disconnect preview generators
    479475    QMutexLocker locker(&m_previewGeneratorLock);
    480476    PreviewMap::iterator it = m_previewGenerator.begin();
     
    483479        if ((*it).gen)
    484480            (*it).gen->disconnectSafe();
    485481    }
     482
     483    clearProgramCache();
     484
     485    delete m_currentItem;
    486486}
    487487
    488488bool PlaybackBox::Create()