From 852e09d61f14e1269bda4c119b8729ea20e5303d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Axel=20D=C3=B6rfler?= Date: Tue, 29 Nov 2016 23:14:36 +0100 Subject: [PATCH] launch_daemon: Added stop target ability. * Before, you had to stop each job by itself. --- headers/private/app/LaunchDaemonDefs.h | 1 + headers/private/app/LaunchRoster.h | 2 + src/kits/app/LaunchRoster.cpp | 19 +++++++++ src/servers/launch/LaunchDaemon.cpp | 56 ++++++++++++++++++++++++++ 4 files changed, 78 insertions(+) diff --git a/headers/private/app/LaunchDaemonDefs.h b/headers/private/app/LaunchDaemonDefs.h index 78980a819c..ea2f6cff41 100644 --- a/headers/private/app/LaunchDaemonDefs.h +++ b/headers/private/app/LaunchDaemonDefs.h @@ -26,6 +26,7 @@ namespace BPrivate { enum { B_GET_LAUNCH_DATA = 'lnda', B_LAUNCH_TARGET = 'lntg', + B_STOP_LAUNCH_TARGET = 'lnst', B_LAUNCH_JOB = 'lnjo', B_ENABLE_LAUNCH_JOB = 'lnje', B_STOP_LAUNCH_JOB = 'lnsj', diff --git a/headers/private/app/LaunchRoster.h b/headers/private/app/LaunchRoster.h index 9b2459518b..93b6bd2a0f 100644 --- a/headers/private/app/LaunchRoster.h +++ b/headers/private/app/LaunchRoster.h @@ -33,6 +33,8 @@ public: status_t Target(const char* name, const BMessage* data = NULL, const char* baseName = NULL); + status_t StopTarget(const char* name, + bool force = false); status_t Start(const char* name); status_t Stop(const char* name, bool force = false); diff --git a/src/kits/app/LaunchRoster.cpp b/src/kits/app/LaunchRoster.cpp index 4f887cdfe8..e8fcc16c3a 100644 --- a/src/kits/app/LaunchRoster.cpp +++ b/src/kits/app/LaunchRoster.cpp @@ -166,6 +166,25 @@ BLaunchRoster::Target(const char* name, const BMessage* data, } +status_t +BLaunchRoster::StopTarget(const char* name, bool force) +{ + if (name == NULL) + return B_BAD_VALUE; + + BMessage request(B_STOP_LAUNCH_TARGET); + status_t status = request.AddInt32("user", getuid()); + if (status == B_OK) + status = request.AddString("target", name); + if (status == B_OK) + status = request.AddBool("force", force); + if (status != B_OK) + return status; + + return _SendRequest(request); +} + + status_t BLaunchRoster::Start(const char* name) { diff --git a/src/servers/launch/LaunchDaemon.cpp b/src/servers/launch/LaunchDaemon.cpp index 17a0ec8ddd..736b4715b8 100644 --- a/src/servers/launch/LaunchDaemon.cpp +++ b/src/servers/launch/LaunchDaemon.cpp @@ -153,6 +153,7 @@ public: private: void _HandleGetLaunchData(BMessage* message); void _HandleLaunchTarget(BMessage* message); + void _HandleStopLaunchTarget(BMessage* message); void _HandleLaunchJob(BMessage* message); void _HandleEnableLaunchJob(BMessage* message); void _HandleStopLaunchJob(BMessage* message); @@ -185,6 +186,7 @@ private: void _InitJobs(Target* target); void _LaunchJobs(Target* target, bool forceNow = false); + void _StopJobs(Target* target, bool force); bool _CanLaunchJob(Job* job, uint32 options, bool testOnly = false); bool _CanLaunchJobRequirements(Job* job, @@ -553,6 +555,9 @@ LaunchDaemon::MessageReceived(BMessage* message) case B_LAUNCH_TARGET: _HandleLaunchTarget(message); break; + case B_STOP_LAUNCH_TARGET: + _HandleStopLaunchTarget(message); + break; case B_LAUNCH_JOB: _HandleLaunchJob(message); break; @@ -741,6 +746,40 @@ LaunchDaemon::_HandleLaunchTarget(BMessage* message) } +void +LaunchDaemon::_HandleStopLaunchTarget(BMessage* message) +{ + uid_t user = _GetUserID(message); + if (user < 0) + return; + + const char* name = message->GetString("target"); + + Target* target = FindTarget(name); + if (target == 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; + } + + BMessage data; + if (message->FindMessage("data", &data) == B_OK) + target->AddData(data.GetString("name"), data); + + _StopJobs(target, message->GetBool("force")); + + BMessage reply((uint32)B_OK); + message->SendReply(&reply); +} + + void LaunchDaemon::_HandleLaunchJob(BMessage* message) { @@ -1470,6 +1509,23 @@ LaunchDaemon::_LaunchJobs(Target* target, bool forceNow) } +/*! Stops all running jobs of the specified target (may be \c NULL). +*/ +void +LaunchDaemon::_StopJobs(Target* target, bool force) +{ + if (target != NULL && !target->HasLaunched()) + return; + + for (JobMap::reverse_iterator iterator = fJobs.rbegin(); + iterator != fJobs.rend(); iterator++) { + Job* job = iterator->second; + if (job->Target() == target) + _StopJob(job, force); + } +} + + /*! Checks whether or not the specified \a job can be launched. If \a testOnly is \c false, calling this method will trigger a demand to the \a job.