Add a new function for loader termination
[platform/core/appfw/launchpad.git] / src / launchpad-process-pool / launchpad.cc
1 /*
2  * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  * Licensed under the Apache License, Version 2.0 (the License);
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an AS IS BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #include "launchpad-process-pool/launchpad.hh"
18
19 #include <bundle_internal.h>
20 #include <errno.h>
21 #include <glib.h>
22 #include <security-manager.h>
23 #include <sys/prctl.h>
24 #include <systemd/sd-daemon.h>
25
26 #include <algorithm>
27 #include <string>
28 #include <utility>
29
30 #include <app_info.hh>
31 #include <aul_keys.hh>
32 #include <cpu_boost_controller.hh>
33 #include <exception.hh>
34 #include <executor.hh>
35 #include <procfs.hh>
36 #include <sched_priority.hh>
37 #include <types.hh>
38 #include <user_tracer.hh>
39 #include <util.hh>
40
41 #include "launchpad-process-pool/config.hh"
42 #include "launchpad-process-pool/dbus.hh"
43 #include "launchpad-process-pool/debug.hh"
44 #include "launchpad-process-pool/launcher_info.hh"
45 #include "launchpad-process-pool/launchpad_args.hh"
46 #include "launchpad-process-pool/loader_manager.hh"
47 #include "launchpad-process-pool/loader_executor.hh"
48 #include "launchpad-process-pool/log.hh"
49 #include "launchpad-process-pool/log_private.hh"
50 #include "launchpad-process-pool/memory_monitor.hh"
51 #include "launchpad-process-pool/signal_manager.hh"
52 #include "launchpad-process-pool/tracer.hh"
53 #include "launchpad-process-pool/util.hh"
54 #include "launchpad-process-pool/worker.hh"
55
56 namespace launchpad {
57 namespace {
58
59 constexpr const char kRunAulDaemonsPath[] = "/run/aul/daemons/";
60 constexpr const char kLaunchpadProcessPoolSock[] =
61     ".launchpad-process-pool-sock";
62 constexpr const char kInfoDirectoryPath[] = "/usr/share/aul";
63 const int kReceivedBufferSize = 131071;
64 const int kMaxPendingConnection = 128;
65 const uid_t kRegularUidMin = 5000;
66
67 class CleanupInfo : public launchpad::Worker::Job {
68  public:
69   CleanupInfo(std::string appid, pid_t pid)
70       : appid_(std::move(appid)), pid_(pid) {}
71
72   void Do() override {
73     _W("security_manager_cleanup_app() ++");
74     security_manager_cleanup_app(appid_.c_str(), getuid(), pid_);
75     _W("security_manager_cleanup_app() --");
76   }
77
78  private:
79   std::string appid_;
80   pid_t pid_;
81 };
82
83 int GetLaunchpadFdFromSystemd() {
84   const std::string path = kRunAulDaemonsPath + std::to_string(getuid()) +
85       "/" + std::string(kLaunchpadProcessPoolSock);
86   int fds = sd_listen_fds(0);
87   for (int fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + fds; ++fd) {
88     if (sd_is_socket_unix(fd, SOCK_STREAM, 1, path.c_str(), 0) > 0)
89       return fd;
90   }
91
92   _W("There is no socket stream");
93   return -1;
94 }
95
96 int GetLaunchpadFdFromEnvironment() {
97   auto* value = getenv("LAUNCHPAD_LISTEN_FD");
98   if (value == nullptr || !isdigit(value[0])) {
99     _E("Failed to get launchpad fd");
100     return -1;
101   }
102
103   _W("fd: %s", value);
104   return atoi(value);
105 }
106
107 ServerSocket* GetLaunchpadSocket() {
108   int fd = GetLaunchpadFdFromSystemd();
109   if (fd < 0)
110     fd = GetLaunchpadFdFromEnvironment();
111
112   if (fd > -1)
113     return new ServerSocket(fd);
114
115   auto* socket = new ServerSocket();
116   const std::string endpoint = kRunAulDaemonsPath + std::to_string(getuid()) +
117       "/" + kLaunchpadProcessPoolSock;
118   socket->Bind(endpoint);
119   socket->SetReceiveBufferSize(kReceivedBufferSize);
120   socket->Listen(kMaxPendingConnection);
121   return socket;
122 }
123
124 void PrintAppInfo(const AppInfo* app_info) {
125   SECURE_LOGD("appid: %s", app_info->GetAppId().c_str());
126   SECURE_LOGD("app_path: %s", app_info->GetAppPath().c_str());
127   SECURE_LOGD("comp_type: %s", app_info->GetCompType().c_str());
128   SECURE_LOGD("internal pool: %s", app_info->GetInternalPool().c_str());
129   SECURE_LOGD("hwacc: %s", app_info->GetHwacc().c_str());
130   SECURE_LOGD("app_type: %s", app_info->GetAppType().c_str());
131   SECURE_LOGD("pkg_type: %s", app_info->GetPkgType().c_str());
132 }
133
134 int CheckCallerPermission(pid_t caller_pid) {
135   std::string attr_current = Procfs::GetAttrCurrent(caller_pid);
136   if (attr_current.empty())
137     return -1;
138
139   if (attr_current.compare("User") == 0 ||
140       attr_current.compare("System") == 0 ||
141       attr_current.compare("System::Privileged") == 0)
142     return 0;
143
144   return -1;
145 }
146
147 int GetLoaderIdFromBundle(const tizen_base::Bundle& b) {
148   auto loader_id = b.GetString(kAulLoaderId);
149   if (loader_id.empty())
150     return -1;
151
152   _W("Requested loader id: %s", loader_id.c_str());
153   return std::stoi(loader_id);
154 }
155
156 }  // namespace
157
158 Launchpad::Launchpad(int argc, char** argv)
159     : argc_(argc),
160       argv_(argv),
161       loop_(g_main_loop_new(nullptr, FALSE)) {
162   LaunchpadArgs::GetInst().Set(argc_, argv_);
163   handlers_ = {
164     { PadCmd::Visibility,
165       std::bind(&Launchpad::HandleVisibilityRequest, this,
166           std::placeholders::_1) },
167     { PadCmd::AddLoader,
168       std::bind(&Launchpad::HandleAddLoaderRequest, this,
169           std::placeholders::_1) },
170     { PadCmd::RemoveLoader,
171       std::bind(&Launchpad::HandleRemoveLoaderRequest, this,
172           std::placeholders::_1) },
173     { PadCmd::MakeDefaultSlots,
174       std::bind(&Launchpad::HandleMakeDefaultSlotsRequest, this,
175           std::placeholders::_1) },
176     { PadCmd::PrepareAppDefinedLoader,
177       std::bind(&Launchpad::HandlePrepareAppDefinedLoaderRequest, this,
178           std::placeholders::_1) },
179     { PadCmd::Demand,
180       std::bind(&Launchpad::HandleDemandRequest, this,
181           std::placeholders::_1) },
182     { PadCmd::Ping,
183       std::bind(&Launchpad::HandlePingRequest, this,
184           std::placeholders::_1) },
185     { PadCmd::UpdateAppType,
186       std::bind(&Launchpad::HandleUpdateAppTypeRequest, this,
187           std::placeholders::_1) },
188     { PadCmd::Connect,
189       std::bind(&Launchpad::HandleConnectRequest, this,
190           std::placeholders::_1) },
191     { PadCmd::Launch,
192       std::bind(&Launchpad::HandleLaunchRequest, this,
193           std::placeholders::_1) },
194     { PadCmd::KillLoader,
195       std::bind(&Launchpad::HandleKillLoaderRequest, this,
196           std::placeholders::_1) },
197     { PadCmd::RestartLoader,
198       std::bind(&Launchpad::HandleRestartLoaderRequest, this,
199           std::placeholders::_1) },
200     { PadCmd::DisposeLoader,
201       std::bind(&Launchpad::HandleDisposeLoaderRequest, this,
202           std::placeholders::_1) },
203   };
204
205   CPUBoostController::Level level;
206   int ret = CPUBoostController::GetBoostLevel(getpid(), &level);
207   if (ret != 0)
208     CPUBoostController::Clear(getpid());
209
210   if (ret != 0 ||
211       level == CPUBoostController::Level::None ||
212       level == CPUBoostController::Level::Weak) {
213     CPUBoostController::DoBoost(getpid(), CPUBoostController::Level::Strong,
214         -1, true);
215   }
216
217   g_timeout_add(1000, [](gpointer data) {
218         CPUBoostController::Clear(getpid());
219         return G_SOURCE_REMOVE;
220       }, this);
221   mode_ = Config::GetInst().GetLaunchMode().GetMode();
222 }
223
224 Launchpad::~Launchpad() {
225   if (loop_ != nullptr)
226     g_main_loop_unref(loop_);
227 }
228
229 int Launchpad::Run() {
230   if (!OnCreate()) {
231     OnTerminate();
232     return -1;
233   }
234
235 #ifdef TIZEN_FEATURE_PRIORITY_CHANGE
236   _set_priority(-12);
237 #endif
238   UserTracer::Print(
239       std::string(__FUNCTION__) + "(" + std::to_string(__LINE__) +
240       "): g_main_loop_run()");
241   g_main_loop_run(loop_);
242   OnTerminate();
243   return 0;
244 }
245
246 void Launchpad::Quit() {
247   g_main_loop_quit(loop_);
248 }
249
250 bool Launchpad::OnCreate() {
251   UserTracer user_tracer(
252       std::string(__FUNCTION__) + "(" + std::to_string(__LINE__) + ")");
253   launchpad::SignalManager::GetInst().SetEventListener(this);
254
255   try {
256     app_executor_.reset(new AppExecutor());
257     socket_.reset(GetLaunchpadSocket());
258     channel_.reset(
259         new IOChannel(socket_->GetFd(), IOChannel::IOCondition::IO_IN, this));
260     channel_->SetCloseOnDestroy(false);
261   } catch (const Exception& e) {
262     _E("Exception occurs. error: %s", e.what());
263     return false;
264   }
265
266   cleaner_.reset(new Worker("cleaner+"));
267   DBus::Init();
268
269   LoaderManager::GetInst().AddDefaultLoaderContexts();
270   LoaderManager::GetInst().SetEventListener(this);
271   launchpad::Debug::GetInst().Init();
272
273   Util::SendCmdToAmd(AmdCmd::LaunchpadLaunchSignal);
274   lang_config_.reset(new LanguageConfig());
275   region_format_config_.reset(new RegionFormatConfig());
276
277   Log::Init();
278   return true;
279 }
280
281 void Launchpad::OnTerminate() {
282   Log::Finish();
283   region_format_config_.reset();
284   lang_config_.reset();
285
286   pid_map_.clear();
287   Util::SendCmdToAmd(AmdCmd::LaunchpadDeadSignal);
288   Debug::GetInst().Dispose();
289   DBus::Finish();
290   cleaner_.reset();
291
292   LoaderManager::GetInst().Dispose();
293   channel_.reset();
294   socket_.reset();
295   SignalManager::GetInst().Dispose();
296 }
297
298 void Launchpad::HandleVisibilityRequest(std::shared_ptr<Request> request) {
299   LoaderManager::GetInst().ActivateLoaderContexts(LoaderMethod::Visibility);
300   request->SendResult(0);
301   _W("[PAD_CMD_VISIBILITY]");
302 }
303
304 void Launchpad::HandleAddLoaderRequest(std::shared_ptr<Request> request) {
305   auto context = LoaderManager::GetInst().AddLoaderContext(
306       request->GetBundle());
307   if (context == nullptr) {
308     request->SendResult(-1);
309     _W("[PAD_CMD_ADD_LOADER] Can not add loader context");
310     return;
311   }
312
313   request->SendResult(context->GetLoaderId());
314   _W("[PAD_CMD_ADD_LOADER]");
315 }
316
317 void Launchpad::HandleRemoveLoaderRequest(std::shared_ptr<Request> request) {
318   auto& b = request->GetBundle();
319   auto loader_id_str = b.GetString(kAulLoaderId);
320   if (loader_id_str.empty()) {
321     _E("Failed to get loader id");
322     request->SendResult(-1);
323     return;
324   }
325
326   LoaderManager::GetInst().RemoveLoaderContext(LoaderType::Dynamic,
327       std::stoi(loader_id_str));
328   request->SendResult(0);
329   _W("[PAD_CMD_REMOVE_LOADER]");
330 }
331
332 void Launchpad::HandleMakeDefaultSlotsRequest(
333   std::shared_ptr<Request> request) {
334   LoaderManager::GetInst().AddDefaultLoaderContexts();
335   _W("[PAD_CMD_MAKE_DEFAULT_SLOTS]");
336 }
337
338 void Launchpad::HandlePrepareAppDefinedLoaderRequest(
339     std::shared_ptr<Request> request) {
340   auto& b = request->GetBundle();
341   auto loader_name = b.GetString(kAulLoaderName);
342   if (loader_name.empty()) {
343     _E("Failed to get loader name");
344     request->SendResult(-EINVAL);
345     return;
346   }
347
348   auto context = LoaderManager::GetInst().PrepareAppDefinedLoaderContext(
349       loader_name, request->GetCallerPid());
350   if (context == nullptr) {
351     request->SendResult(-EINVAL);
352     return;
353   }
354
355   request->SendResult(context->GetLoaderId());
356   _W("[PAD_CMD_PREPARE_APP_DEFINED_LOADER] result: %d", context->GetLoaderId());
357 }
358
359 void Launchpad::HandleDemandRequest(std::shared_ptr<Request> request) {
360   LoaderManager::GetInst().ActivateLoaderContexts(LoaderMethod::Demand);
361   request->SendResult(0);
362   _W("[PAD_CMD_DEMAND]");
363 }
364
365 void Launchpad::HandlePingRequest(std::shared_ptr<Request> request) {
366   request->SendResult(getpid());
367   _W("[PAD_CMD_PING]");
368 }
369
370 void Launchpad::HandleUpdateAppTypeRequest(std::shared_ptr<Request> request) {
371   auto& b = request->GetBundle();
372   auto app_type = b.GetString(kAulAppType);
373   if (app_type.empty()) {
374     _E("Failed to get app type");
375     return;
376   }
377
378   auto installed = b.GetString(kAulIsInstalled);
379   _I("type: %s, installed: %s", app_type.c_str(), installed.c_str());
380   bool app_installed = (installed == "true") ? true : false;
381   LoaderManager::GetInst().UpdateAppInstallationStatus(app_type, app_installed);
382   _W("[PAD_CMD_UPDATE_APP_TYPE]");
383 }
384
385 void Launchpad::HandleConnectRequest(std::shared_ptr<Request> request) {
386   client_socket_.reset(
387       new ClientSocket(request->GetClientSocket()->RemoveFd()));
388   _W("[PAD_CMD_CONNECT] client fd: %d", client_socket_->GetFd());
389 }
390
391 bool Launchpad::CanUseLoaderContext(
392     const std::shared_ptr<LoaderContext>& context) {
393   if (context->IsPrepared())
394     return true;
395
396   if (mode_ == Config::LaunchMode::Mode::PreviousOperation)
397     return false;
398
399   if (mode_ == Config::LaunchMode::Mode::DefaultOperation) {
400     if (context->IsHydraMode())
401       return true;
402
403     return context->GetPid() > 0 && context->RefCount() == 0;
404   }
405
406   // Config::LaunchMode::Mode::AlwaysLoader
407   // Config::LaunchMode::Mode::AlwaysLoaderWithoutCPUChecker
408   // Config::LaunchMode::Mode::AlwaysLoaderWithLowPriority
409   if (context->GetPid() > 0)
410     return true;
411
412   return context->IsLaunchable();
413 }
414
415 Launchpad::LaunchResult Launchpad::LaunchRequestPrepare(
416     std::shared_ptr<Request> request) {
417   auto* app_info = AppInfo::Create(request->GetBundle());
418   if (app_info == nullptr) {
419     _E("Failed to create AppInfo");
420     return LaunchResult::Fail;
421   }
422
423   request->SetAppInfo(std::unique_ptr<AppInfo>(app_info));
424   if (app_info->GetAppPath().empty()) {
425     _E("AppPath is empty");
426     return LaunchResult::Fail;
427   }
428
429   PrintAppInfo(app_info);
430
431   auto& loader_manager = LoaderManager::GetInst();
432   auto& comp_type = app_info->GetCompType();
433   if (comp_type == "svcapp") {
434     request->SetLoaderId(GetLoaderIdFromBundle(request->GetBundle()));
435     if (request->GetLoaderId() > PadLoaderId::DynamicBase) {
436       auto context = loader_manager.FindLoaderContext(LoaderType::Dynamic,
437           request->GetLoaderId());
438       if (context != nullptr && CanUseLoaderContext(context))
439         request->SetAvailableLoaderContext(std::move(context));
440     } else {
441       request->SetLoaderId(PadLoaderId::Direct);
442     }
443   } else if (comp_type == "widget" && app_info->GetAppType() == "webapp") {
444     request->SetLoaderId(PadLoaderId::Direct);
445   } else {
446     request->SetLoaderId(GetLoaderIdFromBundle(request->GetBundle()));
447     if (request->GetLoaderId() <= PadLoaderId::Static) {
448       auto context = loader_manager.FindAvailableLoaderContext(
449           app_info->GetHwacc(), app_info->GetAppType(),
450           app_info->GetLoaderName());
451       if (context != nullptr) {
452         request->SetLoaderContext(context);
453         if (CanUseLoaderContext(context)) {
454           request->SetAvailableLoaderContext(std::move(context));
455         } else {
456           auto alt_context = loader_manager.FindAlternativeLoaderContext(
457               static_cast<LoaderType>(context->GetType()));
458           if (alt_context != nullptr && CanUseLoaderContext(alt_context))
459             request->SetAvailableLoaderContext(std::move(alt_context));
460         }
461       }
462     } else {
463       auto context = loader_manager.FindLoaderContext(LoaderType::Dynamic,
464           request->GetLoaderId());
465       if (context != nullptr && CanUseLoaderContext(context))
466         request->SetAvailableLoaderContext(std::move(context));
467     }
468   }
469
470   return LaunchResult::Success;
471 }
472
473 Launchpad::LaunchResult Launchpad::ForkProcessing(
474     std::shared_ptr<Request> request) {
475   if (request->GetBundle().GetType(kAulSdk) != BUNDLE_TYPE_NONE) {
476     if (Debug::GetInst().Load())
477       app_executor_->DisposeCandidateProcess();
478   }
479
480   _W("appid: %s", request->GetAppInfo()->GetAppId().c_str());
481   request->SetPid(app_executor_->Execute(request->GetAppInfo()));
482   if (request->GetPid() == -1) {
483     _E("Failed to create a child process. appid: %s",
484         request->GetAppInfo()->GetAppId().c_str());
485   }
486
487   request->SendResult(request->GetPid());
488   _W("appid: %s, pid: %d",
489       request->GetAppInfo()->GetAppId().c_str(), request->GetPid());
490   LoaderManager::GetInst().HandleDirectLaunch(
491       std::move(request->GetLoaderContext()));
492   if (request->GetPid() == -1)
493     return LaunchResult::Fail;
494
495   return LaunchResult::Success;
496 }
497
498 Launchpad::LaunchResult Launchpad::LaunchRequestPend(
499     std::shared_ptr<Request> request) {
500   auto loader_context = request->GetAvailableLoaderContext();
501   if (loader_context->IsPrepared()) {
502     if (mode_ == Config::LaunchMode::Mode::AlwaysLoaderWithLowPriority)
503       SchedPriority::Set(loader_context->GetPid(), 0);
504
505     return LaunchResult::Continue;
506   }
507
508   _W("Loader context is not prepared");
509   loader_context->Ref();
510   if (loader_context->GetPid() <= 0)
511     loader_context->Prepare();
512
513   if (loader_context->GetPid() > 0) {
514     CPUBoostController::DoBoost(loader_context->GetPid(),
515         CPUBoostController::Level::Strong, 10000);
516     _W("Send result: %d", loader_context->GetPid());
517     request->SetPid(loader_context->GetPid());
518     request->SendResult(loader_context->GetPid());
519   }
520
521   pending_requests_.push_back(std::move(request));
522   return LaunchResult::Pending;
523 }
524
525 Launchpad::LaunchResult Launchpad::LaunchRequestDo(
526     std::shared_ptr<Request> request) {
527   auto loader_context = request->GetAvailableLoaderContext();
528   if (request->GetLoaderId() == PadLoaderId::Direct ||
529       loader_context == nullptr ||
530       launchpad::Debug::GetInst().CheckAsanApp(
531           request->GetAppInfo()->GetAppId())) {
532     return ForkProcessing(request);
533   }
534
535   if (LaunchRequestPend(request) == LaunchResult::Pending)
536     return LaunchResult::Pending;
537
538   auto* app_info = request->GetAppInfo();
539   _W("Launch %d type process. appid: %s",
540       static_cast<int>(loader_context->GetType()),
541       app_info->GetAppId().c_str());
542   request->SetPid(loader_context->Deploy(app_info));
543
544   if ((mode_ == Config::LaunchMode::Mode::AlwaysLoaderWithoutCPUChecker) ||
545       (mode_ == Config::LaunchMode::Mode::AlwaysLoaderWithLowPriority) ||
546       (mode_ == Config::LaunchMode::Mode::AlwaysLoader &&
547        loader_context->RefCount() > 0))
548     loader_context->Prepare();
549
550   return LaunchResult::Success;
551 }
552
553 void Launchpad::LaunchRequestComplete(std::shared_ptr<Request> request) {
554   MemoryMonitor::GetInst().Reset();
555   request->SendResult(request->GetPid());
556
557   if (request->GetPid() > 0) {
558     auto* app_info = request->GetAppInfo();
559     launchpad::DBus::SendAppLaunchSignal(request->GetPid(),
560         app_info->GetAppId().c_str());
561     pid_map_[request->GetPid()] = app_info->GetAppId();
562     launchpad::Log::Print("[LAUNCH]", "pid(%7d) | appid(%s)",
563         request->GetPid(), app_info->GetAppId().c_str());
564   }
565 }
566
567 void Launchpad::HandleLaunchRequest(std::shared_ptr<Request> request) {
568   Tracer tracer("LAUNCHPAD:LAUNCH");
569   if (LaunchRequestPrepare(request) == LaunchResult::Fail) {
570     request->SendResult(-1);
571     return;
572   }
573
574   if (LaunchRequestDo(request) == LaunchResult::Pending)
575     return;
576
577   LaunchRequestComplete(request);
578   _W("[PAD_CMD_LAUNCH] appid: %s, result: %d",
579       request->GetAppInfo()->GetAppId().c_str(), request->GetPid());
580 }
581
582 void Launchpad::HandleKillLoaderRequest(std::shared_ptr<Request> request) {
583   auto& b = request->GetBundle();
584   auto loader_name = b.GetString(kAulLoaderName);
585   auto loader_context =
586       LoaderManager::GetInst().FindLoaderContextFromName(loader_name);
587   if (loader_context == nullptr) {
588     _E("Failed to find loader context. loader_name(%s)", loader_name.c_str());
589     return;
590   }
591
592   if (loader_context->RefCount() == 0)
593     loader_context->Dispose();
594
595   _W("[PAD_CMD_KILL_LOADER] loader_name: %s", loader_name.c_str());
596 }
597
598 void Launchpad::HandleRestartLoaderRequest(std::shared_ptr<Request> request) {
599   auto& b = request->GetBundle();
600   auto loader_name = b.GetString(kAulLoaderName);
601   auto loader_context =
602       LoaderManager::GetInst().FindLoaderContextFromName(loader_name);
603   if (loader_context == nullptr) {
604     _E("Failed to find loader context. loader_name(%s)", loader_name.c_str());
605     return;
606   }
607
608   if (loader_context->RefCount() == 0)
609     loader_context->Dispose();
610
611   if (loader_context->GetPid() < 1)
612     loader_context->Prepare();
613
614   _W("[PAD_CMD_RESTART_LOADER] loader_name: %s, pid: %d",
615       loader_name.c_str(), loader_context->GetPid());
616 }
617
618 void Launchpad::HandleDisposeLoaderRequest(std::shared_ptr<Request> request) {
619   pid_t caller_pid = request->GetCallerPid();
620   auto loader_context =
621       LoaderManager::GetInst().FindLoaderContextFromPid(caller_pid);
622   if (loader_context == nullptr) {
623     _E("Failed to find loader context. pid(%d)", caller_pid);
624     return;
625   }
626
627   loader_context->Dispose();
628   _W("[PAD_CMD_DISPOSE_LOADER] loader_name: %s, pid: %d",
629      loader_context->GetLoaderName().c_str(), caller_pid);
630 }
631
632 void Launchpad::OnIOEventReceived(int fd, int condition) {
633   auto client_socket = socket_->Accept();
634   if (!client_socket) {
635     _E("Failed to accept the client request");
636     return;
637   }
638
639   try {
640     auto request = std::make_shared<Request>(std::move(client_socket));
641     _W("cmd(%d), caller(%d)", request->GetCmd(), request->GetCallerPid());
642     if (request->GetCallerUid() >= kRegularUidMin) {
643       if (CheckCallerPermission(request->GetCallerPid()) < 0) {
644         _E("Permission denied. pid(%d)", request->GetCallerPid());
645         request->SendResult(-EPERM);
646         return;
647       }
648     }
649
650     auto found = handlers_.find(request->GetCmd());
651     if (found == handlers_.end()) {
652       _E("Unknown command: %d", request->GetCmd());
653       request->SendResult(-EINVAL);
654       return;
655     }
656
657     auto method_handler = found->second;
658     method_handler(std::move(request));
659   } catch (const Exception& e) {
660     _E("Exception occurs. error(%s)", e.what());
661   }
662 }
663
664 void Launchpad::OnSigchldReceived(pid_t pid) {
665   auto found = pid_map_.find(pid);
666   if (found != pid_map_.end()) {
667     auto appid = found->second;
668     cleaner_->Add(std::make_shared<CleanupInfo>(std::move(appid), pid));
669     pid_map_.erase(found);
670   }
671
672   auto iter = pending_requests_.begin();
673   while (iter != pending_requests_.end()) {
674     auto request = *iter;
675     auto context = request->GetAvailableLoaderContext();
676     if (context != nullptr && request->GetPid() == pid) {
677       context->Unref();
678       auto* app_info = request->GetAppInfo();
679       launchpad::DBus::SendAppLaunchSignal(request->GetPid(),
680         app_info->GetAppId().c_str());
681       pending_requests_.erase(iter);
682       break;
683     }
684
685     iter++;
686   }
687
688   launchpad::Log::Print("[SIGCHLD]", "pid(%7d)", pid);
689   LoaderManager::GetInst().HandleSigchld(pid);
690 }
691
692 void Launchpad::OnLoaderPrepared(LoaderContext* loader_context) {
693   _W("Loader is prepared. name(%s), pid(%d)",
694       loader_context->GetLoaderName().c_str(), loader_context->GetPid());
695   if (loader_context->RefCount() == 0)
696     return;
697
698   auto iter = pending_requests_.begin();
699   while (iter != pending_requests_.end()) {
700     auto request = *iter;
701     auto context = request->GetAvailableLoaderContext();
702     if (context != nullptr && context.get() == loader_context) {
703       loader_context->Unref();
704       pending_requests_.erase(iter);
705       LaunchRequestDo(request);
706       LaunchRequestComplete(request);
707       return;
708     }
709
710     iter++;
711   }
712 }
713
714 void Launchpad::OnLoaderLaunched(LoaderContext* loader_context) {
715   _W("Loader is launched. name(%s), pid(%d)",
716       loader_context->GetLoaderName().c_str(), loader_context->GetPid());
717   if (loader_context->RefCount() == 0) {
718     if (mode_ == Config::LaunchMode::Mode::AlwaysLoaderWithLowPriority)
719       SchedPriority::Set(loader_context->GetPid(), 19);
720
721     return;
722   }
723
724   for (auto& request : pending_requests_) {
725     auto context = request->GetAvailableLoaderContext();
726     if (context != nullptr && context.get() == loader_context) {
727       request->SendResult(loader_context->GetPid());
728       return;
729     }
730   }
731 }
732
733 }  // namespace launchpad
734
735 int main(int argc, char** argv) {
736   launchpad::UserTracer tracer(
737       std::string(__FUNCTION__) + "(" + std::to_string(__LINE__) + ")");
738   prctl(PR_SET_CHILD_SUBREAPER, 1, 0, 0, 0);
739   launchpad::Launchpad launchpad(argc, argv);
740   return launchpad.Run();
741 }