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:
Dario Casalinuovo
2015-09-01 15:08:57 +02:00
parent a33d19b0a4
commit 7d337b23b7
2 changed files with 33 additions and 9 deletions
+2
View File
@@ -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);
+31 -9
View File
@@ -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;
} }