launch_daemon: Create/inject ports on launch instead of upfront.

The application is now launched suspended and the ports are created
and transferred to the launched team before its main thread is
resumed.

The ports are therefore owned by the launched team instead of the
launch_daemon. This is important when sending messages by area, as
the port owner is used to determine where the data area needs to be
transferred to. This commit therefore fixes #12285.

Note that it is still possible to get at the ports with find_port()
while they are still owned by the launch_daemon. This should not be a
problem however, as these ports are not supposed to be found this way
but only through BLaunchRoster::GetData(), which is synchronized with
the above process.

Creating the ports in the launch_daemon still has the benefit of
returning valid communication ports earlier, i.e. without having to
wait for the launched application to actually become ready.
This commit is contained in:
Michael Lotz 2015-08-28 22:18:04 +02:00
parent 5b9f6b5485
commit 5cf6c0fd3b
2 changed files with 87 additions and 52 deletions

View File

@ -244,50 +244,6 @@ Job::Init(const Finder& finder, std::set<BString>& dependencies)
}
}
// Create ports
// TODO: prefix system ports with "system:"
bool defaultPort = false;
for (PortMap::iterator iterator = fPortMap.begin();
iterator != fPortMap.end(); iterator++) {
BString name(Name());
const char* suffix = iterator->second.GetString("name");
if (suffix != NULL)
name << ':' << suffix;
else
defaultPort = true;
const int32 capacity = iterator->second.GetInt32("capacity",
B_LOOPER_PORT_DEFAULT_CAPACITY);
port_id port = create_port(capacity, name.String());
if (port < 0) {
fInitStatus = port;
break;
}
iterator->second.SetInt32("port", port);
if (name == "x-vnd.haiku-registrar:auth") {
// Allow the launch_daemon to access the registrar authentication
BPrivate::set_registrar_authentication_port(port);
}
}
if (fInitStatus == B_OK && fCreateDefaultPort && !defaultPort) {
BMessage data;
data.AddInt32("capacity", B_LOOPER_PORT_DEFAULT_CAPACITY);
port_id port = create_port(B_LOOPER_PORT_DEFAULT_CAPACITY, Name());
if (port < 0) {
// TODO: log error
fInitStatus = port;
} else {
data.SetInt32("port", port);
AddPort(data);
}
}
return fInitStatus;
}
@ -351,10 +307,7 @@ Job::Launch()
BString signature("application/");
signature << Name();
status_t status = BRoster::Private().Launch(signature.String(), NULL,
NULL, 0, NULL, &environment[0], &fTeam, NULL, false);
_SetLaunchStatus(status);
return status;
return _Launch(signature.String(), NULL, 0, NULL, &environment[0]);
}
// Build argument vector
@ -377,10 +330,7 @@ Job::Launch()
}
// Launch via entry_ref
status = BRoster::Private().Launch(NULL, &ref, NULL, count, &args[0],
&environment[0], &fTeam, NULL, false);
_SetLaunchStatus(status);
return status;
return _Launch(NULL, &ref, count, &args[0], &environment[0]);
}
@ -505,3 +455,80 @@ Job::_SendPendingLaunchDataReplies()
fPendingLaunchDataReplies.MakeEmpty();
}
status_t
Job::_CreateAndTransferPorts()
{
// TODO: prefix system ports with "system:"
bool defaultPort = false;
for (PortMap::iterator iterator = fPortMap.begin();
iterator != fPortMap.end(); iterator++) {
BString name(Name());
const char* suffix = iterator->second.GetString("name");
if (suffix != NULL)
name << ':' << suffix;
else
defaultPort = true;
const int32 capacity = iterator->second.GetInt32("capacity",
B_LOOPER_PORT_DEFAULT_CAPACITY);
port_id port = create_port(capacity, name.String());
if (port < 0)
return port;
status_t result = set_port_owner(port, fTeam);
if (result != B_OK)
return result;
iterator->second.SetInt32("port", port);
if (name == "x-vnd.haiku-registrar:auth") {
// Allow the launch_daemon to access the registrar authentication
BPrivate::set_registrar_authentication_port(port);
}
}
if (fCreateDefaultPort && !defaultPort) {
BMessage data;
data.AddInt32("capacity", B_LOOPER_PORT_DEFAULT_CAPACITY);
port_id port = create_port(B_LOOPER_PORT_DEFAULT_CAPACITY, Name());
if (port < 0)
return port;
status_t result = set_port_owner(port, fTeam);
if (result != B_OK)
return result;
data.SetInt32("port", port);
AddPort(data);
}
return B_OK;
}
status_t
Job::_Launch(const char* signature, entry_ref* ref, int argCount,
const char* const* args, const char** environment)
{
thread_id mainThread = -1;
status_t result = BRoster::Private().Launch(signature, ref, NULL, argCount,
args, environment, &fTeam, &mainThread, true);
if (result == B_OK) {
result = _CreateAndTransferPorts();
if (result == B_OK)
resume_thread(mainThread);
else
kill_thread(mainThread);
}
_SetLaunchStatus(result);
return result;
}

View File

@ -24,6 +24,8 @@ class BMessage;
class Finder;
class Target;
struct entry_ref;
typedef std::map<BString, BMessage> PortMap;
@ -87,6 +89,12 @@ private:
status_t _SendLaunchDataReply(BMessage* message);
void _SendPendingLaunchDataReplies();
status_t _CreateAndTransferPorts();
status_t _Launch(const char* signature, entry_ref* ref,
int argCount, const char* const* args,
const char** environment);
private:
BStringList fArguments;
BStringList fRequirements;