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:
@@ -26,6 +26,8 @@ namespace BPrivate {
|
|||||||
enum {
|
enum {
|
||||||
B_GET_LAUNCH_DATA = 'lnda',
|
B_GET_LAUNCH_DATA = 'lnda',
|
||||||
B_LAUNCH_TARGET = 'lntg',
|
B_LAUNCH_TARGET = 'lntg',
|
||||||
|
B_LAUNCH_JOB = 'lnjo',
|
||||||
|
B_STOP_LAUNCH_JOB = 'lnsj',
|
||||||
B_LAUNCH_SESSION = 'lnse',
|
B_LAUNCH_SESSION = 'lnse',
|
||||||
B_REGISTER_SESSION_DAEMON = 'lnrs',
|
B_REGISTER_SESSION_DAEMON = 'lnrs',
|
||||||
B_REGISTER_LAUNCH_EVENT = 'lnre',
|
B_REGISTER_LAUNCH_EVENT = 'lnre',
|
||||||
|
|||||||
@@ -34,6 +34,9 @@ public:
|
|||||||
const BMessage* data = NULL,
|
const BMessage* data = NULL,
|
||||||
const char* baseName = 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 StartSession(const char* login);
|
||||||
|
|
||||||
status_t RegisterEvent(const BMessenger& source,
|
status_t RegisterEvent(const BMessenger& source,
|
||||||
@@ -56,6 +59,9 @@ private:
|
|||||||
friend class Private;
|
friend class Private;
|
||||||
|
|
||||||
void _InitMessenger();
|
void _InitMessenger();
|
||||||
|
status_t _SendRequest(BMessage& request);
|
||||||
|
status_t _SendRequest(BMessage& request,
|
||||||
|
BMessage& reply);
|
||||||
status_t _UpdateEvent(uint32 what,
|
status_t _UpdateEvent(uint32 what,
|
||||||
const BMessenger& source, const char* name,
|
const BMessenger& source, const char* name,
|
||||||
uint32 flags = 0);
|
uint32 flags = 0);
|
||||||
|
|||||||
@@ -102,14 +102,7 @@ BLaunchRoster::GetData(const char* signature, BMessage& data)
|
|||||||
if (status != B_OK)
|
if (status != B_OK)
|
||||||
return status;
|
return status;
|
||||||
|
|
||||||
// send the request
|
return _SendRequest(request, data);
|
||||||
status = fMessenger.SendMessage(&request, &data);
|
|
||||||
|
|
||||||
// evaluate the reply
|
|
||||||
if (status == B_OK)
|
|
||||||
status = data.what;
|
|
||||||
|
|
||||||
return status;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -169,15 +162,43 @@ BLaunchRoster::Target(const char* name, const BMessage* data,
|
|||||||
if (status != B_OK)
|
if (status != B_OK)
|
||||||
return status;
|
return status;
|
||||||
|
|
||||||
// send the request
|
return _SendRequest(request);
|
||||||
BMessage result;
|
}
|
||||||
status = fMessenger.SendMessage(&request, &result);
|
|
||||||
|
|
||||||
// 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)
|
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)
|
if (status != B_OK)
|
||||||
return status;
|
return status;
|
||||||
|
|
||||||
// send the request
|
return _SendRequest(request);
|
||||||
BMessage result;
|
|
||||||
status = fMessenger.SendMessage(&request, &result);
|
|
||||||
|
|
||||||
// evaluate the reply
|
|
||||||
if (status == B_OK)
|
|
||||||
status = result.what;
|
|
||||||
|
|
||||||
return status;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -245,12 +258,7 @@ BLaunchRoster::GetTargets(BStringList& targets)
|
|||||||
|
|
||||||
// send the request
|
// send the request
|
||||||
BMessage result;
|
BMessage result;
|
||||||
status = fMessenger.SendMessage(&request, &result);
|
status = _SendRequest(request, result);
|
||||||
|
|
||||||
// evaluate the reply
|
|
||||||
if (status == B_OK)
|
|
||||||
status = result.what;
|
|
||||||
|
|
||||||
if (status == B_OK)
|
if (status == B_OK)
|
||||||
status = result.FindStrings("target", &targets);
|
status = result.FindStrings("target", &targets);
|
||||||
|
|
||||||
@@ -277,12 +285,7 @@ BLaunchRoster::GetJobs(const char* target, BStringList& jobs)
|
|||||||
|
|
||||||
// send the request
|
// send the request
|
||||||
BMessage result;
|
BMessage result;
|
||||||
status = fMessenger.SendMessage(&request, &result);
|
status = _SendRequest(request, result);
|
||||||
|
|
||||||
// evaluate the reply
|
|
||||||
if (status == B_OK)
|
|
||||||
status = result.what;
|
|
||||||
|
|
||||||
if (status == B_OK)
|
if (status == B_OK)
|
||||||
status = result.FindStrings("job", &jobs);
|
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
|
status_t
|
||||||
BLaunchRoster::_UpdateEvent(uint32 what, const BMessenger& source,
|
BLaunchRoster::_UpdateEvent(uint32 what, const BMessenger& source,
|
||||||
const char* name, uint32 flags)
|
const char* name, uint32 flags)
|
||||||
@@ -330,15 +353,7 @@ BLaunchRoster::_UpdateEvent(uint32 what, const BMessenger& source,
|
|||||||
if (status != B_OK)
|
if (status != B_OK)
|
||||||
return status;
|
return status;
|
||||||
|
|
||||||
// send the request
|
return _SendRequest(request);
|
||||||
BMessage result;
|
|
||||||
status = fMessenger.SendMessage(&request, &result);
|
|
||||||
|
|
||||||
// evaluate the reply
|
|
||||||
if (status == B_OK)
|
|
||||||
status = result.what;
|
|
||||||
|
|
||||||
return status;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -355,13 +370,5 @@ BLaunchRoster::_GetInfo(uint32 what, const char* name, BMessage& info)
|
|||||||
if (status != B_OK)
|
if (status != B_OK)
|
||||||
return status;
|
return status;
|
||||||
|
|
||||||
// send the request
|
return _SendRequest(request, info);
|
||||||
BMessage result;
|
|
||||||
status = fMessenger.SendMessage(&request, &info);
|
|
||||||
|
|
||||||
// evaluate the reply
|
|
||||||
if (status == B_OK)
|
|
||||||
status = result.what;
|
|
||||||
|
|
||||||
return status;
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,6 +13,7 @@
|
|||||||
#include <Message.h>
|
#include <Message.h>
|
||||||
#include <Roster.h>
|
#include <Roster.h>
|
||||||
|
|
||||||
|
#include <MessagePrivate.h>
|
||||||
#include <RosterPrivate.h>
|
#include <RosterPrivate.h>
|
||||||
#include <user_group.h>
|
#include <user_group.h>
|
||||||
|
|
||||||
@@ -43,6 +44,7 @@ Job::Job(const Job& other)
|
|||||||
fEnabled(other.IsEnabled()),
|
fEnabled(other.IsEnabled()),
|
||||||
fService(other.IsService()),
|
fService(other.IsService()),
|
||||||
fCreateDefaultPort(other.CreateDefaultPort()),
|
fCreateDefaultPort(other.CreateDefaultPort()),
|
||||||
|
fLaunching(other.IsLaunching()),
|
||||||
fInitStatus(B_NO_INIT),
|
fInitStatus(B_NO_INIT),
|
||||||
fTeam(-1),
|
fTeam(-1),
|
||||||
fLaunchStatus(B_NO_INIT),
|
fLaunchStatus(B_NO_INIT),
|
||||||
@@ -380,7 +382,7 @@ bool
|
|||||||
Job::CanBeLaunched() const
|
Job::CanBeLaunched() const
|
||||||
{
|
{
|
||||||
// Services cannot be launched while they are running
|
// 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
|
status_t
|
||||||
Job::Run()
|
Job::Run()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -20,6 +20,7 @@
|
|||||||
|
|
||||||
using namespace BSupportKit;
|
using namespace BSupportKit;
|
||||||
class BMessage;
|
class BMessage;
|
||||||
|
class BMessenger;
|
||||||
|
|
||||||
class Finder;
|
class Finder;
|
||||||
class Job;
|
class Job;
|
||||||
@@ -90,6 +91,7 @@ public:
|
|||||||
void SetLaunching(bool launching);
|
void SetLaunching(bool launching);
|
||||||
|
|
||||||
status_t HandleGetLaunchData(BMessage* message);
|
status_t HandleGetLaunchData(BMessage* message);
|
||||||
|
status_t GetMessenger(BMessenger& messenger);
|
||||||
|
|
||||||
virtual status_t Run();
|
virtual status_t Run();
|
||||||
|
|
||||||
|
|||||||
@@ -153,6 +153,8 @@ public:
|
|||||||
private:
|
private:
|
||||||
void _HandleGetLaunchData(BMessage* message);
|
void _HandleGetLaunchData(BMessage* message);
|
||||||
void _HandleLaunchTarget(BMessage* message);
|
void _HandleLaunchTarget(BMessage* message);
|
||||||
|
void _HandleLaunchJob(BMessage* message);
|
||||||
|
void _HandleStopLaunchJob(BMessage* message);
|
||||||
void _HandleLaunchSession(BMessage* message);
|
void _HandleLaunchSession(BMessage* message);
|
||||||
void _HandleRegisterSessionDaemon(BMessage* message);
|
void _HandleRegisterSessionDaemon(BMessage* message);
|
||||||
void _HandleRegisterLaunchEvent(BMessage* message);
|
void _HandleRegisterLaunchEvent(BMessage* message);
|
||||||
@@ -179,6 +181,7 @@ private:
|
|||||||
void _LaunchJobs(Target* target,
|
void _LaunchJobs(Target* target,
|
||||||
bool forceNow = false);
|
bool forceNow = false);
|
||||||
void _LaunchJob(Job* job, uint32 options = 0);
|
void _LaunchJob(Job* job, uint32 options = 0);
|
||||||
|
void _StopJob(Job* job, bool force);
|
||||||
void _AddTarget(Target* target);
|
void _AddTarget(Target* target);
|
||||||
void _SetCondition(BaseJob* job,
|
void _SetCondition(BaseJob* job,
|
||||||
const BMessage& message);
|
const BMessage& message);
|
||||||
@@ -501,11 +504,16 @@ LaunchDaemon::MessageReceived(BMessage* message)
|
|||||||
case B_LAUNCH_TARGET:
|
case B_LAUNCH_TARGET:
|
||||||
_HandleLaunchTarget(message);
|
_HandleLaunchTarget(message);
|
||||||
break;
|
break;
|
||||||
|
case B_LAUNCH_JOB:
|
||||||
|
_HandleLaunchJob(message);
|
||||||
|
break;
|
||||||
|
case B_STOP_LAUNCH_JOB:
|
||||||
|
_HandleStopLaunchJob(message);
|
||||||
|
break;
|
||||||
|
|
||||||
case B_LAUNCH_SESSION:
|
case B_LAUNCH_SESSION:
|
||||||
_HandleLaunchSession(message);
|
_HandleLaunchSession(message);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case B_REGISTER_SESSION_DAEMON:
|
case B_REGISTER_SESSION_DAEMON:
|
||||||
_HandleRegisterSessionDaemon(message);
|
_HandleRegisterSessionDaemon(message);
|
||||||
break;
|
break;
|
||||||
@@ -513,15 +521,12 @@ LaunchDaemon::MessageReceived(BMessage* message)
|
|||||||
case B_REGISTER_LAUNCH_EVENT:
|
case B_REGISTER_LAUNCH_EVENT:
|
||||||
_HandleRegisterLaunchEvent(message);
|
_HandleRegisterLaunchEvent(message);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case B_UNREGISTER_LAUNCH_EVENT:
|
case B_UNREGISTER_LAUNCH_EVENT:
|
||||||
_HandleUnregisterLaunchEvent(message);
|
_HandleUnregisterLaunchEvent(message);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case B_NOTIFY_LAUNCH_EVENT:
|
case B_NOTIFY_LAUNCH_EVENT:
|
||||||
_HandleNotifyLaunchEvent(message);
|
_HandleNotifyLaunchEvent(message);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case B_RESET_STICKY_LAUNCH_EVENT:
|
case B_RESET_STICKY_LAUNCH_EVENT:
|
||||||
_HandleResetStickyLaunchEvent(message);
|
_HandleResetStickyLaunchEvent(message);
|
||||||
break;
|
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
|
void
|
||||||
LaunchDaemon::_HandleLaunchSession(BMessage* message)
|
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
|
void
|
||||||
LaunchDaemon::_AddTarget(Target* target)
|
LaunchDaemon::_AddTarget(Target* target)
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user