Fix crash on exit; that would happen when LLOfferHandler would try to access mChannel which was already destroyed prior.

Nicky 2012-04-01 20:59:53 +02:00
parent c33e710c42
commit 28327b8cc5
4 changed files with 45 additions and 1 deletions

View File

@ -81,6 +81,7 @@ typedef enum e_notification_type
// - signal, that emits ID of the notification that is being processed
//
class LLEventHandler
: public LLScreenChannelBase::LLScreenChannelObserver // </FS:ND> derive from observer, so we get notified when the Channel we hold dies.
{
public:
virtual ~LLEventHandler() {};
@ -110,6 +111,10 @@ protected:
LLScreenChannelBase* mChannel;
e_notification_type mType;
// <FS:ND> Channel is dead, remove it. Yay for mChannel being protected so every derived class just mucks with the pointer as it wishes. Otherwise we could register an observer as soon as mChannel is set.
virtual void observeDestruction( LLScreenChannelBase *)
{ mChannel = 0; }
// </FS:ND>
};
// LLSysHandler and LLChatHandler are more specific base classes
@ -256,6 +261,7 @@ protected:
* Handler for offers notices.
* It manages life time of offer notices.
*/
class LLOfferHandler : public LLSysHandler
{
public:
@ -265,6 +271,7 @@ public:
// base interface functions
virtual bool processNotification(const LLSD& notify);
protected:
virtual void onDeleteToast(LLToast* toast);
virtual void initChannel();

View File

@ -51,11 +51,20 @@ LLOfferHandler::LLOfferHandler(e_notification_type type, const LLSD& id)
LLScreenChannel* channel = dynamic_cast<LLScreenChannel*>(mChannel);
if(channel)
channel->setOnRejectToastCallback(boost::bind(&LLOfferHandler::onRejectToast, this, _1));
// <FS:ND> Register with observer so we notice when mChannel diees
if( mChannel )
mChannel->setObserver( this );
// </FS:ND>
}
//--------------------------------------------------------------------------
LLOfferHandler::~LLOfferHandler()
{
// <FS:ND> Where are dead. In case we still hold a channel unregister
if( mChannel )
mChannel->setObserver( 0 );
// </FS:ND>
}
//--------------------------------------------------------------------------

View File

@ -125,6 +125,16 @@ LLScreenChannelBase::LLScreenChannelBase(const Params& p)
setMouseOpaque( false );
setVisible(FALSE);
mObserver = 0; // </FS:ND> Observerable
}
LLScreenChannelBase::~LLScreenChannelBase()
{
// <FS:ND> Notofiy our observer that we're going down
if( mObserver )
mObserver->observeDestruction( this );
// </FS:ND>
}
BOOL LLScreenChannelBase::postBuild()
@ -233,7 +243,6 @@ void LLScreenChannel::init(S32 channel_left, S32 channel_right)
//--------------------------------------------------------------------------
LLScreenChannel::~LLScreenChannel()
{
}
std::list<LLToast*> LLScreenChannel::findToasts(const Matcher& matcher)

View File

@ -52,6 +52,7 @@ typedef enum e_channel_alignment
class LLScreenChannelBase : public LLUICtrl
{
friend class LLChannelManager;
public:
struct Params : public LLInitParam::Block<Params, LLUICtrl::Params>
{
@ -69,6 +70,7 @@ public:
};
LLScreenChannelBase(const Params&);
virtual ~LLScreenChannelBase();
BOOL postBuild();
@ -142,6 +144,22 @@ protected:
LLView* mFloaterSnapRegion;
LLView* mChicletRegion;
// <FS:ND> Oberserver for ScreenChannelBase destruction
public:
class LLScreenChannelObserver
{
public:
virtual ~LLScreenChannelObserver() {}
virtual void observeDestruction( LLScreenChannelBase *) = 0;
};
void setObserver( LLScreenChannelObserver *aObserver )
{ mObserver = aObserver; }
private:
LLScreenChannelObserver *mObserver;
// </FS:ND>
};
@ -151,6 +169,7 @@ protected:
class LLScreenChannel : public LLScreenChannelBase
{
friend class LLChannelManager;
public:
LLScreenChannel(const Params&);
virtual ~LLScreenChannel();