Skip to content

Commit e8e6d2a

Browse files
committed
Code to kill child process
1 parent 7cf1de5 commit e8e6d2a

2 files changed

Lines changed: 85 additions & 16 deletions

File tree

Launcher.cpp

Lines changed: 42 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -59,9 +59,9 @@ SERVICE_REGISTRATION(Launcher, 1, 0);
5959
ASSERT(_activity.IsValid() == true);
6060

6161
_memory->Observe(0);
62-
_observer.Unregister(&_notification);
6362

6463
_activity->Shutdown();
64+
_observer.Unregister(&_notification);
6565
_activity.Release();
6666

6767
_memory->Release();
@@ -84,21 +84,47 @@ void Launcher::Update(const ProcessObserver::Info& info)
8484

8585
// This can potentially be called on a socket thread, so the deactivation (wich in turn kills this object) must be done
8686
// on a seperate thread. Also make sure this call-stack can be unwound before we are totally destructed.
87-
if ( (_activity->Pid() == info.Id()) && (info.Event() == ProcessObserver::Info::EVENT_EXIT) ) {
88-
89-
_memory->Observe(0);
90-
uint32_t result = _activity->ExitCode();
91-
92-
if (result != Core::ERROR_NONE) {
93-
SYSLOG(Trace::Fatal, (_T("FORCED Shutdown: %s by error: %d."), _service->Callsign().c_str(), result));
94-
PluginHost::WorkerPool::Instance().Submit(PluginHost::IShell::Job::Create(_service, PluginHost::IShell::DEACTIVATED, PluginHost::IShell::FAILURE));
95-
}
96-
else if (_activity->Continuous() == false) {
97-
TRACE(Trace::Information, (_T("Launcher [%s] has run succesfully, deactivation requested."), _service->Callsign().c_str()));
98-
PluginHost::WorkerPool::Instance().Submit(PluginHost::IShell::Job::Create(_service, PluginHost::IShell::DEACTIVATED, PluginHost::IShell::AUTOMATIC));
87+
if (_activity->HasPid(info.Id()) == true) {
88+
89+
switch (info.Event()) {
90+
case ProcessObserver::Info::EVENT_FORK:
91+
TRACE(Trace::Information, (_T("FORK: parent tid=%d pid=%d -> child tid=%d pid=%d\n"), info.Id(), info.Group(), info.ChildId(), info.ChildGroup()));
92+
if (_activity->ShutdownInProgress() == false) {
93+
_activity->AddPid(info.ChildId());
94+
} else {
95+
_activity->Kill(info.ChildId());
96+
}
97+
break;
98+
case ProcessObserver::Info::EVENT_EXEC:
99+
TRACE(Trace::Information, (_T("EXEC: tid=%d pid=%d\n"), info.Id(), info.Group()));
100+
break;
101+
case ProcessObserver::Info::EVENT_EXIT:
102+
{
103+
if (_activity->Pid() == info.Id()) {
104+
_memory->Observe(0);
105+
uint32_t result = _activity->ExitCode();
106+
107+
if (result != Core::ERROR_NONE) {
108+
SYSLOG(Trace::Fatal, (_T("FORCED Shutdown: %s by error: %d."), _service->Callsign().c_str(), result));
109+
if (_activity->ShutdownInProgress() == false) {
110+
PluginHost::WorkerPool::Instance().Submit(PluginHost::IShell::Job::Create(_service, PluginHost::IShell::DEACTIVATED, PluginHost::IShell::FAILURE));
111+
}
112+
}
113+
else if (_activity->Continuous() == false) {
114+
TRACE(Trace::Information, (_T("Launcher [%s] has run succesfully, deactivation requested."), _service->Callsign().c_str()));
115+
PluginHost::WorkerPool::Instance().Submit(PluginHost::IShell::Job::Create(_service, PluginHost::IShell::DEACTIVATED, PluginHost::IShell::AUTOMATIC));
116+
}
117+
else {
118+
TRACE(Trace::Information, (_T("Launcher [%s] has run succesfully, scheduled for the next run."), _service->Callsign().c_str()));
119+
}
120+
} else {
121+
_activity->RemovePid(info.Id());
122+
}
123+
break;
99124
}
100-
else {
101-
TRACE(Trace::Information, (_T("Launcher [%s] has run succesfully, scheduled for the next run."), _service->Callsign().c_str()));
125+
default:
126+
printf("unhandled proc event\n");
127+
break;
102128
}
103129
}
104130
}
@@ -125,6 +151,7 @@ bool Launcher::ScheduleParameters(const Config& config, string& message, Core::T
125151
}
126152
else if ( (timeMode == ABSOLUTE_WITH_INTERVAL) && ((interval.IsValid() == false) || (interval.TimeInSeconds() == 0)) ) {
127153
message = _T("Requested mode is ABSOLUTE WITH INTERVAL but no interval (or 0 second interval) is given.");
154+
128155
}
129156
else {
130157
// All signals green, we have valid input, calculate the ScheduleTime/Interval time

Launcher.h

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
#include "Module.h"
44
#include <interfaces/IMemory.h>
55
#include <linux/cn_proc.h>
6+
#include <vector>
67

78
namespace WPEFramework {
89
namespace Plugin {
@@ -544,6 +545,8 @@ class Launcher : public PluginHost::IPlugin {
544545
Job(const Job&) = delete;
545546
Job& operator=(const Job&) = delete;
546547

548+
typedef std::vector<uint32_t> ProcessList;
549+
547550
public:
548551
Job(Config* config, const Time& interval, Exchange::IMemory* memory)
549552
: _adminLock()
@@ -586,6 +589,41 @@ class Launcher : public PluginHost::IPlugin {
586589
uint32_t Pid() {
587590
return _pid;
588591
}
592+
bool ShutdownInProgress() {
593+
return _shutdownPhase;
594+
}
595+
void Kill(uint32_t pid) {
596+
::kill(pid, SIGKILL);
597+
}
598+
bool HasPid(uint32_t pid) {
599+
_adminLock.Lock();
600+
ProcessList::iterator position = std::find(_processList.begin(), _processList.end(), pid);
601+
_adminLock.Unlock();
602+
return (position != _processList.end());
603+
}
604+
void AddPid(uint32_t pid) {
605+
_adminLock.Lock();
606+
ASSERT(std::find(_processList.begin(), _processList.end(), pid) == _processList.end());
607+
_processList.push_back(pid);
608+
_adminLock.Unlock();
609+
}
610+
void RemovePid(uint32_t pid) {
611+
_adminLock.Lock();
612+
ProcessList::iterator position = std::find(_processList.begin(), _processList.end(), pid);
613+
if (position != _processList.end()) {
614+
_processList.erase(position);
615+
}
616+
_adminLock.Unlock();
617+
}
618+
void StopChilds() {
619+
_adminLock.Lock();
620+
ASSERT(!_processList.empty())
621+
for (int i = 1; i < _processList.size(); i++) {
622+
Kill(_processList[i];);
623+
}
624+
_processList.clear(); //Clear to ensure it is removed before doing the force shutdown
625+
_adminLock.Unlock();
626+
}
589627
void Schedule (const Core::Time& time) {
590628
if (time <= Core::Time::Now()) {
591629
PluginHost::WorkerPool::Instance().Submit(Core::ProxyType<Core::IDispatch>(*this));
@@ -599,7 +637,7 @@ class Launcher : public PluginHost::IPlugin {
599637
_shutdownPhase = 1;
600638
_adminLock.Unlock();
601639

602-
PluginHost::WorkerPool::Instance().Revoke(Core::ProxyType<Core::IDispatch>(*this));
640+
(PluginHost::WorkerPool::Instance().Revoke(Core::ProxyType<Core::IDispatch>(*this)));
603641

604642
if (_process.IsActive() == true) {
605643

@@ -608,9 +646,11 @@ class Launcher : public PluginHost::IPlugin {
608646

609647
// Wait for a maximum configured wait time before we shoot the process!!
610648
if (_process.WaitProcessCompleted(_closeTime * 1000) != Core::ERROR_NONE) {
649+
TRACE_L1("Trying to force kill\n");
611650
_process.Kill(true);
612651
_process.WaitProcessCompleted(1000);
613652
}
653+
StopChilds(); //Ensure all childs are exited before quiting
614654
}
615655
}
616656

@@ -624,6 +664,7 @@ class Launcher : public PluginHost::IPlugin {
624664
if (_process.IsActive() == false) {
625665

626666
_process.Launch(_options, &_pid);
667+
AddPid(_pid);
627668

628669
TRACE(Trace::Information, (_T("Launched command: %s [%d]."), _options.Command().c_str(), _pid));
629670
ASSERT (_memory != nullptr);
@@ -651,6 +692,7 @@ class Launcher : public PluginHost::IPlugin {
651692
Time _interval;
652693
uint8_t _closeTime;
653694
uint8_t _shutdownPhase;
695+
ProcessList _processList;
654696
};
655697

656698
public:

0 commit comments

Comments
 (0)