launch_daemon: Retrieve default port from monitoring BRoster.

* Instead, we now maintain a default port for a job. For "legacy"
  services, BRoster's B_SOME_APP_LAUNCHED will update it, too.
* This allows to quit Tracker using "launch_roster stop".
* Also, this fixes bug #12249, as we don't use the signature variant of
  creating BMessenger anymore in Job::GetMessenger(). This would call
  into the launch_daemon again, and deadlock.
This commit is contained in:
Axel Dörfler 2015-11-10 15:55:35 +01:00
parent c1a27ee107
commit 70708ef97d
3 changed files with 83 additions and 23 deletions

View File

@ -30,6 +30,7 @@ Job::Job(const char* name)
fLaunching(false),
fInitStatus(B_NO_INIT),
fTeam(-1),
fDefaultPort(-1),
fLaunchStatus(B_NO_INIT),
fTarget(NULL),
fPendingLaunchDataReplies(0, false)
@ -47,6 +48,7 @@ Job::Job(const Job& other)
fLaunching(other.IsLaunching()),
fInitStatus(B_NO_INIT),
fTeam(-1),
fDefaultPort(-1),
fLaunchStatus(B_NO_INIT),
fTarget(other.Target()),
fPendingLaunchDataReplies(0, false)
@ -298,6 +300,20 @@ Job::Port(const char* name) const
}
port_id
Job::DefaultPort() const
{
return fDefaultPort;
}
void
Job::SetDefaultPort(port_id port)
{
fDefaultPort = port;
}
status_t
Job::Launch()
{
@ -373,8 +389,12 @@ void
Job::TeamDeleted()
{
fTeam = -1;
fDefaultPort = -1;
if (IsService())
SetState(B_JOB_STATE_WAITING_TO_RUN);
_SetLaunchStatus(B_NO_INIT);
}
@ -414,24 +434,12 @@ Job::HandleGetLaunchData(BMessage* message)
status_t
Job::GetMessenger(BMessenger& messenger)
{
PortMap::const_iterator iterator = fPortMap.begin();
for (; iterator != fPortMap.end(); iterator++) {
if (iterator->second.HasString("name"))
continue;
if (fDefaultPort < 0)
return B_NAME_NOT_FOUND;
port_id port = (port_id)iterator->second.GetInt32("port", -1);
if (port >= 0) {
BMessenger::Private(messenger).SetTo(fTeam, port,
B_PREFERRED_TOKEN);
return B_OK;
}
}
// There is no default port, try roster via signature
BString signature = "application/";
signature << Name();
return messenger.SetTo(signature);
BMessenger::Private(messenger).SetTo(fTeam, fDefaultPort,
B_PREFERRED_TOKEN);
return B_OK;
}
@ -518,9 +526,6 @@ Job::_SetLaunchStatus(status_t launchStatus)
fLaunchStatus = launchStatus != B_NO_INIT ? launchStatus : B_ERROR;
launchLocker.Unlock();
if (fTeamRegistrator != NULL)
fTeamRegistrator->RegisterTeam(this);
_SendPendingLaunchDataReplies();
}
@ -588,6 +593,8 @@ Job::_CreateAndTransferPorts()
return result;
iterator->second.SetInt32("port", port);
if (suffix == NULL)
fDefaultPort = port;
if (name == "x-vnd.haiku-registrar:auth") {
// Allow the launch_daemon to access the registrar authentication
@ -608,6 +615,7 @@ Job::_CreateAndTransferPorts()
return result;
data.SetInt32("port", port);
fDefaultPort = port;
AddPort(data);
}
@ -626,9 +634,12 @@ Job::_Launch(const char* signature, entry_ref* ref, int argCount,
if (result == B_OK) {
result = _CreateAndTransferPorts();
if (result == B_OK)
if (result == B_OK) {
resume_thread(mainThread);
else
if (fTeamRegistrator != NULL)
fTeamRegistrator->RegisterTeam(this);
} else
kill_thread(mainThread);
}

View File

@ -81,6 +81,9 @@ public:
const PortMap& Ports() const;
port_id Port(const char* name = NULL) const;
port_id DefaultPort() const;
void SetDefaultPort(port_id port);
status_t Launch();
bool IsLaunched() const;
bool IsRunning() const;
@ -126,6 +129,7 @@ private:
PortMap fPortMap;
status_t fInitStatus;
team_id fTeam;
port_id fDefaultPort;
status_t fLaunchStatus;
mutex fLaunchStatusLock;
::Target* fTarget;

View File

@ -232,6 +232,9 @@ private:
static const char*
get_leaf(const char* signature)
{
if (signature == NULL)
return NULL;
const char* separator = strrchr(signature, '/');
if (separator != NULL)
return separator + 1;
@ -469,6 +472,9 @@ LaunchDaemon::ReadyToRun()
if (target != NULL)
_LaunchJobs(target);
}
if (fUserMode)
be_roster->StartWatching(this, B_REQUEST_LAUNCHED);
}
@ -499,6 +505,41 @@ LaunchDaemon::MessageReceived(BMessage* message)
}
break;
}
case B_SOME_APP_LAUNCHED:
{
team_id team = (team_id)message->GetInt32("be:team", -1);
Job* job = NULL;
MutexLocker locker(fTeamsLock);
TeamMap::iterator found = fTeams.find(team);
if (found != fTeams.end()) {
job = found->second;
locker.Unlock();
} else {
locker.Unlock();
// Find job by name instead
const char* signature = message->GetString("be:signature");
job = FindJob(get_leaf(signature));
if (job != NULL) {
TRACE("Updated default port of untracked team %d, %s\n",
(int)team, signature);
}
}
if (job != NULL) {
// Update port info
app_info info;
status_t status = be_roster->GetRunningAppInfo(team, &info);
if (status == B_OK && info.port != job->DefaultPort()) {
TRACE("Update default port for %s to %d\n", job->Name(),
(int)info.port);
job->SetDefaultPort(info.port);
}
}
break;
}
case B_GET_LAUNCH_DATA:
_HandleGetLaunchData(message);
@ -1654,7 +1695,11 @@ LaunchDaemon::_StartSession(const char* login)
// TODO: This leaks the parent application
be_app = NULL;
// TODO: take over system jobs, and reserve their names
// Reinitialize be_roster
BRoster::Private().DeleteBeRoster();
BRoster::Private().InitBeRoster();
// TODO: take over system jobs, and reserve their names (or ask parent)
status_t status;
LaunchDaemon* daemon = new LaunchDaemon(true, fEvents, status);
if (status == B_OK)