BMediaRoster: Reintroduce the undertaker class
* This has been necessary due to the undefined call order of of static objects. Fixes #12315. * The bug has been caused by the linker which free unused resources, making the BMediaRoster to run in a zombie state. In this state anything such as a message could make the looper to crash. * The class is reintroduced with some differences though, we are going to protect it from another thread calling Roster() while the BMediaRoster is quitting and implement BMediaRosterEx::Quit. * Unregister registrar notifications before we quit our thread. Avoid to uninitialize anything from QuitRequested as it may cause problems.
This commit is contained in:
@@ -37,6 +37,8 @@ public:
|
|||||||
BMediaRosterEx(status_t* out_error);
|
BMediaRosterEx(status_t* out_error);
|
||||||
virtual ~BMediaRosterEx();
|
virtual ~BMediaRosterEx();
|
||||||
|
|
||||||
|
virtual void Quit();
|
||||||
|
|
||||||
status_t SaveNodeConfiguration(BMediaNode* node);
|
status_t SaveNodeConfiguration(BMediaNode* node);
|
||||||
status_t LoadNodeConfiguration(media_addon_id addonid,
|
status_t LoadNodeConfiguration(media_addon_id addonid,
|
||||||
int32 flavorid, BMessage* out_msg);
|
int32 flavorid, BMessage* out_msg);
|
||||||
|
|||||||
@@ -86,6 +86,22 @@ static bool sServerIsUp = false;
|
|||||||
static List<RosterNotification> sNotificationList;
|
static List<RosterNotification> sNotificationList;
|
||||||
static BLocker sInitLocker("BMediaRoster::Roster locker");
|
static BLocker sInitLocker("BMediaRoster::Roster locker");
|
||||||
|
|
||||||
|
|
||||||
|
class MediaRosterUndertaker {
|
||||||
|
public:
|
||||||
|
~MediaRosterUndertaker()
|
||||||
|
{
|
||||||
|
BAutolock _(sInitLocker);
|
||||||
|
if (BMediaRoster::CurrentRoster() != NULL
|
||||||
|
&& BMediaRoster::CurrentRoster()->Lock()) {
|
||||||
|
BMediaRoster::CurrentRoster()->Quit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static MediaRosterUndertaker sMediaRosterUndertaker;
|
||||||
|
|
||||||
} // namespace media
|
} // namespace media
|
||||||
} // namespace BPrivate
|
} // namespace BPrivate
|
||||||
|
|
||||||
@@ -96,8 +112,8 @@ BMediaRosterEx::BMediaRosterEx(status_t* _error)
|
|||||||
:
|
:
|
||||||
BMediaRoster()
|
BMediaRoster()
|
||||||
{
|
{
|
||||||
gDormantNodeManager = new DormantNodeManager;
|
gDormantNodeManager = new DormantNodeManager();
|
||||||
gTimeSourceObjectManager = new TimeSourceObjectManager;
|
gTimeSourceObjectManager = new TimeSourceObjectManager();
|
||||||
|
|
||||||
*_error = BuildConnections();
|
*_error = BuildConnections();
|
||||||
|
|
||||||
@@ -111,6 +127,19 @@ BMediaRosterEx::BMediaRosterEx(status_t* _error)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
BMediaRosterEx::Quit()
|
||||||
|
{
|
||||||
|
if (be_roster->StopWatching(BMessenger(this, this)) != B_OK)
|
||||||
|
TRACE("Can't unregister roster notifications");
|
||||||
|
|
||||||
|
if (sNotificationList.CountItems() != 0)
|
||||||
|
sNotificationList.MakeEmpty();
|
||||||
|
|
||||||
|
BMediaRoster::Quit();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
BMediaRosterEx::BuildConnections()
|
BMediaRosterEx::BuildConnections()
|
||||||
{
|
{
|
||||||
@@ -3474,13 +3503,6 @@ bool
|
|||||||
BMediaRoster::QuitRequested()
|
BMediaRoster::QuitRequested()
|
||||||
{
|
{
|
||||||
CALLED();
|
CALLED();
|
||||||
|
|
||||||
if (be_roster->StopWatching(BMessenger(this, this)) != B_OK)
|
|
||||||
TRACE("Can't unregister roster notifications");
|
|
||||||
|
|
||||||
if (sNotificationList.CountItems() != 0)
|
|
||||||
sNotificationList.MakeEmpty();
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user