launch_daemon: Monitor teams, and restart services.
* Services that end are now automatically restarted. * However, this is very basic at the moment, there is no throttling, and no support for shutting down the system.
This commit is contained in:
parent
d8c0972a81
commit
e2f83cbd6b
@ -81,6 +81,20 @@ Job::~Job()
|
||||
}
|
||||
|
||||
|
||||
::TeamRegistrator*
|
||||
Job::TeamRegistrator() const
|
||||
{
|
||||
return fTeamRegistrator;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Job::SetTeamRegistrator(::TeamRegistrator* registrator)
|
||||
{
|
||||
fTeamRegistrator = registrator;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
Job::IsEnabled() const
|
||||
{
|
||||
@ -349,8 +363,24 @@ Job::IsLaunched() const
|
||||
bool
|
||||
Job::IsRunning() const
|
||||
{
|
||||
// TODO: monitor team status; should jobs be allowed to run multiple times?
|
||||
return State() == B_JOB_STATE_SUCCEEDED && IsLaunched() && IsService();
|
||||
return fTeam >= 0;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Job::TeamDeleted()
|
||||
{
|
||||
fTeam = -1;
|
||||
if (IsService())
|
||||
SetState(B_JOB_STATE_WAITING_TO_RUN);
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
Job::CanBeLaunched() const
|
||||
{
|
||||
// Services cannot be launched while they are running
|
||||
return !IsLaunching() && (!IsService() || !IsRunning());
|
||||
}
|
||||
|
||||
|
||||
@ -384,7 +414,7 @@ Job::Run()
|
||||
{
|
||||
status_t status = BJob::Run();
|
||||
|
||||
// TODO: monitor team, don't just do this
|
||||
// Jobs can be relaunched at any time
|
||||
if (!IsService())
|
||||
SetState(B_JOB_STATE_WAITING_TO_RUN);
|
||||
|
||||
@ -396,8 +426,10 @@ status_t
|
||||
Job::Execute()
|
||||
{
|
||||
status_t status = B_OK;
|
||||
if (!IsLaunched() || !IsService())
|
||||
if (!IsRunning() || !IsService())
|
||||
status = Launch();
|
||||
else
|
||||
debug_printf("Ignore launching %s\n", Name());
|
||||
|
||||
fLaunching = false;
|
||||
return status;
|
||||
@ -460,6 +492,9 @@ Job::_SetLaunchStatus(status_t launchStatus)
|
||||
fLaunchStatus = launchStatus != B_NO_INIT ? launchStatus : B_ERROR;
|
||||
launchLocker.Unlock();
|
||||
|
||||
if (fTeamRegistrator != NULL)
|
||||
fTeamRegistrator->RegisterTeam(this);
|
||||
|
||||
_SendPendingLaunchDataReplies();
|
||||
}
|
||||
|
||||
|
@ -22,6 +22,7 @@ using namespace BSupportKit;
|
||||
class BMessage;
|
||||
|
||||
class Finder;
|
||||
class Job;
|
||||
class Target;
|
||||
|
||||
struct entry_ref;
|
||||
@ -30,12 +31,22 @@ struct entry_ref;
|
||||
typedef std::map<BString, BMessage> PortMap;
|
||||
|
||||
|
||||
class TeamRegistrator {
|
||||
public:
|
||||
virtual void RegisterTeam(Job* job) = 0;
|
||||
};
|
||||
|
||||
|
||||
class Job : public BaseJob {
|
||||
public:
|
||||
Job(const char* name);
|
||||
Job(const Job& other);
|
||||
virtual ~Job();
|
||||
|
||||
::TeamRegistrator* TeamRegistrator() const;
|
||||
void SetTeamRegistrator(
|
||||
::TeamRegistrator* registrator);
|
||||
|
||||
bool IsEnabled() const;
|
||||
void SetEnabled(bool enable);
|
||||
|
||||
@ -72,6 +83,8 @@ public:
|
||||
status_t Launch();
|
||||
bool IsLaunched() const;
|
||||
bool IsRunning() const;
|
||||
void TeamDeleted();
|
||||
bool CanBeLaunched() const;
|
||||
|
||||
bool IsLaunching() const;
|
||||
void SetLaunching(bool launching);
|
||||
@ -117,6 +130,7 @@ private:
|
||||
::Condition* fCondition;
|
||||
BObjectList<BMessage>
|
||||
fPendingLaunchDataReplies;
|
||||
::TeamRegistrator* fTeamRegistrator;
|
||||
};
|
||||
|
||||
|
||||
|
@ -27,8 +27,11 @@
|
||||
#include <AppMisc.h>
|
||||
#include <LaunchDaemonDefs.h>
|
||||
#include <LaunchRosterPrivate.h>
|
||||
#include <locks.h>
|
||||
#include <MessengerPrivate.h>
|
||||
#include <RosterPrivate.h>
|
||||
#include <syscalls.h>
|
||||
#include <system_info.h>
|
||||
|
||||
#include "multiuser_utils.h"
|
||||
|
||||
@ -116,10 +119,11 @@ typedef std::map<BString, Job*> JobMap;
|
||||
typedef std::map<uid_t, Session*> SessionMap;
|
||||
typedef std::map<BString, Target*> TargetMap;
|
||||
typedef std::map<BString, ExternalEventSource*> EventMap;
|
||||
typedef std::map<team_id, Job*> TeamMap;
|
||||
|
||||
|
||||
class LaunchDaemon : public BServer, public Finder, public ConditionContext,
|
||||
public EventRegistrator {
|
||||
public EventRegistrator, public TeamRegistrator {
|
||||
public:
|
||||
LaunchDaemon(bool userMode,
|
||||
const EventMap& events, status_t& error);
|
||||
@ -140,6 +144,9 @@ public:
|
||||
virtual void UnregisterExternalEvent(Event* event,
|
||||
const char* name);
|
||||
|
||||
// TeamRegistrator
|
||||
virtual void RegisterTeam(Job* job);
|
||||
|
||||
virtual void ReadyToRun();
|
||||
virtual void MessageReceived(BMessage* message);
|
||||
|
||||
@ -208,6 +215,8 @@ private:
|
||||
SessionMap fSessions;
|
||||
MainWorker* fMainWorker;
|
||||
Target* fInitTarget;
|
||||
TeamMap fTeams;
|
||||
mutex fTeamsLock;
|
||||
bool fSafeMode;
|
||||
bool fReadOnlyBootVolume;
|
||||
bool fUserMode;
|
||||
@ -305,6 +314,8 @@ LaunchDaemon::LaunchDaemon(bool userMode, const EventMap& events,
|
||||
fInitTarget(userMode ? NULL : new Target("init")),
|
||||
fUserMode(userMode)
|
||||
{
|
||||
mutex_init(&fTeamsLock, "teams lock");
|
||||
|
||||
fMainWorker = new MainWorker(fJobQueue);
|
||||
fMainWorker->Init();
|
||||
|
||||
@ -391,6 +402,14 @@ LaunchDaemon::UnregisterExternalEvent(Event* event, const char* name)
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
LaunchDaemon::RegisterTeam(Job* job)
|
||||
{
|
||||
MutexLocker locker(fTeamsLock);
|
||||
fTeams.insert(std::make_pair(job->Team(), job));
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
LaunchDaemon::ReadyToRun()
|
||||
{
|
||||
@ -429,6 +448,12 @@ LaunchDaemon::ReadyToRun()
|
||||
fUserMode ? B_FIND_PATHS_USER_ONLY : B_FIND_PATHS_SYSTEM_ONLY, paths);
|
||||
_ReadPaths(paths);
|
||||
|
||||
BMessenger target(this);
|
||||
BMessenger::Private messengerPrivate(target);
|
||||
port_id port = messengerPrivate.Port();
|
||||
int32 token = messengerPrivate.Token();
|
||||
__start_watching_system(-1, B_WATCH_SYSTEM_TEAM_DELETION, port, token);
|
||||
|
||||
_InitJobs(NULL);
|
||||
_LaunchJobs(NULL);
|
||||
|
||||
@ -445,6 +470,30 @@ void
|
||||
LaunchDaemon::MessageReceived(BMessage* message)
|
||||
{
|
||||
switch (message->what) {
|
||||
case B_SYSTEM_OBJECT_UPDATE:
|
||||
{
|
||||
int32 opcode = message->GetInt32("opcode", 0);
|
||||
team_id team = (team_id)message->GetInt32("team", -1);
|
||||
if (opcode != B_TEAM_DELETED || team < 0)
|
||||
break;
|
||||
|
||||
MutexLocker locker(fTeamsLock);
|
||||
|
||||
TeamMap::iterator found = fTeams.find(team);
|
||||
if (found != fTeams.end()) {
|
||||
Job* job = found->second;
|
||||
TRACE("Job %s ended!\n", job->Name());
|
||||
job->TeamDeleted();
|
||||
|
||||
if (job->IsService()) {
|
||||
// TODO: take restart throttle into account
|
||||
// TODO: don't restart on shutdown
|
||||
_LaunchJob(job);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case B_GET_LAUNCH_DATA:
|
||||
_HandleGetLaunchData(message);
|
||||
break;
|
||||
@ -1112,6 +1161,7 @@ LaunchDaemon::_AddJob(Target* target, bool service, BMessage& message)
|
||||
if (job == NULL)
|
||||
return;
|
||||
|
||||
job->SetTeamRegistrator(this);
|
||||
job->SetService(service);
|
||||
job->SetCreateDefaultPort(service);
|
||||
job->SetTarget(target);
|
||||
@ -1232,7 +1282,7 @@ LaunchDaemon::_LaunchJobs(Target* target, bool forceNow)
|
||||
void
|
||||
LaunchDaemon::_LaunchJob(Job* job, uint32 options)
|
||||
{
|
||||
if (job == NULL || job->IsLaunching() || job->IsRunning()
|
||||
if (job == NULL || !job->CanBeLaunched()
|
||||
|| ((options & FORCE_NOW) == 0
|
||||
&& (!job->EventHasTriggered() || !job->CheckCondition(*this)
|
||||
|| ((options & TRIGGER_DEMAND) != 0
|
||||
@ -1256,7 +1306,12 @@ LaunchDaemon::_LaunchJob(Job* job, uint32 options)
|
||||
job->Event()->ResetTrigger();
|
||||
|
||||
job->SetLaunching(true);
|
||||
fJobQueue.AddJob(job);
|
||||
|
||||
status_t status = fJobQueue.AddJob(job);
|
||||
if (status != B_OK) {
|
||||
debug_printf("Adding job %s to queue failed: %s\n", job->Name(),
|
||||
strerror(status));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1532,7 +1587,11 @@ LaunchDaemon::_AddInitJob(BJob* job)
|
||||
static void
|
||||
open_stdio(int targetFD, int openMode)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
int fd = open("/dev/dprintf", openMode);
|
||||
#else
|
||||
int fd = open("/dev/null", openMode);
|
||||
#endif
|
||||
if (fd != targetFD) {
|
||||
dup2(fd, targetFD);
|
||||
close(fd);
|
||||
|
Loading…
Reference in New Issue
Block a user