try to avoid a media_addon_server crash on quit (bug #5863).

* BMediaRosterEx::ReleaseNodeAll(): if media_server isn't available,
try to contact the node locally.
* BMediaRoster::UnregisterNode(): if media_server isn't available,
try to get the addon_id from the local node.
* BMediaNode::AddOn() as a pure virtual methode isn't available in the
BMediaNode destructor. Workaround that by calling UnregisterNode()
in DeleteHook() instead of the destructor.
* MediaAddonServer::_DestroyInstantiatedFlavors(): give time to each
flavor to clean up.
This commit is contained in:
Jérôme Duval
2013-10-19 19:51:48 +02:00
parent 79ce2c2d1b
commit c74afb578a
3 changed files with 33 additions and 16 deletions
+5 -4
View File
@@ -148,12 +148,9 @@ BMediaNode::~BMediaNode()
fTimeSource = NULL;
}
// Attention! We do not unregister TimeSourceObject nodes,
// or delete their control ports, since they are only a
// Attention! We do not delete their control ports, since they are only a
// shadow object, and the real one still exists
if (0 == (fKinds & NODE_KIND_SHADOW_TIMESOURCE)) {
BMediaRoster::Roster()->UnregisterNode(this);
if (fControlPort > 0)
delete_port(fControlPort);
} else {
@@ -829,6 +826,10 @@ BMediaNode::ApplyChangeTag(int32 previously_reserved)
BMediaNode::DeleteHook(BMediaNode *node)
{
CALLED();
// Attention! We do not unregister TimeSourceObject nodes,
// since they are only a shadow object, and the real one still exists
if ((fKinds & NODE_KIND_SHADOW_TIMESOURCE) == 0)
BMediaRoster::Roster()->UnregisterNode(this);
delete this; // delete "this" or "node", both are the same
return B_OK;
}
+15 -4
View File
@@ -221,9 +221,18 @@ BMediaRosterEx::ReleaseNodeAll(const media_node& node)
rv = QueryServer(SERVER_RELEASE_NODE_ALL, &request, sizeof(request), &reply,
sizeof(reply));
if (rv != B_OK) {
ERROR("BMediaRoster::ReleaseNodeAll FAILED, node %" B_PRId32 ", port %"
ERROR("BMediaRoster::ReleaseNodeAll failed to query media_server, "
"retrying local, node %" B_PRId32 ", port %"
B_PRId32 ", team %" B_PRId32 "!\n", node.node, node.port,
BPrivate::current_team());
node_final_release_command command;
rv = SendToPort(node.port, NODE_FINAL_RELEASE, &command,
sizeof(command));
if (rv != B_OK) {
ERROR("BMediaRoster::ReleaseNodeAll FAILED, node %" B_PRId32 ", port %"
B_PRId32 ", team %" B_PRId32 "!\n", node.node, node.port,
BPrivate::current_team());
}
}
return rv;
}
@@ -2079,13 +2088,16 @@ BMediaRoster::UnregisterNode(BMediaNode* node)
BPrivate::media::notifications::NodesDeleted(&request.node_id, 1);
server_unregister_node_reply reply;
reply.add_on_id = -1;
status_t status = QueryServer(SERVER_UNREGISTER_NODE, &request,
sizeof(request), &reply, sizeof(reply));
if (status != B_OK) {
ERROR("BMediaRoster::UnregisterNode: failed to unregister node id %"
B_PRId32 ", name '%s': %s\n", node->ID(), node->Name(),
strerror(status));
return status;
BMediaAddOn *addon = node->AddOn(&reply.flavor_id);
if (addon != NULL)
reply.add_on_id = addon->AddonID();
}
if (reply.add_on_id != -1) {
@@ -2110,7 +2122,7 @@ BMediaRoster::UnregisterNode(BMediaNode* node)
// we are a friend class of BMediaNode and invalidate this member variable
node->fNodeID = NODE_UNREGISTERED_ID;
return B_OK;
return status;
}
@@ -3309,4 +3321,3 @@ BMediaRoster::SetRunningDefault(media_node_id forDefault,
BMediaRoster* BMediaRoster::sDefaultInstance = NULL;
+13 -8
View File
@@ -315,7 +315,7 @@ MediaAddonServer::QuitRequested()
BMediaRoster::CurrentRoster()->Lock();
BMediaRoster::CurrentRoster()->Quit();
for (iterator = fInfoMap.begin(); iterator != fInfoMap.end(); iterator++)
_PutAddonIfPossible(iterator->second);
@@ -579,9 +579,9 @@ MediaAddonServer::_DestroyInstantiatedFlavors(AddOnInfo& info)
NodeVector::iterator iterator = info.active_flavors.begin();
for (; iterator != info.active_flavors.end(); iterator++) {
media_node& node = *iterator;
printf("node %" B_PRId32 "\n", node.node);
if ((node.kind & B_TIME_SOURCE) != 0
&& (fMediaRoster->StopTimeSource(node, 0, true) != B_OK)) {
printf("MediaAddonServer::_DestroyInstantiatedFlavors couldn't stop "
@@ -650,8 +650,14 @@ MediaAddonServer::_DestroyInstantiatedFlavors(AddOnInfo& info)
}
}
}
MediaRosterEx(fMediaRoster)->ReleaseNodeAll(node);
if (MediaRosterEx(fMediaRoster)->ReleaseNodeAll(node) != B_OK) {
printf("MediaAddonServer::_DestroyInstantiatedFlavors "
"couldn't release node\n");
}
// wait a bit to let the node clean up
snooze(50000);
}
info.active_flavors.clear();
@@ -724,9 +730,9 @@ MediaAddonServer::_InstantiateAutostartFlavors(AddOnInfo& info)
continue;
else if (status != B_OK)
break;
printf("started node %" B_PRId32 "\n", index);
status = MediaRosterEx(fMediaRoster)->RegisterNode(node, info.id,
internalID);
if (status != B_OK) {
@@ -798,4 +804,3 @@ main()
delete be_app;
return 0;
}