launch_daemon: Added basic ability to stop/start jobs via API.

* Stopping a job is very simplistic right now, and will have to be
  extended considerably, probably with its own job.
This commit is contained in:
Axel Dörfler
2015-11-07 21:58:12 +01:00
parent de0e15ae8c
commit 5860caae39
6 changed files with 194 additions and 58 deletions
+2
View File
@@ -26,6 +26,8 @@ namespace BPrivate {
enum {
B_GET_LAUNCH_DATA = 'lnda',
B_LAUNCH_TARGET = 'lntg',
B_LAUNCH_JOB = 'lnjo',
B_STOP_LAUNCH_JOB = 'lnsj',
B_LAUNCH_SESSION = 'lnse',
B_REGISTER_SESSION_DAEMON = 'lnrs',
B_REGISTER_LAUNCH_EVENT = 'lnre',
+6
View File
@@ -34,6 +34,9 @@ public:
const BMessage* data = NULL,
const char* baseName = NULL);
status_t Start(const char* name);
status_t Stop(const char* name, bool force = false);
status_t StartSession(const char* login);
status_t RegisterEvent(const BMessenger& source,
@@ -56,6 +59,9 @@ private:
friend class Private;
void _InitMessenger();
status_t _SendRequest(BMessage& request);
status_t _SendRequest(BMessage& request,
BMessage& reply);
status_t _UpdateEvent(uint32 what,
const BMessenger& source, const char* name,
uint32 flags = 0);
+60 -53
View File
@@ -102,14 +102,7 @@ BLaunchRoster::GetData(const char* signature, BMessage& data)
if (status != B_OK)
return status;
// send the request
status = fMessenger.SendMessage(&request, &data);
// evaluate the reply
if (status == B_OK)
status = data.what;
return status;
return _SendRequest(request, data);
}
@@ -169,15 +162,43 @@ BLaunchRoster::Target(const char* name, const BMessage* data,
if (status != B_OK)
return status;
// send the request
BMessage result;
status = fMessenger.SendMessage(&request, &result);
return _SendRequest(request);
}
// evaluate the reply
status_t
BLaunchRoster::Start(const char* name)
{
if (name == NULL)
return B_BAD_VALUE;
BMessage request(B_LAUNCH_JOB);
status_t status = request.AddInt32("user", getuid());
if (status == B_OK)
status = result.what;
status = request.AddString("name", name);
if (status != B_OK)
return status;
return status;
return _SendRequest(request);
}
status_t
BLaunchRoster::Stop(const char* name, bool force)
{
if (name == NULL)
return B_BAD_VALUE;
BMessage request(B_STOP_LAUNCH_JOB);
status_t status = request.AddInt32("user", getuid());
if (status == B_OK)
status = request.AddString("name", name);
if (status == B_OK)
status = request.AddBool("force", force);
if (status != B_OK)
return status;
return _SendRequest(request);
}
@@ -194,15 +215,7 @@ BLaunchRoster::StartSession(const char* login)
if (status != B_OK)
return status;
// send the request
BMessage result;
status = fMessenger.SendMessage(&request, &result);
// evaluate the reply
if (status == B_OK)
status = result.what;
return status;
return _SendRequest(request);
}
@@ -245,12 +258,7 @@ BLaunchRoster::GetTargets(BStringList& targets)
// send the request
BMessage result;
status = fMessenger.SendMessage(&request, &result);
// evaluate the reply
if (status == B_OK)
status = result.what;
status = _SendRequest(request, result);
if (status == B_OK)
status = result.FindStrings("target", &targets);
@@ -277,12 +285,7 @@ BLaunchRoster::GetJobs(const char* target, BStringList& jobs)
// send the request
BMessage result;
status = fMessenger.SendMessage(&request, &result);
// evaluate the reply
if (status == B_OK)
status = result.what;
status = _SendRequest(request, result);
if (status == B_OK)
status = result.FindStrings("job", &jobs);
@@ -310,6 +313,26 @@ BLaunchRoster::_InitMessenger()
}
status_t
BLaunchRoster::_SendRequest(BMessage& request)
{
BMessage result;
return _SendRequest(request, result);
}
status_t
BLaunchRoster::_SendRequest(BMessage& request, BMessage& result)
{
// Send the request, and evaluate the reply
status_t status = fMessenger.SendMessage(&request, &result);
if (status == B_OK)
status = result.what;
return status;
}
status_t
BLaunchRoster::_UpdateEvent(uint32 what, const BMessenger& source,
const char* name, uint32 flags)
@@ -330,15 +353,7 @@ BLaunchRoster::_UpdateEvent(uint32 what, const BMessenger& source,
if (status != B_OK)
return status;
// send the request
BMessage result;
status = fMessenger.SendMessage(&request, &result);
// evaluate the reply
if (status == B_OK)
status = result.what;
return status;
return _SendRequest(request);
}
@@ -355,13 +370,5 @@ BLaunchRoster::_GetInfo(uint32 what, const char* name, BMessage& info)
if (status != B_OK)
return status;
// send the request
BMessage result;
status = fMessenger.SendMessage(&request, &info);
// evaluate the reply
if (status == B_OK)
status = result.what;
return status;
return _SendRequest(request, info);
}
+27 -1
View File
@@ -13,6 +13,7 @@
#include <Message.h>
#include <Roster.h>
#include <MessagePrivate.h>
#include <RosterPrivate.h>
#include <user_group.h>
@@ -43,6 +44,7 @@ Job::Job(const Job& other)
fEnabled(other.IsEnabled()),
fService(other.IsService()),
fCreateDefaultPort(other.CreateDefaultPort()),
fLaunching(other.IsLaunching()),
fInitStatus(B_NO_INIT),
fTeam(-1),
fLaunchStatus(B_NO_INIT),
@@ -380,7 +382,7 @@ bool
Job::CanBeLaunched() const
{
// Services cannot be launched while they are running
return !IsLaunching() && (!IsService() || !IsRunning());
return IsEnabled() && !IsLaunching() && (!IsService() || !IsRunning());
}
@@ -409,6 +411,30 @@ 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;
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);
}
status_t
Job::Run()
{
+2
View File
@@ -20,6 +20,7 @@
using namespace BSupportKit;
class BMessage;
class BMessenger;
class Finder;
class Job;
@@ -90,6 +91,7 @@ public:
void SetLaunching(bool launching);
status_t HandleGetLaunchData(BMessage* message);
status_t GetMessenger(BMessenger& messenger);
virtual status_t Run();
+97 -4
View File
@@ -153,6 +153,8 @@ public:
private:
void _HandleGetLaunchData(BMessage* message);
void _HandleLaunchTarget(BMessage* message);
void _HandleLaunchJob(BMessage* message);
void _HandleStopLaunchJob(BMessage* message);
void _HandleLaunchSession(BMessage* message);
void _HandleRegisterSessionDaemon(BMessage* message);
void _HandleRegisterLaunchEvent(BMessage* message);
@@ -179,6 +181,7 @@ private:
void _LaunchJobs(Target* target,
bool forceNow = false);
void _LaunchJob(Job* job, uint32 options = 0);
void _StopJob(Job* job, bool force);
void _AddTarget(Target* target);
void _SetCondition(BaseJob* job,
const BMessage& message);
@@ -501,11 +504,16 @@ LaunchDaemon::MessageReceived(BMessage* message)
case B_LAUNCH_TARGET:
_HandleLaunchTarget(message);
break;
case B_LAUNCH_JOB:
_HandleLaunchJob(message);
break;
case B_STOP_LAUNCH_JOB:
_HandleStopLaunchJob(message);
break;
case B_LAUNCH_SESSION:
_HandleLaunchSession(message);
break;
case B_REGISTER_SESSION_DAEMON:
_HandleRegisterSessionDaemon(message);
break;
@@ -513,15 +521,12 @@ LaunchDaemon::MessageReceived(BMessage* message)
case B_REGISTER_LAUNCH_EVENT:
_HandleRegisterLaunchEvent(message);
break;
case B_UNREGISTER_LAUNCH_EVENT:
_HandleUnregisterLaunchEvent(message);
break;
case B_NOTIFY_LAUNCH_EVENT:
_HandleNotifyLaunchEvent(message);
break;
case B_RESET_STICKY_LAUNCH_EVENT:
_HandleResetStickyLaunchEvent(message);
break;
@@ -787,6 +792,67 @@ LaunchDaemon::_HandleLaunchTarget(BMessage* message)
}
void
LaunchDaemon::_HandleLaunchJob(BMessage* message)
{
uid_t user = _GetUserID(message);
if (user < 0)
return;
const char* name = message->GetString("name");
Job* job = FindJob(name);
if (job == NULL) {
Session* session = FindSession(user);
if (session != NULL) {
// Forward request to user launch_daemon
if (session->Daemon().SendMessage(message) == B_OK)
return;
}
BMessage reply(B_NAME_NOT_FOUND);
message->SendReply(&reply);
return;
}
job->SetEnabled(true);
_LaunchJob(job, FORCE_NOW);
BMessage reply((uint32)B_OK);
message->SendReply(&reply);
}
void
LaunchDaemon::_HandleStopLaunchJob(BMessage* message)
{
uid_t user = _GetUserID(message);
if (user < 0)
return;
const char* name = message->GetString("name");
Job* job = FindJob(name);
if (job == NULL) {
Session* session = FindSession(user);
if (session != NULL) {
// Forward request to user launch_daemon
if (session->Daemon().SendMessage(message) == B_OK)
return;
}
BMessage reply(B_NAME_NOT_FOUND);
message->SendReply(&reply);
return;
}
_StopJob(job, message->GetBool("force"));
BMessage reply((uint32)B_OK);
message->SendReply(&reply);
}
void
LaunchDaemon::_HandleLaunchSession(BMessage* message)
{
@@ -1315,6 +1381,33 @@ LaunchDaemon::_LaunchJob(Job* job, uint32 options)
}
void
LaunchDaemon::_StopJob(Job* job, bool force)
{
// TODO: find out which jobs require this job, and don't stop if any,
// unless force, and then stop them all.
job->SetEnabled(false);
if (!job->IsRunning())
return;
// Be nice first, and send a simple quit message
BMessenger messenger;
if (job->GetMessenger(messenger) == B_OK) {
BMessage request(B_QUIT_REQUESTED);
messenger.SendMessage(&request);
// TODO: wait a bit before going further
return;
}
// TODO: allow custom shutdown
send_signal(-job->Team(), SIGINT);
// TODO: this would be the next step, again, after a delay
//send_signal(job->Team(), SIGKILL);
}
void
LaunchDaemon::_AddTarget(Target* target)
{