launch_daemon: added support for arbitrary ports.

* Dropped "create_port" -- this is now the default for services.
* Additionally (or alternatively, if you use the "legacy" mode), you can
  now create named ports, and specify their capacity.
* Added convenience methods to BLaunchRoster that automatically use the
  signature of the current be_app.
This commit is contained in:
Axel Dörfler 2015-04-21 18:40:26 +02:00
parent 89168ad8b9
commit 43aec2c726
5 changed files with 153 additions and 41 deletions

View File

@ -1,11 +1,9 @@
service x-vnd.Haiku-registrar {
launch /system/servers/registrar
create_port
}
service x-vnd.Haiku-app_server {
launch /system/servers/app_server
create_port
}
service x-vnd.Haiku-debug_server {
@ -14,57 +12,69 @@ service x-vnd.Haiku-debug_server {
service x-vnd.Haiku-package_daemon {
launch /system/servers/package_daemon
create_port
}
service x-vnd.Haiku-syslog_daemon {
service x-vnd.Haiku-SystemLogger {
launch /system/servers/syslog_daemon
port logger {
capacity 256
}
}
service x-vnd.Haiku-mount_server {
launch /system/servers/mount_server
legacy
}
service x-vnd.Haiku-media_server {
launch /system/servers/media_server
no_safemode
legacy
}
service x-vnd.Haiku-midi_server {
launch /system/servers/midi_server
no_safemode
legacy
}
service x-vnd.Haiku-mail_daemon {
launch /system/servers/mail_daemon -E
no_safemode
legacy
}
service x-vnd.Haiku-cddb_daemon {
launch /system/servers/cddb_daemon
no_safemode
legacy
}
service x-vnd.Haiku-print_server {
launch /system/servers/print_server
no_safemode
legacy
}
service x-vnd.Haiku-notification_server {
launch /system/servers/notification_server
no_safemode
legacy
}
service x-vnd.Haiku-power_daemon {
launch /system/servers/power_daemon
no_safemode
legacy
}
# The following will be moved into the user launch data
service x-vnd.Be-TRAK {
launch /system/Tracker
legacy
}
service x-vnd.Be-TSKB {
launch /system/Deskbar
legacy
}

View File

@ -16,9 +16,11 @@ public:
status_t InitCheck() const;
status_t GetData(BMessage& data);
status_t GetData(const char* signature, BMessage& data);
port_id GetPort(const char* name = NULL);
port_id GetPort(const char* signature,
const char* name = NULL);
const char* name);
private:
void _InitMessenger();

View File

@ -531,7 +531,7 @@ DBG(OUT("BApplication::InitData() done\n"));
port_id
BApplication::_GetPort(const char* signature)
{
return BLaunchRoster().GetPort(signature);
return BLaunchRoster().GetPort(signature, NULL);
}

View File

@ -9,6 +9,7 @@
#include <LaunchRoster.h>
#include <Application.h>
#include <String.h>
#include <LaunchDaemonDefs.h>
@ -39,6 +40,16 @@ BLaunchRoster::InitCheck() const
}
status_t
BLaunchRoster::GetData(BMessage& data)
{
if (be_app == NULL)
return B_BAD_VALUE;
return GetData(be_app->Signature(), data);
}
status_t
BLaunchRoster::GetData(const char* signature, BMessage& data)
{
@ -55,12 +66,22 @@ BLaunchRoster::GetData(const char* signature, BMessage& data)
// evaluate the reply
if (status == B_OK)
status = data.GetInt32("error", B_OK);
status = data.what;
return status;
}
port_id
BLaunchRoster::GetPort(const char* name)
{
if (be_app == NULL)
return B_BAD_VALUE;
return GetPort(be_app->Signature(), name);
}
port_id
BLaunchRoster::GetPort(const char* signature, const char* name)
{
@ -69,12 +90,10 @@ BLaunchRoster::GetPort(const char* signature, const char* name)
status_t status = launchRoster.GetData(signature, data);
if (status == B_OK) {
BString fieldName;
if (name == NULL)
fieldName = "port";
else {
fieldName = name;
fieldName << "_port";
}
if (name != NULL)
fieldName << name << "_";
fieldName << "port";
port_id port = data.GetInt32(fieldName.String(), B_NAME_NOT_FOUND);
if (port >= 0)
return port;

View File

@ -30,11 +30,17 @@ using namespace BPrivate;
static const char* kLaunchDirectory = "launch";
const static settings_template kPortTemplate[] = {
{B_STRING_TYPE, "name", NULL, true},
{B_INT32_TYPE, "capacity", NULL},
};
const static settings_template kJobTemplate[] = {
{B_STRING_TYPE, "name", NULL, true},
{B_BOOL_TYPE, "disabled", NULL},
{B_STRING_TYPE, "launch", NULL},
{B_BOOL_TYPE, "create_port", NULL},
{B_BOOL_TYPE, "legacy", NULL},
{B_MESSAGE_TYPE, "port", kPortTemplate},
{B_BOOL_TYPE, "no_safemode", NULL},
{0, NULL, NULL}
};
@ -46,6 +52,9 @@ const static settings_template kSettingsTemplate[] = {
};
typedef std::map<BString, BMessage> PortMap;
class Job {
public:
Job(const char* name);
@ -59,8 +68,10 @@ public:
bool IsService() const;
void SetService(bool service);
bool CreatePort() const;
void SetCreatePort(bool createPort);
bool CreateDefaultPort() const;
void SetCreateDefaultPort(bool createPort);
void AddPort(BMessage& data);
bool LaunchInSafeMode() const;
void SetLaunchInSafeMode(bool launch);
@ -73,7 +84,9 @@ public:
status_t InitCheck() const;
team_id Team() const;
port_id Port() const;
const PortMap& Ports() const;
port_id Port(const char* name = NULL) const;
status_t Launch();
bool IsLaunched() const;
@ -83,9 +96,9 @@ private:
BStringList fArguments;
bool fEnabled;
bool fService;
bool fCreatePort;
bool fCreateDefaultPort;
bool fLaunchInSafeMode;
port_id fPort;
PortMap fPortMap;
status_t fInitStatus;
team_id fTeam;
};
@ -141,9 +154,8 @@ Job::Job(const char* name)
fName(name),
fEnabled(true),
fService(false),
fCreatePort(false),
fCreateDefaultPort(false),
fLaunchInSafeMode(true),
fPort(-1),
fInitStatus(B_NO_INIT),
fTeam(-1)
{
@ -153,8 +165,12 @@ Job::Job(const char* name)
Job::~Job()
{
if (fPort >= 0)
delete_port(fPort);
PortMap::const_iterator iterator = Ports().begin();
for (; iterator != Ports().end(); iterator++) {
port_id port = iterator->second.GetInt32("port", -1);
if (port >= 0)
delete_port(port);
}
}
@ -194,16 +210,24 @@ Job::SetService(bool service)
bool
Job::CreatePort() const
Job::CreateDefaultPort() const
{
return fCreatePort;
return fCreateDefaultPort;
}
void
Job::SetCreatePort(bool createPort)
Job::SetCreateDefaultPort(bool createPort)
{
fCreatePort = createPort;
fCreateDefaultPort = createPort;
}
void
Job::AddPort(BMessage& data)
{
const char* name = data.GetString("name");
fPortMap.insert(std::pair<BString, BMessage>(BString(name), data));
}
@ -247,11 +271,42 @@ Job::Init()
{
fInitStatus = B_OK;
if (fCreatePort) {
// TODO: prefix system ports with "system:"
fPort = create_port(B_LOOPER_PORT_DEFAULT_CAPACITY, Name());
if (fPort < 0)
fInitStatus = fPort;
// 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 (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)
fInitStatus = port;
else {
data.SetInt32("port", port);
AddPort(data);
}
}
return fInitStatus;
@ -272,10 +327,21 @@ Job::Team() const
}
port_id
Job::Port() const
const PortMap&
Job::Ports() const
{
return fPort;
return fPortMap;
}
port_id
Job::Port(const char* name) const
{
PortMap::const_iterator found = fPortMap.find(name);
if (found != fPortMap.end())
return found->second.GetInt32("port", -1);
return B_NAME_NOT_FOUND;
}
@ -366,18 +432,27 @@ LaunchDaemon::MessageReceived(BMessage* message)
switch (message->what) {
case B_GET_LAUNCH_DATA:
{
BMessage reply;
BMessage reply((uint32)B_OK);
Job* job = _Job(get_leaf(message->GetString("name")));
if (job == NULL) {
reply.AddInt32("error", B_NAME_NOT_FOUND);
reply.what = B_NAME_NOT_FOUND;
} else {
// If the job has not been launched yet, we'll pass on our
// team here. The rationale behind this is that this team
// will temporarily own the synchronous reply ports.
reply.AddInt32("team", job->Team() < 0
? current_team() : job->Team());
if (job->CreatePort())
reply.AddInt32("port", job->Port());
PortMap::const_iterator iterator = job->Ports().begin();
for (; iterator != job->Ports().end(); iterator++) {
BString name;
if (iterator->second.HasString("name"))
name << iterator->second.GetString("name") << "_";
name << "port";
reply.AddInt32(name.String(),
iterator->second.GetInt32("port", -1));
}
// Launch job now if it isn't running yet
if (!job->IsLaunched())
@ -447,7 +522,7 @@ LaunchDaemon::_ReadFile(const char* context, BEntry& entry)
BMessage job;
for (int32 index = 0; message.FindMessage("service", index,
&job) == B_OK; index++) {
_AddJob(false, job);
_AddJob(true, job);
}
for (int32 index = 0; message.FindMessage("job", index, &job) == B_OK;
@ -475,10 +550,16 @@ LaunchDaemon::_AddJob(bool service, BMessage& message)
job->SetEnabled(!message.GetBool("disabled", !job->IsEnabled()));
job->SetService(service);
job->SetCreatePort(message.GetBool("create_port", job->CreatePort()));
job->SetCreateDefaultPort(!message.GetBool("legacy", !service));
job->SetLaunchInSafeMode(
!message.GetBool("no_safemode", !job->LaunchInSafeMode()));
BMessage portMessage;
for (int32 index = 0;
message.FindMessage("port", index, &portMessage) == B_OK; index++) {
job->AddPort(portMessage);
}
const char* argument;
for (int32 index = 0;
message.FindString("launch", index, &argument) == B_OK; index++) {