BMessage: fixed reply port race condition.

* When the team that we got the synchronous reply from immediately
  terminated afterwards, it might have still owned (and therefore
  destroyed) our reply port.
* Make sure it's not added to the pool again, but is recreated instead.
This commit is contained in:
Axel Dörfler
2015-07-22 20:40:06 +02:00
parent d482c7ca5b
commit e31148095d
+12 -7
View File
@@ -1,5 +1,5 @@
/* /*
* Copyright 2005-2014 Haiku, Inc. All rights reserved. * Copyright 2005-2015 Haiku, Inc. All rights reserved.
* Distributed under the terms of the MIT License. * Distributed under the terms of the MIT License.
* *
* Authors: * Authors:
@@ -58,7 +58,7 @@
#if BMESSAGE_TRACING #if BMESSAGE_TRACING
# define KTRACE(format...) ktrace_printf(format) # define KTRACE(format...) ktrace_printf(format)
#else #else
# define KTRACE(format...) # define KTRACE(format...) ;
#endif #endif
@@ -2276,6 +2276,8 @@ BMessage::_SendMessage(port_id port, team_id portOwner, int32 token,
replyPort = sReplyPorts[cachedReplyPort]; replyPort = sReplyPorts[cachedReplyPort];
} }
bool recreateCachedPort = false;
team_id team = B_BAD_TEAM_ID; team_id team = B_BAD_TEAM_ID;
if (be_app != NULL) if (be_app != NULL)
team = be_app->Team(); team = be_app->Team();
@@ -2345,15 +2347,18 @@ BMessage::_SendMessage(port_id port, team_id portOwner, int32 token,
result = handle_reply(replyPort, &code, replyTimeout, reply); result = handle_reply(replyPort, &code, replyTimeout, reply);
if (result != B_OK && cachedReplyPort >= 0) { if (result != B_OK && cachedReplyPort >= 0) {
delete_port(replyPort); delete_port(replyPort);
sReplyPorts[cachedReplyPort] = create_port(1, "tmp_rport"); recreateCachedPort = true;
} }
error: error:
if (cachedReplyPort >= 0) { if (cachedReplyPort >= 0) {
// Reclaim ownership of cached port // Reclaim ownership of cached port, if possible
set_port_owner(replyPort, team); if (!recreateCachedPort && set_port_owner(replyPort, team) == B_OK) {
// Flag as available // Flag as available
atomic_add(&sReplyPortInUse[cachedReplyPort], -1); atomic_add(&sReplyPortInUse[cachedReplyPort], -1);
} else
sReplyPorts[cachedReplyPort] = create_port(1, "tmp_rport");
return result; return result;
} }