From 2892ef619131f830f45e0c7161676133e5b27269 Mon Sep 17 00:00:00 2001 From: Hwankyu Jhun Date: Mon, 24 Apr 2023 09:15:35 +0000 Subject: [PATCH 01/16] Release version 0.30.4 Changes: - Improve launchpad initialization Change-Id: I127c196dddc0423b787fa26481eeb2fb2a703c21 Signed-off-by: Hwankyu Jhun --- packaging/launchpad.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packaging/launchpad.spec b/packaging/launchpad.spec index f8d236c..8ab5ef0 100644 --- a/packaging/launchpad.spec +++ b/packaging/launchpad.spec @@ -1,6 +1,6 @@ Name: launchpad Summary: Launchpad for launching applications -Version: 0.30.3 +Version: 0.30.4 Release: 1 Group: Application Framework/Daemons License: Apache-2.0 -- 2.7.4 From 6d0fc80bf23f420d9759644d5d3b3791cbf8e70f Mon Sep 17 00:00:00 2001 From: Hwankyu Jhun Date: Mon, 24 Apr 2023 23:23:49 +0000 Subject: [PATCH 02/16] Prevent crash issue When an app fails to run, the child process can crash while accessing the thread code created by the parent process. This patch is to avoid the crash issue. When it's failed, the child process executes the "echo" tool to reload the memory state. Change-Id: I53a16048f528c72159af5f50032bfffa6a77b7b7 Signed-off-by: Hwankyu Jhun --- src/launchpad-process-pool/app_executor.cc | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/src/launchpad-process-pool/app_executor.cc b/src/launchpad-process-pool/app_executor.cc index fc79d1c..91f6b32 100644 --- a/src/launchpad-process-pool/app_executor.cc +++ b/src/launchpad-process-pool/app_executor.cc @@ -56,6 +56,17 @@ std::shared_ptr CreateAppInfoFromAppPacket( return std::shared_ptr(AppInfo::Create(std::move(b))); } +void ExecuteEcho(const std::string& app_path) { + char *argv[] = { + const_cast("/usr/bin/echo"), + const_cast("Failed to execute a file. path: "), + const_cast(app_path.c_str()), + nullptr, + }; + + execv(argv[0], argv); +} + } // namespace AppExecutor::AppExecutor() @@ -141,8 +152,10 @@ void AppExecutor::OnExecution() { _close_all_fds(); if (execv(app_argv[LOADER_ARG_PATH], app_argv) < 0) { char err_buf[1024]; - fprintf(stderr, "Failed to exeucte a file. errno: %d(%s)\n", - errno, strerror_r(errno, err_buf, sizeof(err_buf))); + fprintf(stderr, "Failed to exeucte a file. path: %s, errno: %d(%s)\n", + app_info_->GetAppPath().c_str(), errno, + strerror_r(errno, err_buf, sizeof(err_buf))); + ExecuteEcho(app_info_->GetAppPath()); exit(EXIT_FAILURE); } } -- 2.7.4 From 899e3284e2980f81c8055ee3e627dceaa414794f Mon Sep 17 00:00:00 2001 From: Hwankyu Jhun Date: Tue, 25 Apr 2023 01:49:34 +0000 Subject: [PATCH 03/16] Release version 0.30.5 Changes: - Prevent crash issue Change-Id: Icf68e558751e442e83b3d6f502dd3a4075690b4a Signed-off-by: Hwankyu Jhun --- packaging/launchpad.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packaging/launchpad.spec b/packaging/launchpad.spec index 8ab5ef0..271d265 100644 --- a/packaging/launchpad.spec +++ b/packaging/launchpad.spec @@ -1,6 +1,6 @@ Name: launchpad Summary: Launchpad for launching applications -Version: 0.30.4 +Version: 0.30.5 Release: 1 Group: Application Framework/Daemons License: Apache-2.0 -- 2.7.4 From e4e8d89a7555e387b247a8f7c54e92adc64ff496 Mon Sep 17 00:00:00 2001 From: Hwankyu Jhun Date: Tue, 25 Apr 2023 02:38:10 +0000 Subject: [PATCH 04/16] Add missing function call To prevent crash issues, ExecuteEcho() should be called before calling exit() with the error code. Change-Id: I1e745cd752bac61381af35d84875bbaf5239c861 Signed-off-by: Hwankyu Jhun --- src/launchpad-process-pool/app_executor.cc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/launchpad-process-pool/app_executor.cc b/src/launchpad-process-pool/app_executor.cc index 91f6b32..fb65f07 100644 --- a/src/launchpad-process-pool/app_executor.cc +++ b/src/launchpad-process-pool/app_executor.cc @@ -126,6 +126,7 @@ void AppExecutor::OnExecution() { if (ret < 0) { _E("Failed to prepare executing application(%s)", app_info_->GetAppId().c_str()); + ExecuteEcho(app_info_->GetAppPath()); exit(ret); } @@ -134,6 +135,7 @@ void AppExecutor::OnExecution() { char** app_argv = static_cast(calloc(argv.size() + 1, sizeof(char*))); if (app_argv == nullptr) { _E("Out of memory"); + ExecuteEcho(app_info_->GetAppPath()); exit(-1); } -- 2.7.4 From e06e50f2b5e38e66d4cbd0bc048dda3d67f0fef8 Mon Sep 17 00:00:00 2001 From: Changgyu Choi Date: Tue, 25 Apr 2023 12:04:02 +0900 Subject: [PATCH 05/16] Release version 0.30.6 Changes: - Add missing function call Change-Id: I9c775f949874d5f94e3b2bb9d6b2358a21aa9ec4 Signed-off-by: Changgyu Choi --- packaging/launchpad.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packaging/launchpad.spec b/packaging/launchpad.spec index 271d265..5d52c2c 100644 --- a/packaging/launchpad.spec +++ b/packaging/launchpad.spec @@ -1,6 +1,6 @@ Name: launchpad Summary: Launchpad for launching applications -Version: 0.30.5 +Version: 0.30.6 Release: 1 Group: Application Framework/Daemons License: Apache-2.0 -- 2.7.4 From 55598ec9cc0078184699305a98f3739f268d4d7b Mon Sep 17 00:00:00 2001 From: Hwankyu Jhun Date: Thu, 27 Apr 2023 23:43:39 +0000 Subject: [PATCH 06/16] Dispose candidate process of process pool When the app label changed event is received, the launchpad has to terminate all candidate processes. If it's not, calling the security_manager_prepare_app2() will be failed when executing an application. Change-Id: I730bfc0fa5126743d2bd80c541d131ae581ad931 Signed-off-by: Hwankyu Jhun --- src/launchpad-process-pool/loader_executor.cc | 5 +++++ src/launchpad-process-pool/loader_executor.hh | 1 + src/launchpad-process-pool/loader_manager.cc | 3 +++ src/launchpad-process-pool/process_pool.cc | 24 +++++++++++++++++++----- src/launchpad-process-pool/process_pool.hh | 5 +++-- 5 files changed, 31 insertions(+), 7 deletions(-) diff --git a/src/launchpad-process-pool/loader_executor.cc b/src/launchpad-process-pool/loader_executor.cc index 1be888e..7184d99 100644 --- a/src/launchpad-process-pool/loader_executor.cc +++ b/src/launchpad-process-pool/loader_executor.cc @@ -73,6 +73,11 @@ bool LoaderExecutor::HasCandidateProcess() const { return process_pool_->IsPrepared(); } +void LoaderExecutor::DisposeCandidateProcess() { + process_pool_->Dispose(); + process_pool_->SetTimer(); +} + void LoaderExecutor::OnExecution() { std::vector loader_argv(loader_argv_.size() + 1); int loader_argc = loader_argv_.size(); diff --git a/src/launchpad-process-pool/loader_executor.hh b/src/launchpad-process-pool/loader_executor.hh index a55ca30..c3b2664 100644 --- a/src/launchpad-process-pool/loader_executor.hh +++ b/src/launchpad-process-pool/loader_executor.hh @@ -40,6 +40,7 @@ class LoaderExecutor : public Executor::Delegator, pid_t Execute(const LoaderContext* loader_context, int priority); bool HasCandidateProcess() const; + void DisposeCandidateProcess(); private: LoaderExecutor(); diff --git a/src/launchpad-process-pool/loader_manager.cc b/src/launchpad-process-pool/loader_manager.cc index 7d88860..46620ef 100644 --- a/src/launchpad-process-pool/loader_manager.cc +++ b/src/launchpad-process-pool/loader_manager.cc @@ -20,6 +20,7 @@ #include #include "launchpad-process-pool/config.hh" +#include "launchpad-process-pool/loader_executor.hh" #include "launchpad-process-pool/loader_factory.hh" #include "launchpad-process-pool/log_private.hh" @@ -457,6 +458,8 @@ void LoaderManager::OnAppLabelsChanged() { context->Prepare(); } } + + LoaderExecutor::GetInst().DisposeCandidateProcess(); } void LoaderManager::OnMemoryStatusChanged(bool low_memory, diff --git a/src/launchpad-process-pool/process_pool.cc b/src/launchpad-process-pool/process_pool.cc index cec1c39..19fbcc6 100644 --- a/src/launchpad-process-pool/process_pool.cc +++ b/src/launchpad-process-pool/process_pool.cc @@ -40,11 +40,7 @@ ProcessPool::ProcessPool(int num_processes, IEvent* event_listener = nullptr) } ProcessPool::~ProcessPool() { - while (!queue_.empty()) { - auto process = std::move(queue_.front()); - queue_.pop(); - process->Kill(); - } + Dispose(); } bool ProcessPool::IsPrepared() const { @@ -62,6 +58,17 @@ pid_t ProcessPool::Execute(std::shared_ptr app_packet) { return process->GetPid(); } +void ProcessPool::Dispose() { + while (!queue_.empty()) { + auto process = std::move(queue_.front()); + queue_.pop(); + process->Kill(); + _D("Kill process(%d)", process->GetPid()); + } + + UnsetTimer(); +} + ProcessPool::Process::Process(pid_t pid, int fd) : pid_(pid), socket_(new Socket(fd)) { } @@ -162,6 +169,13 @@ void ProcessPool::SetTimer() { timer_ = g_timeout_add(1000, OnTimeout, this); } +void ProcessPool::UnsetTimer() { + if (timer_ != 0) { + g_source_remove(timer_); + timer_ = 0; + } +} + gboolean ProcessPool::OnTimeout(gpointer user_data) { auto* process_pool = static_cast(user_data); process_pool->PrepareProcess(); diff --git a/src/launchpad-process-pool/process_pool.hh b/src/launchpad-process-pool/process_pool.hh index 302a826..85b87fa 100644 --- a/src/launchpad-process-pool/process_pool.hh +++ b/src/launchpad-process-pool/process_pool.hh @@ -45,6 +45,8 @@ class ProcessPool : public Executor::Delegator, bool IsPrepared() const; pid_t Execute(std::shared_ptr app_packet); + void Dispose(); + void SetTimer(); private: class Process { @@ -61,10 +63,9 @@ class ProcessPool : public Executor::Delegator, }; void OnExecution() override; - + void UnsetTimer(); void PrepareProcess(); int WaitForRequest(std::unique_ptr socket); - void SetTimer(); static gboolean OnTimeout(gpointer user_data); private: -- 2.7.4 From 56cfdcd9370f3f7c7b993f4f8c0194fd1411c320 Mon Sep 17 00:00:00 2001 From: Hwankyu Jhun Date: Fri, 28 Apr 2023 00:58:27 +0000 Subject: [PATCH 07/16] Release version 0.30.7 Changes: - Dispose candidate process of process pool Change-Id: Idf1c133d682b04e1677a7291c216d636ef411127 Signed-off-by: Hwankyu Jhun --- packaging/launchpad.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packaging/launchpad.spec b/packaging/launchpad.spec index 5d52c2c..1c25cc8 100644 --- a/packaging/launchpad.spec +++ b/packaging/launchpad.spec @@ -1,6 +1,6 @@ Name: launchpad Summary: Launchpad for launching applications -Version: 0.30.6 +Version: 0.30.7 Release: 1 Group: Application Framework/Daemons License: Apache-2.0 -- 2.7.4 From bcd9ce0e7f2a937c5fd8aadb3f37ce407dc89e04 Mon Sep 17 00:00:00 2001 From: Hwankyu Jhun Date: Tue, 2 May 2023 00:13:10 +0000 Subject: [PATCH 08/16] Fix bug about handling app labels changes event Before disposing and preparaing the loader context, the launchpad has to dispose the candidate process of the process pool. Change-Id: Id80371087d2172399482d0350226e23c7b323e55 Signed-off-by: Hwankyu Jhun --- src/launchpad-process-pool/loader_manager.cc | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/launchpad-process-pool/loader_manager.cc b/src/launchpad-process-pool/loader_manager.cc index 46620ef..549b7ab 100644 --- a/src/launchpad-process-pool/loader_manager.cc +++ b/src/launchpad-process-pool/loader_manager.cc @@ -446,6 +446,8 @@ LoaderManager::~LoaderManager() { } void LoaderManager::OnAppLabelsChanged() { + _W("BEGIN"); + LoaderExecutor::GetInst().DisposeCandidateProcess(); for (auto& context : loader_contexts_) { if (context->IsHydraMode()) { auto* hydra_context = dynamic_cast(context.get()); @@ -458,8 +460,7 @@ void LoaderManager::OnAppLabelsChanged() { context->Prepare(); } } - - LoaderExecutor::GetInst().DisposeCandidateProcess(); + _W("END"); } void LoaderManager::OnMemoryStatusChanged(bool low_memory, -- 2.7.4 From 0fe4b8880136bd700bfe34ac6bbc9b706525d0fe Mon Sep 17 00:00:00 2001 From: Hwankyu Jhun Date: Tue, 2 May 2023 00:21:50 +0000 Subject: [PATCH 09/16] Release version 0.30.8 Changes: - Fix bug about handling app labels changes event Change-Id: I123ea87900ef4305ee3f4778211fc7e124edf77f Signed-off-by: Hwankyu Jhun --- packaging/launchpad.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packaging/launchpad.spec b/packaging/launchpad.spec index 1c25cc8..0c26848 100644 --- a/packaging/launchpad.spec +++ b/packaging/launchpad.spec @@ -1,6 +1,6 @@ Name: launchpad Summary: Launchpad for launching applications -Version: 0.30.7 +Version: 0.30.8 Release: 1 Group: Application Framework/Daemons License: Apache-2.0 -- 2.7.4 From bbe43df225f4adb2cda226e583a1e1f2005cddac Mon Sep 17 00:00:00 2001 From: Hwankyu Jhun Date: Wed, 3 May 2023 06:26:13 +0000 Subject: [PATCH 10/16] Fix a bug about app-defined-loader The arguments has to be changed before executing an application. Change-Id: I64d97656bd8e8481ff3711e7f9904ceb51228957 Signed-off-by: Hwankyu Jhun --- src/app-defined-loader/src/app-defined-loader.cc | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/app-defined-loader/src/app-defined-loader.cc b/src/app-defined-loader/src/app-defined-loader.cc index 21f1c01..1a5255f 100644 --- a/src/app-defined-loader/src/app-defined-loader.cc +++ b/src/app-defined-loader/src/app-defined-loader.cc @@ -221,6 +221,9 @@ class AppDefinedLoader { argv[LOADER_ARG_PATH]); char old_cwd[PATH_MAX] = {0, }; AppDefinedLoader* loader = static_cast(user_data); + loader->argc_ = argc; + loader->argv_ = argv; + if (getcwd(old_cwd, sizeof(old_cwd)) == nullptr) { _E("getcwd() is failed"); loader->DoDlOpen(false, old_cwd, ""); -- 2.7.4 From 2ed13283766222782bec186f006567e32061b85d Mon Sep 17 00:00:00 2001 From: Hwankyu Jhun Date: Wed, 3 May 2023 06:57:40 +0000 Subject: [PATCH 11/16] Modify app-defined-loader for linux container Some product developer wants to use the app-defined-loader for executing an application which will be attached to the linux container. This patch adds the plugin function call while calling the OnCreate() method. Change-Id: Ied702faffcc6097b22f71646ee1a21f318b5ab31 Signed-off-by: Hwankyu Jhun --- src/app-defined-loader/src/app-defined-loader.cc | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/src/app-defined-loader/src/app-defined-loader.cc b/src/app-defined-loader/src/app-defined-loader.cc index 1a5255f..b5c1d5a 100644 --- a/src/app-defined-loader/src/app-defined-loader.cc +++ b/src/app-defined-loader/src/app-defined-loader.cc @@ -15,24 +15,23 @@ */ #include +#include #include #include +#include #include #include #include #include -#include - #include #include +#include "config.hh" #include "key.h" -#include "launchpad.h" #include "launchpad_common.h" +#include "launchpad_plugin.h" #include "launchpad_types.h" - -#include "config.hh" #include "log-private.hh" #include "proc.hh" @@ -126,6 +125,12 @@ class AppDefinedLoader { static void OnCreate(bundle* extra, int type, void* user_data) { _I("on create"); + int ret = _launchpad_plugin_prepare_app(nullptr, extra); + if (ret != 0) { + _E("_launchpad_plugin_prepare_app() is failed. error(%d)", ret); + exit(EXIT_FAILURE); + } + AppDefinedLoader* loader = static_cast(user_data); tizen_base::Bundle ex = tizen_base::Bundle(extra, false, false); std::string loader_type = ex.GetString(KEY_LOADER_TYPE); -- 2.7.4 From 2c436ab2d64df353c54c2159ee6c9c37a8d61f77 Mon Sep 17 00:00:00 2001 From: Hwankyu Jhun Date: Wed, 3 May 2023 03:54:45 +0000 Subject: [PATCH 12/16] Refactor Launchpad Hydra The launchpad hydra libary is implemented using C++ language. The process pool is added to the hydra loader. And, this patch decreases the number of the process pool of executors to one from two. The liblaunchpad-glib library is added to separate the libary related to glib from the liblaunchpad-common library. It's for the liblaunchpad-hydra library. Change-Id: I434e9612e2b1c3c2cfe9ac174c7175d16ddda842 Signed-off-by: Hwankyu Jhun --- CMakeLists.txt | 1 + packaging/launchpad.spec | 7 +- src/launchpad-process-pool/CMakeLists.txt | 3 +- src/launchpad-process-pool/app_executor.cc | 31 +- src/launchpad-process-pool/app_executor.hh | 2 +- src/launchpad-process-pool/hydra_loader_context.cc | 18 +- src/launchpad-process-pool/hydra_sigchld_event.cc | 27 +- src/launchpad-process-pool/hydra_sigchld_event.hh | 2 +- src/launchpad-process-pool/launchpad.cc | 4 +- src/launchpad-process-pool/launchpad_args.cc | 39 ++ src/launchpad-process-pool/launchpad_args.hh | 45 ++ src/launchpad-process-pool/loader_executor.cc | 28 +- src/launchpad-process-pool/loader_executor.hh | 2 +- src/launchpad-process-pool/process_pool.cc | 56 +-- src/launchpad-process-pool/process_pool.hh | 13 +- src/launchpad-process-pool/signal_manager.cc | 4 +- src/launchpad-process-pool/signal_manager.hh | 2 +- src/lib/CMakeLists.txt | 1 + src/lib/common/inc/launchpad_types.h | 1 + src/lib/launchpad-common/CMakeLists.txt | 4 +- src/lib/launchpad-common/app_packet.cc | 65 --- src/lib/launchpad-common/hydra_request.cc | 67 +++ .../{app_packet.hh => hydra_request.hh} | 42 +- src/lib/launchpad-common/sigchld_info.cc | 42 ++ src/lib/launchpad-common/sigchld_info.hh | 49 +++ src/lib/launchpad-common/socket.hh | 2 + src/lib/launchpad-common/stdio.cc | 43 ++ .../stdio.hh} | 24 +- src/lib/launchpad-glib/CMakeLists.txt | 37 ++ .../app_info.cc | 49 ++- .../app_info.hh | 15 +- .../io_channel.cc | 4 +- .../io_channel.hh | 6 +- src/lib/launchpad-glib/log_private.hh | 37 ++ .../pkgconfig/liblaunchpad-glib.pc.in | 13 + .../{launchpad-common => launchpad-glib}/plugin.cc | 4 +- .../{launchpad-common => launchpad-glib}/plugin.hh | 6 +- .../{launchpad-common => launchpad-glib}/util.cc | 7 +- .../{launchpad-common => launchpad-glib}/util.hh | 6 +- .../{launchpad-common => launchpad-glib}/vconf.cc | 4 +- .../{launchpad-common => launchpad-glib}/vconf.hh | 6 +- src/lib/launchpad-hydra/CMakeLists.txt | 16 +- src/lib/launchpad-hydra/event_loop.cc | 79 ++++ src/lib/launchpad-hydra/event_loop.hh | 48 +++ src/lib/launchpad-hydra/executor.cc | 95 +++++ src/lib/launchpad-hydra/executor.hh | 43 ++ src/lib/launchpad-hydra/hydra_args.cc | 39 ++ src/lib/launchpad-hydra/hydra_args.hh | 44 ++ src/lib/launchpad-hydra/io_event.cc | 60 +++ src/lib/launchpad-hydra/io_event.hh | 54 +++ src/lib/launchpad-hydra/launchpad_hydra.cc | 280 +++++++++++++ src/lib/launchpad-hydra/launchpad_hydra.hh | 73 ++++ src/lib/launchpad-hydra/loader_executor.cc | 107 +++++ src/lib/launchpad-hydra/loader_executor.hh | 60 +++ src/lib/launchpad-hydra/log_private.hh | 37 ++ src/lib/launchpad-hydra/process_pool.cc | 212 ++++++++++ src/lib/launchpad-hydra/process_pool.hh | 84 ++++ src/lib/launchpad-hydra/signal_manager.cc | 130 ++++++ src/lib/launchpad-hydra/signal_manager.hh | 73 ++++ src/lib/launchpad-hydra/src/launchpad_hydra.c | 462 --------------------- src/lib/launchpad-hydra/src/launchpad_sigchld.c | 50 --- src/lib/launchpad/src/launchpad_lib.c | 9 + .../launchpad-process-pool-unittest/CMakeLists.txt | 3 +- 63 files changed, 2143 insertions(+), 733 deletions(-) create mode 100644 src/launchpad-process-pool/launchpad_args.cc create mode 100644 src/launchpad-process-pool/launchpad_args.hh delete mode 100644 src/lib/launchpad-common/app_packet.cc create mode 100644 src/lib/launchpad-common/hydra_request.cc rename src/lib/launchpad-common/{app_packet.hh => hydra_request.hh} (57%) create mode 100644 src/lib/launchpad-common/sigchld_info.cc create mode 100644 src/lib/launchpad-common/sigchld_info.hh create mode 100644 src/lib/launchpad-common/stdio.cc rename src/lib/{launchpad-hydra/inc/launchpad_sigchld.h => launchpad-common/stdio.hh} (60%) create mode 100644 src/lib/launchpad-glib/CMakeLists.txt rename src/lib/{launchpad-common => launchpad-glib}/app_info.cc (78%) rename src/lib/{launchpad-common => launchpad-glib}/app_info.hh (90%) rename src/lib/{launchpad-common => launchpad-glib}/io_channel.cc (95%) rename src/lib/{launchpad-common => launchpad-glib}/io_channel.hh (92%) create mode 100644 src/lib/launchpad-glib/log_private.hh create mode 100644 src/lib/launchpad-glib/pkgconfig/liblaunchpad-glib.pc.in rename src/lib/{launchpad-common => launchpad-glib}/plugin.cc (95%) rename src/lib/{launchpad-common => launchpad-glib}/plugin.hh (88%) rename src/lib/{launchpad-common => launchpad-glib}/util.cc (97%) rename src/lib/{launchpad-common => launchpad-glib}/util.hh (89%) rename src/lib/{launchpad-common => launchpad-glib}/vconf.cc (97%) rename src/lib/{launchpad-common => launchpad-glib}/vconf.hh (93%) create mode 100644 src/lib/launchpad-hydra/event_loop.cc create mode 100644 src/lib/launchpad-hydra/event_loop.hh create mode 100644 src/lib/launchpad-hydra/executor.cc create mode 100644 src/lib/launchpad-hydra/executor.hh create mode 100644 src/lib/launchpad-hydra/hydra_args.cc create mode 100644 src/lib/launchpad-hydra/hydra_args.hh create mode 100644 src/lib/launchpad-hydra/io_event.cc create mode 100644 src/lib/launchpad-hydra/io_event.hh create mode 100644 src/lib/launchpad-hydra/launchpad_hydra.cc create mode 100644 src/lib/launchpad-hydra/launchpad_hydra.hh create mode 100644 src/lib/launchpad-hydra/loader_executor.cc create mode 100644 src/lib/launchpad-hydra/loader_executor.hh create mode 100644 src/lib/launchpad-hydra/log_private.hh create mode 100644 src/lib/launchpad-hydra/process_pool.cc create mode 100644 src/lib/launchpad-hydra/process_pool.hh create mode 100644 src/lib/launchpad-hydra/signal_manager.cc create mode 100644 src/lib/launchpad-hydra/signal_manager.hh delete mode 100644 src/lib/launchpad-hydra/src/launchpad_hydra.c delete mode 100644 src/lib/launchpad-hydra/src/launchpad_sigchld.c diff --git a/CMakeLists.txt b/CMakeLists.txt index d301623..67bdb59 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -37,6 +37,7 @@ SET(CMAKE_EXE_LINKER_FLAGS "-Wl,--as-needed") SET(TARGET_APP_DEFINED_LOADER "app-defined-loader") SET(TARGET_LAUNCHPAD "launchpad") SET(TARGET_LAUNCHPAD_COMMON "launchpad-common") +SET(TARGET_LAUNCHPAD_GLIB "launchpad-glib") SET(TARGET_LAUNCHPAD_HYDRA "launchpad-hydra") SET(TARGET_LAUNCHPAD_LOADER "launchpad-loader") SET(TARGET_LAUNCHPAD_PARSER "launchpad-parser") diff --git a/packaging/launchpad.spec b/packaging/launchpad.spec index 0c26848..ece4c6f 100644 --- a/packaging/launchpad.spec +++ b/packaging/launchpad.spec @@ -154,7 +154,7 @@ MAJORVER=`echo %{version} | awk 'BEGIN {FS="."}{print $1}'` %__make %{?_smp_mflags} %check -export LD_LIBRARY_PATH="../../src/lib/launchpad-common/" +export LD_LIBRARY_PATH="../../src/lib/launchpad-common/:../../src/lib/launchpad-glib" ctest --verbose %{?_smp_mflags} %install @@ -170,6 +170,7 @@ ln -sf ../launchpad-process-pool.socket %{buildroot}%{_unitdir_user}/sockets.tar ln -sf ../launchpad-process-pool.service %{buildroot}%{_unitdir_user}/basic.target.wants/launchpad-process-pool.service %post +lns -sf /usr/bin/false /usr/bin/process-pool %files %manifest launchpad.manifest @@ -184,14 +185,18 @@ ln -sf ../launchpad-process-pool.service %{buildroot}%{_unitdir_user}/basic.targ %{_sysconfdir}/package-manager/parserlib/liblaunchpad-parser.so %{_datadir}/parser-plugins/* %attr(0644,root,root) %{_libdir}/liblaunchpad-common.so.* +%attr(0644,root,root) %{_libdir}/liblaunchpad-glib.so.* %files devel %{_includedir}/launchpad/*.h %{_includedir}/launchpad-common/*.hh +%{_includedir}/launchpad-glib/*.hh %{_libdir}/*.so %{_libdir}/pkgconfig/launchpad.pc %attr(0644,root,root) %{_libdir}/liblaunchpad-common.so %{_libdir}/pkgconfig/liblaunchpad-common.pc +%attr(0644,root,root) %{_libdir}/liblaunchpad-glib.so +%{_libdir}/pkgconfig/liblaunchpad-glib.pc %files -n launchpad-loader %manifest launchpad-loader.manifest diff --git a/src/launchpad-process-pool/CMakeLists.txt b/src/launchpad-process-pool/CMakeLists.txt index 7c07104..062173c 100644 --- a/src/launchpad-process-pool/CMakeLists.txt +++ b/src/launchpad-process-pool/CMakeLists.txt @@ -14,6 +14,7 @@ TARGET_INCLUDE_DIRECTORIES(${TARGET_LAUNCHPAD_PROCESS_POOL} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/../ ${CMAKE_CURRENT_SOURCE_DIR}/../lib/common/inc ${CMAKE_CURRENT_SOURCE_DIR}/../lib/launchpad-common + ${CMAKE_CURRENT_SOURCE_DIR}/../lib/launchpad-glib ) IF(_TIZEN_FEATURE_PRELINK) @@ -45,7 +46,7 @@ APPLY_PKG_CONFIG(${TARGET_LAUNCHPAD_PROCESS_POOL} PUBLIC ) TARGET_LINK_LIBRARIES(${TARGET_LAUNCHPAD_PROCESS_POOL} PUBLIC - ${TARGET_LAUNCHPAD_COMMON} "-lm -ldl -lpthread") + ${TARGET_LAUNCHPAD_COMMON} ${TARGET_LAUNCHPAD_GLIB} "-lm -ldl -lpthread") CONFIGURE_FILE(${CMAKE_SOURCE_DIR}/packaging/default.debugger.in ${CMAKE_SOURCE_DIR}/packaging/default.debugger @ONLY) diff --git a/src/launchpad-process-pool/app_executor.cc b/src/launchpad-process-pool/app_executor.cc index fb65f07..e99c17e 100644 --- a/src/launchpad-process-pool/app_executor.cc +++ b/src/launchpad-process-pool/app_executor.cc @@ -42,20 +42,6 @@ namespace launchpad { namespace fs = std::filesystem; namespace { -std::shared_ptr CreateAppPacketFromAppInfo(const AppInfo* app_info) { - auto raw = const_cast(app_info->GetBundle()).ToRaw(); - std::vector data(raw.first.get(), raw.first.get() + raw.second); - return std::shared_ptr(new AppPacket(0, 0, std::move(data))); -} - -std::shared_ptr CreateAppInfoFromAppPacket( - const AppPacket* app_packet) { - auto& data = app_packet->GetData(); - std::string raw(data.begin(), data.end()); - tizen_base::Bundle b(raw); - return std::shared_ptr(AppInfo::Create(std::move(b))); -} - void ExecuteEcho(const std::string& app_path) { char *argv[] = { const_cast("/usr/bin/echo"), @@ -69,8 +55,7 @@ void ExecuteEcho(const std::string& app_path) { } // namespace -AppExecutor::AppExecutor() - : Executor(this) { +AppExecutor::AppExecutor() : Executor(this) { LauncherInfoInflator inflator; launcher_infos_ = inflator.Inflate("/usr/share/aul"); @@ -102,13 +87,14 @@ AppExecutor::AppExecutor() std::bind(&AppExecutor::StepPrepareAppSocketAndIdFile, this)); prepare_funcs_.push_back( std::bind(&AppExecutor::StepSendStartupSignal, this)); - process_pool_ = std::unique_ptr(new ProcessPool(2, this)); + process_pool_ = std::unique_ptr(new ProcessPool("app", 1, this)); } pid_t AppExecutor::Execute(const AppInfo* app_info) { if (process_pool_->IsPrepared()) { - auto app_packet = CreateAppPacketFromAppInfo(app_info); - return process_pool_->Execute(std::move(app_packet)); + tizen_base::Parcel parcel; + parcel.WriteParcelable(*app_info); + return process_pool_->Execute(parcel); } app_info_ = app_info; @@ -162,10 +148,11 @@ void AppExecutor::OnExecution() { } } -void AppExecutor::OnRequestReceived(std::shared_ptr app_packet) { +void AppExecutor::OnRequestReceived(tizen_base::Parcel* parcel) { _W("Request received"); - auto app_info = CreateAppInfoFromAppPacket(app_packet.get()); - app_info_ = app_info.get(); + AppInfo app_info; + parcel->ReadParcelable(&app_info); + app_info_ = &app_info; OnExecution(); } diff --git a/src/launchpad-process-pool/app_executor.hh b/src/launchpad-process-pool/app_executor.hh index ea964af..7d1f8d6 100644 --- a/src/launchpad-process-pool/app_executor.hh +++ b/src/launchpad-process-pool/app_executor.hh @@ -42,7 +42,7 @@ class AppExecutor : public Executor::Delegator, private: void OnExecution() override; - void OnRequestReceived(std::shared_ptr app_packet) override; + void OnRequestReceived(tizen_base::Parcel* parcel) override; int Prepare(); int StepCreateNewSession(); diff --git a/src/launchpad-process-pool/hydra_loader_context.cc b/src/launchpad-process-pool/hydra_loader_context.cc index df0eb45..b42db39 100644 --- a/src/launchpad-process-pool/hydra_loader_context.cc +++ b/src/launchpad-process-pool/hydra_loader_context.cc @@ -22,6 +22,7 @@ #include #include +#include #include "launchpad-process-pool/log_private.hh" #include "lib/common/inc/launchpad_types.h" @@ -109,10 +110,21 @@ void HydraLoaderContext::SetHydraPid(pid_t hydra_pid) { void HydraLoaderContext::PrepareCandidateProcess() { _W("Send launch request to hydra loader. fd(%d)", client_socket_->GetFd()); - int cmd = static_cast(LAUNCH_CANDIDATE); - int ret = client_socket_->Send(static_cast(&cmd), sizeof(cmd)); + HydraRequest request(LAUNCH_CANDIDATE); + tizen_base::Parcel parcel; + parcel.WriteParcelable(request); + + size_t data_size = parcel.GetDataSize(); + int ret = client_socket_->Send(static_cast(&data_size), + sizeof(data_size)); + if (ret != 0) { + _E("Send() is failed. error: %d", ret); + return; + } + + ret = client_socket_->Send(parcel.GetData(), data_size); if (ret != 0) - _E("Failed to send candidate launch request. error(%d)", ret); + _E("Send() is failed. error: %d", ret); } void HydraLoaderContext::HandleHydraLoaderEvent() { diff --git a/src/launchpad-process-pool/hydra_sigchld_event.cc b/src/launchpad-process-pool/hydra_sigchld_event.cc index f09f093..4ae62e7 100644 --- a/src/launchpad-process-pool/hydra_sigchld_event.cc +++ b/src/launchpad-process-pool/hydra_sigchld_event.cc @@ -18,6 +18,7 @@ #include +#include #include #include @@ -77,12 +78,32 @@ void HydraSigchldEvent::OnIOEventReceived(int fd, int condition) { if (CheckPermission(peer_creds->GetPid()) != 0) return; - pid_t pid = -1; - if (client_socket->Receive(&pid, sizeof(pid)) != 0) + size_t data_size = 0; + int ret = client_socket->Receive(&data_size, sizeof(data_size)); + if (ret != 0) { + _E("Receive() is failed. error: %d", ret); return; + } + + uint8_t* data = static_cast(malloc(sizeof(data_size))); + if (data == nullptr) { + _E("malloc() is failed"); + return; + } + + std::unique_ptr data_auto(data, free); + ret = client_socket->Receive(data, data_size); + if (ret != 0) { + _E("Receive() is failed. error: %d", ret); + return; + } + + tizen_base::Parcel parcel(data_auto.release(), data_size, false); + SigchldInfo info; + parcel.ReadParcelable(&info); if (listener_ != nullptr) - listener_->OnHydraSigchld(pid); + listener_->OnHydraSigchld(info.GetPid(), info.GetStatus()); } } // namespace launchpad diff --git a/src/launchpad-process-pool/hydra_sigchld_event.hh b/src/launchpad-process-pool/hydra_sigchld_event.hh index cc703cd..b4bba0e 100644 --- a/src/launchpad-process-pool/hydra_sigchld_event.hh +++ b/src/launchpad-process-pool/hydra_sigchld_event.hh @@ -32,7 +32,7 @@ class HydraSigchldEvent : public IOChannel::IEvent { class IEvent { public: virtual ~IEvent() = default; - virtual void OnHydraSigchld(pid_t pid) = 0; + virtual void OnHydraSigchld(pid_t pid, int status) = 0; }; explicit HydraSigchldEvent(IEvent* listener); diff --git a/src/launchpad-process-pool/launchpad.cc b/src/launchpad-process-pool/launchpad.cc index 9857488..3176a54 100644 --- a/src/launchpad-process-pool/launchpad.cc +++ b/src/launchpad-process-pool/launchpad.cc @@ -44,6 +44,7 @@ #include "launchpad-process-pool/debug.hh" #include "launchpad-process-pool/language_config.hh" #include "launchpad-process-pool/launcher_info.hh" +#include "launchpad-process-pool/launchpad_args.hh" #include "launchpad-process-pool/loader_manager.hh" #include "launchpad-process-pool/loader_executor.hh" #include "launchpad-process-pool/log.hh" @@ -177,6 +178,7 @@ Launchpad::Launchpad(int argc, char** argv) : argc_(argc), argv_(argv), loop_(g_main_loop_new(nullptr, FALSE)) { + LaunchpadArgs::GetInst().Set(argc_, argv_); handlers_ = { { PAD_CMD_VISIBILITY, std::bind(&Launchpad::HandleVisibilityRequest, this, @@ -516,7 +518,7 @@ void Launchpad::HandleLaunchRequest(std::shared_ptr request) { return; LaunchRequestComplete(request); - _D("PAD_CMD_LAUNCH] appid: %s, result: %d", + _D("[PAD_CMD_LAUNCH] appid: %s, result: %d", request->GetAppInfo()->GetAppId().c_str(), request->GetPid()); } diff --git a/src/launchpad-process-pool/launchpad_args.cc b/src/launchpad-process-pool/launchpad_args.cc new file mode 100644 index 0000000..bda43bb --- /dev/null +++ b/src/launchpad-process-pool/launchpad_args.cc @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "launchpad-process-pool/launchpad_args.hh" + +namespace launchpad { + +LaunchpadArgs& LaunchpadArgs::GetInst() { + static LaunchpadArgs inst; + return inst; +} + +void LaunchpadArgs::Set(int argc, char** args) { + argc_ = argc; + args_ = args; +} + +int LaunchpadArgs::GetArgc() const { + return argc_; +} + +char** LaunchpadArgs::GetArgs() const { + return args_; +} + +} // namespace launchpad diff --git a/src/launchpad-process-pool/launchpad_args.hh b/src/launchpad-process-pool/launchpad_args.hh new file mode 100644 index 0000000..741e949 --- /dev/null +++ b/src/launchpad-process-pool/launchpad_args.hh @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef LAUNCHPAD_PROCESS_POOL_LAUNCHPAD_ARGS_HH_ +#define LAUNCHPAD_PROCESS_POOL_LAUNCHPAD_ARGS_HH_ + +namespace launchpad { + +class LaunchpadArgs { + public: + LaunchpadArgs(const LaunchpadArgs&) = delete; + LaunchpadArgs& operator=(const LaunchpadArgs&) = delete; + + static LaunchpadArgs& GetInst(); + + void Set(int argc, char** args); + + int GetArgc() const; + char** GetArgs() const; + + private: + LaunchpadArgs() = default; + ~LaunchpadArgs() = default; + + private: + int argc_ = 0; + char** args_ = nullptr; +}; + +} // namespace launchpad + +#endif // LAUNCHPAD_PROCESS_POOL_LAUNCHPAD_ARGS_HH_ diff --git a/src/launchpad-process-pool/loader_executor.cc b/src/launchpad-process-pool/loader_executor.cc index 7184d99..f0c03fd 100644 --- a/src/launchpad-process-pool/loader_executor.cc +++ b/src/launchpad-process-pool/loader_executor.cc @@ -32,18 +32,18 @@ namespace launchpad { namespace { -std::shared_ptr CreateAppPacketFromArgs( - const std::vector& args) { +tizen_base::Parcel CreateParcelFromArgv(const std::vector& argv) { tizen_base::Bundle b; - b.Add("LOADER_ARGS", args); - auto raw = b.ToRaw(); - std::vector data(raw.first.get(), raw.first.get() + raw.second); - return std::shared_ptr(new AppPacket(0, 0, std::move(data))); + b.Add("LOADER_ARGS", argv); + auto b_raw = b.ToRaw(); + std::string raw(reinterpret_cast(b_raw.first.get())); + tizen_base::Parcel parcel; + parcel.WriteString(raw); + return parcel; } -std::vector CreateArgsFromAppPacket(const AppPacket* app_packet) { - auto& data = app_packet->GetData(); - std::string raw(data.begin(), data.end()); +std::vector CreateArgvFromParcel(tizen_base::Parcel* parcel) { + std::string raw = parcel->ReadString(); tizen_base::Bundle b(raw); return b.GetStringArray("LOADER_ARGS"); } @@ -51,7 +51,7 @@ std::vector CreateArgsFromAppPacket(const AppPacket* app_packet) { } // namespace LoaderExecutor::LoaderExecutor() - : Executor(this), process_pool_(new ProcessPool(2, this)) {} + : Executor(this), process_pool_(new ProcessPool("loader", 1, this)) {} LoaderExecutor& LoaderExecutor::GetInst() { static LoaderExecutor inst; @@ -62,8 +62,8 @@ pid_t LoaderExecutor::Execute(const LoaderContext* loader_context, int priority) { loader_argv_ = CreateLoaderArgv(loader_context); if (process_pool_->IsPrepared()) { - auto app_packet = CreateAppPacketFromArgs(loader_argv_); - return process_pool_->Execute(std::move(app_packet)); + auto parcel = CreateParcelFromArgv(loader_argv_); + return process_pool_->Execute(parcel); } return Executor::Execute(priority); @@ -100,9 +100,9 @@ void LoaderExecutor::OnExecution() { } } -void LoaderExecutor::OnRequestReceived(std::shared_ptr app_packet) { +void LoaderExecutor::OnRequestReceived(tizen_base::Parcel* parcel) { _W("Request received"); - loader_argv_ = CreateArgsFromAppPacket(app_packet.get()); + loader_argv_ = CreateArgvFromParcel(parcel); OnExecution(); } diff --git a/src/launchpad-process-pool/loader_executor.hh b/src/launchpad-process-pool/loader_executor.hh index c3b2664..110ffef 100644 --- a/src/launchpad-process-pool/loader_executor.hh +++ b/src/launchpad-process-pool/loader_executor.hh @@ -47,7 +47,7 @@ class LoaderExecutor : public Executor::Delegator, ~LoaderExecutor() = default; void OnExecution() override; - void OnRequestReceived(std::shared_ptr app_packet) override; + void OnRequestReceived(tizen_base::Parcel* parcel) override; std::vector CreateLoaderArgv( const LoaderContext* loader_context); diff --git a/src/launchpad-process-pool/process_pool.cc b/src/launchpad-process-pool/process_pool.cc index 19fbcc6..df32ce6 100644 --- a/src/launchpad-process-pool/process_pool.cc +++ b/src/launchpad-process-pool/process_pool.cc @@ -25,15 +25,20 @@ #include -#include -#include - +#include "launchpad-process-pool/launchpad_args.hh" #include "launchpad-process-pool/log_private.hh" namespace launchpad { +namespace { + +constexpr const char kProcessPool[] = "process-pool"; + +} // namespace -ProcessPool::ProcessPool(int num_processes, IEvent* event_listener = nullptr) +ProcessPool::ProcessPool(std::string name, int num_processes, + IEvent* event_listener = nullptr) : Executor(this), + name_(std::move(name)), num_processes_(num_processes), event_listener_(event_listener) { PrepareProcess(); @@ -47,14 +52,14 @@ bool ProcessPool::IsPrepared() const { return !queue_.empty(); } -pid_t ProcessPool::Execute(std::shared_ptr app_packet) { +pid_t ProcessPool::Execute(const tizen_base::Parcel& parcel) { SetTimer(); if (!IsPrepared()) return -1; auto process = std::move(queue_.front()); queue_.pop(); - process->Send(std::move(app_packet)); + process->Send(parcel); return process->GetPid(); } @@ -77,10 +82,15 @@ pid_t ProcessPool::Process::GetPid() const { return pid_; } -int ProcessPool::Process::Send(std::shared_ptr app_packet) { +int ProcessPool::Process::Send(const tizen_base::Parcel& parcel) { _W("Send execution request. process ID: %d", pid_); - tizen_base::Parcel parcel; - app_packet->WriteToParcel(&parcel); + size_t data_size = parcel.GetDataSize(); + int ret = socket_->Write(static_cast(&data_size), sizeof(data_size)); + if (ret != 0) { + _E("Write() is failed. error(%d)", ret); + return ret; + } + return socket_->Write(parcel.GetData(), parcel.GetDataSize()); } @@ -94,7 +104,11 @@ void ProcessPool::Process::Kill() { void ProcessPool::OnExecution() { _W("Candidate Process"); - Procfs::SetComm(getpid(), "process-pool+"); + char** args = LaunchpadArgs::GetInst().GetArgs(); + size_t length = strlen(args[0]); + memset(args[0], '\0', length); + snprintf(args[0], length, "/usr/bin/%s <%s>", kProcessPool, name_.c_str()); + close(pipe_fd_[1]); int ret = WaitForRequest(std::make_unique(pipe_fd_[0])); exit(ret); @@ -110,10 +124,10 @@ void ProcessPool::PrepareProcess() { return; } - if (fcntl(pipe_fd_[0], F_SETPIPE_SZ, AppPacket::kMaxPacketSize) == -1) + if (fcntl(pipe_fd_[0], F_SETPIPE_SZ, Socket::kSocketMaxBufferSize) == -1) _E("Failed to set pipe size. errno(%d)", errno); - if (fcntl(pipe_fd_[1], F_SETPIPE_SZ, AppPacket::kMaxPacketSize) == -1) + if (fcntl(pipe_fd_[1], F_SETPIPE_SZ, Socket::kSocketMaxBufferSize) == -1) _E("Failed to set pipe size. errno(%d)", errno); pid_t pid = Executor::Execute(); @@ -130,34 +144,28 @@ void ProcessPool::PrepareProcess() { } int ProcessPool::WaitForRequest(std::unique_ptr socket) { - auto app_packet = std::make_shared(); + tizen_base::Parcel parcel; int ret = 0; do { - char buf[AppPacket::GetHeaderSize()] = { 0, }; - ret = socket->Read(buf, sizeof(buf)); + size_t data_size = 0; + ret = socket->Read(static_cast(&data_size), sizeof(data_size)); if (ret != 0) { _E("Failed to read from socket. error(%d)", ret); return -1; } - tizen_base::Parcel parcel(buf, sizeof(buf)); - app_packet->ReadFromParcel(&parcel); - - std::vector data; - data.resize(app_packet->GetDataSize()); - ret = socket->Read(data.data(), app_packet->GetDataSize()); + std::vector data(data_size); + ret = socket->Read(data.data(), data.size()); if (ret != 0) { _E("Failed to read from socket. error(%d)", ret); return -1; } parcel.Write(data.data(), data.size()); - parcel.ResetReader(); - app_packet->ReadFromParcel(&parcel); } while (ret != 0); if (event_listener_ != nullptr) - event_listener_->OnRequestReceived(std::move(app_packet)); + event_listener_->OnRequestReceived(&parcel); return 0; } diff --git a/src/launchpad-process-pool/process_pool.hh b/src/launchpad-process-pool/process_pool.hh index 85b87fa..d38e327 100644 --- a/src/launchpad-process-pool/process_pool.hh +++ b/src/launchpad-process-pool/process_pool.hh @@ -22,9 +22,10 @@ #include #include +#include #include -#include +#include #include #include "launchpad-process-pool/executor.hh" @@ -37,14 +38,15 @@ class ProcessPool : public Executor::Delegator, class IEvent { public: virtual ~IEvent() = default; - virtual void OnRequestReceived(std::shared_ptr app_packet) = 0; + virtual void OnRequestReceived(tizen_base::Parcel* parcel) = 0; }; - explicit ProcessPool(int num_processes, IEvent* event_listener); + explicit ProcessPool(std::string name, int num_processes, + IEvent* event_listener); virtual ~ProcessPool(); bool IsPrepared() const; - pid_t Execute(std::shared_ptr app_packet); + pid_t Execute(const tizen_base::Parcel& parcel); void Dispose(); void SetTimer(); @@ -54,7 +56,7 @@ class ProcessPool : public Executor::Delegator, Process(pid_t pid, int fd); pid_t GetPid() const; - int Send(std::shared_ptr app_packet); + int Send(const tizen_base::Parcel& parcel); void Kill(); private: @@ -69,6 +71,7 @@ class ProcessPool : public Executor::Delegator, static gboolean OnTimeout(gpointer user_data); private: + std::string name_; int num_processes_; IEvent* event_listener_; int pipe_fd_[2] = { -1, -1 }; diff --git a/src/launchpad-process-pool/signal_manager.cc b/src/launchpad-process-pool/signal_manager.cc index 3839121..5340025 100644 --- a/src/launchpad-process-pool/signal_manager.cc +++ b/src/launchpad-process-pool/signal_manager.cc @@ -194,8 +194,8 @@ void SignalManager::OnSigchld(pid_t pid, int status) { HandleSigchld(pid); } -void SignalManager::OnHydraSigchld(pid_t pid) { - _W("pid: %d", pid); +void SignalManager::OnHydraSigchld(pid_t pid, int status) { + _W("pid: %d, status: %d", pid, status); HandleSigchld(pid); } diff --git a/src/launchpad-process-pool/signal_manager.hh b/src/launchpad-process-pool/signal_manager.hh index 23bef10..0af613d 100644 --- a/src/launchpad-process-pool/signal_manager.hh +++ b/src/launchpad-process-pool/signal_manager.hh @@ -63,7 +63,7 @@ class SignalManager : public SigchldEvent::IEvent, int BlockSigchld(); void OnSigchld(pid_t pid, int status) override; - void OnHydraSigchld(pid_t pid) override; + void OnHydraSigchld(pid_t pid, int status) override; private: bool disposed_ = true; diff --git a/src/lib/CMakeLists.txt b/src/lib/CMakeLists.txt index 25baf15..65cdaca 100644 --- a/src/lib/CMakeLists.txt +++ b/src/lib/CMakeLists.txt @@ -1,3 +1,4 @@ ADD_SUBDIRECTORY(launchpad) ADD_SUBDIRECTORY(launchpad-common) +ADD_SUBDIRECTORY(launchpad-glib) ADD_SUBDIRECTORY(launchpad-hydra) diff --git a/src/lib/common/inc/launchpad_types.h b/src/lib/common/inc/launchpad_types.h index fc822d7..29157a8 100644 --- a/src/lib/common/inc/launchpad_types.h +++ b/src/lib/common/inc/launchpad_types.h @@ -38,6 +38,7 @@ typedef enum loader_arg { typedef enum hydra_cmd { LAUNCH_CANDIDATE, + LAUNCH_CANDIDATE_WITH_ARGS, } hydra_cmd_e; typedef enum launchpad_loader_type { diff --git a/src/lib/launchpad-common/CMakeLists.txt b/src/lib/launchpad-common/CMakeLists.txt index a6a6ef1..bcad9a0 100644 --- a/src/lib/launchpad-common/CMakeLists.txt +++ b/src/lib/launchpad-common/CMakeLists.txt @@ -13,12 +13,10 @@ TARGET_INCLUDE_DIRECTORIES(${TARGET_LAUNCHPAD_COMMON} PUBLIC ) APPLY_PKG_CONFIG(${TARGET_LAUNCHPAD_COMMON} PUBLIC - BUNDLE_DEPS CAPI_SYSTEM_RESOURCE_DEPS DLOG_DEPS - GIO_DEPS + DLOG_REDIRECT_STDOUT_DEPS INIPARSER_DEPS - VCONF_DEPS PARCEL_DEPS ) diff --git a/src/lib/launchpad-common/app_packet.cc b/src/lib/launchpad-common/app_packet.cc deleted file mode 100644 index 519ac4b..0000000 --- a/src/lib/launchpad-common/app_packet.cc +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "launchpad-common/app_packet.hh" - -#include - -#include - -namespace launchpad { - -AppPacket::AppPacket(int command, int option, std::vector data) - : command_(command), - option_(option), - data_size_(static_cast(data.size())), - data_(std::move(data)) {} - -void AppPacket::WriteToParcel(tizen_base::Parcel* parcel) const { - parcel->WriteInt32(command_); - parcel->WriteInt32(option_); - parcel->WriteInt32(data_size_); - if (data_size_ > 0) - parcel->Write(data_.data(), data_.size()); -} - -void AppPacket::ReadFromParcel(tizen_base::Parcel* parcel) { - parcel->ReadInt32(&command_); - parcel->ReadInt32(&option_); - parcel->ReadInt32(&data_size_); - if (data_size_ > 0) { - data_.resize(data_size_); - parcel->Read(data_.data(), data_.size()); - } -} - -int AppPacket::GetCommand() const { - return command_; -} - -int AppPacket::GetOption() const { - return option_; -} - -int AppPacket::GetDataSize() const { - return data_size_; -} - -const std::vector& AppPacket::GetData() const { - return data_; -} - -} // namespace launchpad diff --git a/src/lib/launchpad-common/hydra_request.cc b/src/lib/launchpad-common/hydra_request.cc new file mode 100644 index 0000000..3d4fc64 --- /dev/null +++ b/src/lib/launchpad-common/hydra_request.cc @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "launchpad-common/hydra_request.hh" + +#include + +namespace launchpad { + +HydraRequest::HydraRequest(int cmd) : cmd_(cmd) {} + +HydraRequest::HydraRequest(int cmd, int argc, char** argv) + : cmd_(cmd), argc_(argc), argv_(argv) {} + +int HydraRequest::GetCommand() const { + return cmd_; +} + +int HydraRequest::GetArgc() const { + return argc_; +} + +char** HydraRequest::GetArgv() const { + return argv_; +} + +void HydraRequest::WriteToParcel(tizen_base::Parcel* parcel) const { + parcel->WriteInt32(cmd_); + parcel->WriteInt32(argc_); + for (int i = 0; i < argc_; ++i) + parcel->WriteCString(argv_[i]); +} + +void HydraRequest::ReadFromParcel(tizen_base::Parcel* parcel) { + for (int i = 0; i < argc_; ++i) + free(argv_[i]); + + free(argv_); + argv_ = nullptr; + + parcel->ReadInt32(&cmd_); + parcel->ReadInt32(&argc_); + if (argc_ == 0) + return; + + argv_ = static_cast(calloc(argc_ + 1, sizeof(char*))); + if (argv_ == nullptr) + return; + + for (int i = 0; i < argc_; ++i) + parcel->ReadCString(&argv_[i]); +} + +} // namespace launchpad diff --git a/src/lib/launchpad-common/app_packet.hh b/src/lib/launchpad-common/hydra_request.hh similarity index 57% rename from src/lib/launchpad-common/app_packet.hh rename to src/lib/launchpad-common/hydra_request.hh index 07ba8b9..f6fdf79 100644 --- a/src/lib/launchpad-common/app_packet.hh +++ b/src/lib/launchpad-common/hydra_request.hh @@ -14,13 +14,12 @@ * limitations under the License. */ -#ifndef LIB_LAUNCHPAD_COMMON_APP_PACKET_HH_ -#define LIB_LAUNCHPAD_COMMON_APP_PACKET_HH_ +#ifndef LIB_LAUNCHPAD_COMMON_HYDRA_REQUEST_HH_ +#define LIB_LAUNCHPAD_COMMON_HYDRA_REQUEST_HH_ -#include -#include -#include +#include +#include #include #undef EXPORT_API @@ -28,33 +27,26 @@ namespace launchpad { -class EXPORT_API AppPacket : public tizen_base::Parcelable { +class EXPORT_API HydraRequest : public tizen_base::Parcelable { public: - AppPacket() = default; - AppPacket(int command, int option, std::vector data); - virtual ~AppPacket() = default; - - void WriteToParcel(tizen_base::Parcel* parcel) const override; - void ReadFromParcel(tizen_base::Parcel* parcel) override; - - static constexpr size_t GetHeaderSize() { - return sizeof(int) + sizeof(int) + sizeof(int); - } + explicit HydraRequest(int cmd); + HydraRequest(int cmd, int argc, char** argv); + HydraRequest() = default; + virtual ~HydraRequest() = default; int GetCommand() const; - int GetOption() const; - int GetDataSize() const; - const std::vector& GetData() const; + int GetArgc() const; + char** GetArgv() const; - static constexpr int kMaxPacketSize = 131071; + void WriteToParcel(tizen_base::Parcel* parcel) const override; + void ReadFromParcel(tizen_base::Parcel* parcel) override; private: - int command_ = 0; - int option_ = 0; - int data_size_ = 0; - std::vector data_; + int cmd_; + int argc_ = 0; + char** argv_ = nullptr; }; } // namespace launchpad -#endif // LIB_LAUNCHPAD_COMMON_APP_PACKET_HH_ +#endif // LIB_LAUNCHPAD_COMMON_HYDRA_REQUEST_HH_ diff --git a/src/lib/launchpad-common/sigchld_info.cc b/src/lib/launchpad-common/sigchld_info.cc new file mode 100644 index 0000000..1961b81 --- /dev/null +++ b/src/lib/launchpad-common/sigchld_info.cc @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "launchpad-common/sigchld_info.hh" + +namespace launchpad { + +SigchldInfo::SigchldInfo(pid_t pid, int status) + : pid_(pid), status_(status) {} + +void SigchldInfo::WriteToParcel(tizen_base::Parcel* parcel) const { + parcel->WriteInt32(pid_); + parcel->WriteInt32(status_); +} + +void SigchldInfo::ReadFromParcel(tizen_base::Parcel* parcel) { + parcel->ReadInt32(&pid_); + parcel->ReadInt32(&status_); +} + +pid_t SigchldInfo::GetPid() const { + return pid_; +} + +int SigchldInfo::GetStatus() const { + return status_; +} + +} // namespace launchpad diff --git a/src/lib/launchpad-common/sigchld_info.hh b/src/lib/launchpad-common/sigchld_info.hh new file mode 100644 index 0000000..9a09f52 --- /dev/null +++ b/src/lib/launchpad-common/sigchld_info.hh @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef LIB_LAUNCHPAD_COMMON_SIGCHLD_INFO_HH_ +#define LIB_LAUNCHPAD_COMMON_SIGCHLD_INFO_HH_ + +#include + +#include +#include + +#undef EXPORT_API +#define EXPORT_API __attribute__((visibility("default"))) + +namespace launchpad { + +class EXPORT_API SigchldInfo : public tizen_base::Parcelable { + public: + SigchldInfo(pid_t pid, int status); + SigchldInfo() = default; + virtual ~SigchldInfo() = default; + + void WriteToParcel(tizen_base::Parcel* parcel) const override; + void ReadFromParcel(tizen_base::Parcel* parcel) override; + + pid_t GetPid() const; + int GetStatus() const; + + private: + pid_t pid_ = -1; + int status_ = -1; +}; + +} // namespace launchpad + +#endif // LIB_LAUNCHPAD_COMMON_SIGCHLD_INFO_HH_ diff --git a/src/lib/launchpad-common/socket.hh b/src/lib/launchpad-common/socket.hh index 3078e96..aa2a8ae 100644 --- a/src/lib/launchpad-common/socket.hh +++ b/src/lib/launchpad-common/socket.hh @@ -38,6 +38,8 @@ class EXPORT_API Socket { int GetFd() const; int RemoveFd(); + static constexpr int kSocketMaxBufferSize = 131071; + private: int fd_; }; diff --git a/src/lib/launchpad-common/stdio.cc b/src/lib/launchpad-common/stdio.cc new file mode 100644 index 0000000..6d3d805 --- /dev/null +++ b/src/lib/launchpad-common/stdio.cc @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "launchpad-common/stdio.hh" + +#include +#include +#include +#include +#include + +#include "launchpad-common/log_private.hh" + +namespace launchpad { +namespace { + +void Redirect(int fd, const char* ident, int priority) { + int ret = dlog_connect_fd(LOG_ID_APPS, fd, ident, priority); + if (ret != 0) + _E("dlog_connect_fd() is failed. error(%d)", ret); +} + +} // namespace + +void Stdio::Setup() { + Redirect(STDOUT_FILENO, "STDOUT", DLOG_WARN); + Redirect(STDERR_FILENO, "STDERR", DLOG_ERROR); +} + +} // namespace launchpad diff --git a/src/lib/launchpad-hydra/inc/launchpad_sigchld.h b/src/lib/launchpad-common/stdio.hh similarity index 60% rename from src/lib/launchpad-hydra/inc/launchpad_sigchld.h rename to src/lib/launchpad-common/stdio.hh index bd4b968..bd6893d 100644 --- a/src/lib/launchpad-hydra/inc/launchpad_sigchld.h +++ b/src/lib/launchpad-common/stdio.hh @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020 Samsung Electronics Co., Ltd All Rights Reserved + * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,17 +14,19 @@ * limitations under the License. */ -#ifndef __LAUNCHPAD_SIGCHLD_H__ -#define __LAUNCHPAD_SIGCHLD_H__ +#ifndef LIB_LAUNCHPAD_COMMON_STDIO_HH_ +#define LIB_LAUNCHPAD_COMMON_STDIO_HH_ -#ifdef __cplusplus -extern "C" { -#endif +#undef EXPORT_API +#define EXPORT_API __attribute__((visibility("default"))) -int _sigchld_send(int pid); +namespace launchpad { -#ifdef __cplusplus -} -#endif +class EXPORT_API Stdio { + public: + static void Setup(); +}; -#endif /* __LAUNCHPAD_SIGCHLD_H__ */ +} // namespace launchpad + +#endif // LIB_LAUNCHPAD_COMMON_STDIO_HH_ diff --git a/src/lib/launchpad-glib/CMakeLists.txt b/src/lib/launchpad-glib/CMakeLists.txt new file mode 100644 index 0000000..2c519fa --- /dev/null +++ b/src/lib/launchpad-glib/CMakeLists.txt @@ -0,0 +1,37 @@ +AUX_SOURCE_DIRECTORY(${CMAKE_CURRENT_SOURCE_DIR}/ LAUNCHPAD_GLIB_SRCS) + +ADD_LIBRARY(${TARGET_LAUNCHPAD_GLIB} SHARED ${LAUNCHPAD_GLIB_SRCS}) + +SET_TARGET_PROPERTIES(${TARGET_LAUNCHPAD_GLIB} PROPERTIES + SOVERSION ${MAJORVER}) +SET_TARGET_PROPERTIES(${TARGET_LAUNCHPAD_GLIB} PROPERTIES + VERSION ${VERSION}) + +TARGET_INCLUDE_DIRECTORIES(${TARGET_LAUNCHPAD_GLIB} PUBLIC + ${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_CURRENT_SOURCE_DIR}/../ +) + +APPLY_PKG_CONFIG(${TARGET_LAUNCHPAD_GLIB} PUBLIC + BUNDLE_DEPS + DLOG_DEPS + GIO_DEPS + VCONF_DEPS +) + +TARGET_LINK_LIBRARIES(${TARGET_LAUNCHPAD_GLIB} PUBLIC + ${TARGET_LAUNCHPAD_COMMON} "-ldl") + +INSTALL(TARGETS ${TARGET_LAUNCHPAD_GLIB} DESTINATION ${LIB_INSTALL_DIR} + COMPONENT RuntimeLibraries) +INSTALL(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/ + DESTINATION include/launchpad-glib + FILES_MATCHING + PATTERN "*_private.hh" EXCLUDE + PATTERN "*.hh" +) + +CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/pkgconfig/liblaunchpad-glib.pc.in + ${CMAKE_CURRENT_SOURCE_DIR}/pkgconfig/liblaunchpad-glib.pc @ONLY) +INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/pkgconfig/liblaunchpad-glib.pc + DESTINATION ${LIB_INSTALL_DIR}/pkgconfig) diff --git a/src/lib/launchpad-common/app_info.cc b/src/lib/launchpad-glib/app_info.cc similarity index 78% rename from src/lib/launchpad-common/app_info.cc rename to src/lib/launchpad-glib/app_info.cc index b689ee5..c286f6b 100644 --- a/src/lib/launchpad-common/app_info.cc +++ b/src/lib/launchpad-glib/app_info.cc @@ -14,11 +14,13 @@ * limitations under the License. */ -#include "launchpad-common/app_info.hh" +#include "launchpad-glib/app_info.hh" + +#include #include -#include "launchpad-common/aul_keys.hh" +#include namespace launchpad { @@ -179,6 +181,49 @@ const tizen_base::Bundle& AppInfo::GetBundle() const { return b_; } +void AppInfo::WriteToParcel(tizen_base::Parcel* parcel) const { + parcel->WriteString(app_id_); + parcel->WriteString(app_path_); + parcel->WriteString(original_app_path_); + parcel->WriteString(pkg_type_); + parcel->WriteString(app_type_); + parcel->WriteString(hwacc_); + parcel->WriteString(taskmanage_); + parcel->WriteString(pkg_id_); + parcel->WriteString(comp_type_); + parcel->WriteString(internal_pool_); + parcel->WriteString(root_path_); + parcel->WriteString(loader_name_); + parcel->WriteBool(global_); + + bundle_raw* b_raw = nullptr; + int len = 0; + bundle_encode(b_.GetHandle(), &b_raw, &len); + std::string raw(b_raw != nullptr ? reinterpret_cast(b_raw) : ""); + bundle_free_encoded_rawdata(&b_raw); + parcel->WriteString(raw); +} + +void AppInfo::ReadFromParcel(tizen_base::Parcel* parcel) { + app_id_ = parcel->ReadString(); + app_path_ = parcel->ReadString(); + original_app_path_ = parcel->ReadString(); + pkg_type_ = parcel->ReadString(); + app_type_ = parcel->ReadString(); + hwacc_ = parcel->ReadString(); + taskmanage_ = parcel->ReadString(); + pkg_id_ = parcel->ReadString(); + comp_type_ = parcel->ReadString(); + internal_pool_ = parcel->ReadString(); + root_path_ = parcel->ReadString(); + loader_name_ = parcel->ReadString(); + parcel->ReadBool(&global_); + + auto raw = parcel->ReadString(); + if (!raw.empty()) + b_ = tizen_base::Bundle(raw); +} + AppInfo::AppInfo(std::string app_id, std::string app_path, std::string original_app_path, std::string pkg_type, std::string app_type, std::string hwacc, std::string taskmanage, std::string pkg_id, diff --git a/src/lib/launchpad-common/app_info.hh b/src/lib/launchpad-glib/app_info.hh similarity index 90% rename from src/lib/launchpad-common/app_info.hh rename to src/lib/launchpad-glib/app_info.hh index 0e5ff06..9e6d27a 100644 --- a/src/lib/launchpad-common/app_info.hh +++ b/src/lib/launchpad-glib/app_info.hh @@ -14,20 +14,23 @@ * limitations under the License. */ -#ifndef LIB_LAUNCHPAD_COMMON_APP_INFO_HH_ -#define LIB_LAUNCHPAD_COMMON_APP_INFO_HH_ +#ifndef LIB_LAUNCHPAD_GLIB_APP_INFO_HH_ +#define LIB_LAUNCHPAD_GLIB_APP_INFO_HH_ #include #include #include +#include +#include + #undef EXPORT_API #define EXPORT_API __attribute__((visibility("default"))) namespace launchpad { -class EXPORT_API AppInfo { +class EXPORT_API AppInfo : public tizen_base::Parcelable { public: class Builder { public: @@ -64,6 +67,7 @@ class EXPORT_API AppInfo { tizen_base::Bundle b_; }; + AppInfo() = default; virtual ~AppInfo() = default; static AppInfo* Create(tizen_base::Bundle b); @@ -83,6 +87,9 @@ class EXPORT_API AppInfo { const bool IsGlobal() const; const tizen_base::Bundle& GetBundle() const; + void WriteToParcel(tizen_base::Parcel* parcel) const override; + void ReadFromParcel(tizen_base::Parcel* parcel) override; + private: AppInfo(std::string app_id, std::string app_path, std::string original_app_path, std::string pkg_type, std::string app_type, @@ -109,4 +116,4 @@ class EXPORT_API AppInfo { } // namespace launchpad -#endif // LIB_LAUNCHPAD_COMMON_APP_INFO_HH_ +#endif // LIB_LAUNCHPAD_GLIB_APP_INFO_HH_ diff --git a/src/lib/launchpad-common/io_channel.cc b/src/lib/launchpad-glib/io_channel.cc similarity index 95% rename from src/lib/launchpad-common/io_channel.cc rename to src/lib/launchpad-glib/io_channel.cc index 10ddbb9..8ac0531 100644 --- a/src/lib/launchpad-common/io_channel.cc +++ b/src/lib/launchpad-glib/io_channel.cc @@ -14,13 +14,13 @@ * limitations under the License. */ -#include "launchpad-common/io_channel.hh" +#include "launchpad-glib/io_channel.hh" #include #include -#include "launchpad-common/log_private.hh" +#include "launchpad-glib/log_private.hh" namespace launchpad { diff --git a/src/lib/launchpad-common/io_channel.hh b/src/lib/launchpad-glib/io_channel.hh similarity index 92% rename from src/lib/launchpad-common/io_channel.hh rename to src/lib/launchpad-glib/io_channel.hh index e65c168..0936754 100644 --- a/src/lib/launchpad-common/io_channel.hh +++ b/src/lib/launchpad-glib/io_channel.hh @@ -14,8 +14,8 @@ * limitations under the License. */ -#ifndef LIB_LAUNCHPAD_COMMON_IO_CHANNEL_HH_ -#define LIB_LAUNCHPAD_COMMON_IO_CHANNEL_HH_ +#ifndef LIB_LAUNCHPAD_GLIB_IO_CHANNEL_HH_ +#define LIB_LAUNCHPAD_GLIB_IO_CHANNEL_HH_ #include @@ -64,4 +64,4 @@ class EXPORT_API IOChannel { } // namespace launchpad -#endif // LIB_LAUNCHPAD_COMMON_IO_CHANNEL_HH_ +#endif // LIB_LAUNCHPAD_GLIB_IO_CHANNEL_HH_ diff --git a/src/lib/launchpad-glib/log_private.hh b/src/lib/launchpad-glib/log_private.hh new file mode 100644 index 0000000..7484e16 --- /dev/null +++ b/src/lib/launchpad-glib/log_private.hh @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef LIB_LAUNCHPAD_GLIB_LOG_PRIVATE_HH_ +#define LIB_LAUNCHPAD_GLIB_LOG_PRIVATE_HH_ + +#include + +#undef LOG_TAG +#define LOG_TAG "LAUNCHPAD_GLIB" + +#undef _E +#define _E LOGE + +#undef _W +#define _W LOGW + +#undef _I +#define _I LOGI + +#undef _D +#define _D LOGD + +#endif // LIB_LAUNCHPAD_GLIB_LOG_PRIVATE_HH_ diff --git a/src/lib/launchpad-glib/pkgconfig/liblaunchpad-glib.pc.in b/src/lib/launchpad-glib/pkgconfig/liblaunchpad-glib.pc.in new file mode 100644 index 0000000..5f27cae --- /dev/null +++ b/src/lib/launchpad-glib/pkgconfig/liblaunchpad-glib.pc.in @@ -0,0 +1,13 @@ +# Package Information for pkg-config + +prefix=/usr +exec_prefix=@EXEC_PREFIX@ +libdir=@LIB_INSTALL_DIR@ +includedir=@INCLUDE_INSTALL_DIR@ + +Name: liblaunchpad-glib +Description: launchpad glib library +Version: @VERSION@ +Requires: bundle dlog parcel launchpad-common +Libs: -L${libdir} -llaunchpad-glib +Cflags: -I${includedir} -I${includedir}/launchpad-glib diff --git a/src/lib/launchpad-common/plugin.cc b/src/lib/launchpad-glib/plugin.cc similarity index 95% rename from src/lib/launchpad-common/plugin.cc rename to src/lib/launchpad-glib/plugin.cc index d8f3778..f9dfdd5 100644 --- a/src/lib/launchpad-common/plugin.cc +++ b/src/lib/launchpad-glib/plugin.cc @@ -14,13 +14,13 @@ * limitations under the License. */ -#include "launchpad-common/plugin.hh" +#include "launchpad-glib/plugin.hh" #include #include -#include "launchpad-common/log_private.hh" +#include "launchpad-glib/log_private.hh" namespace fs = std::filesystem; diff --git a/src/lib/launchpad-common/plugin.hh b/src/lib/launchpad-glib/plugin.hh similarity index 88% rename from src/lib/launchpad-common/plugin.hh rename to src/lib/launchpad-glib/plugin.hh index 57b1a8b..29fc215 100644 --- a/src/lib/launchpad-common/plugin.hh +++ b/src/lib/launchpad-glib/plugin.hh @@ -14,8 +14,8 @@ * limitations under the License. */ -#ifndef LIB_LAUNCHPAD_COMMON_PLUGIN_HH_ -#define LIB_LAUNCHPAD_COMMON_PLUGIN_HH_ +#ifndef LIB_LAUNCHPAD_GLIB_PLUGIN_HH_ +#define LIB_LAUNCHPAD_GLIB_PLUGIN_HH_ #include @@ -33,4 +33,4 @@ class EXPORT_API Plugin { } // namespace launchpad -#endif // LIB_LAUNCHPAD_COMMON_PLUGIN_HH_ +#endif // LIB_LAUNCHPAD_GLIB_PLUGIN_HH_ diff --git a/src/lib/launchpad-common/util.cc b/src/lib/launchpad-glib/util.cc similarity index 97% rename from src/lib/launchpad-common/util.cc rename to src/lib/launchpad-glib/util.cc index b7ee819..3839f17 100644 --- a/src/lib/launchpad-common/util.cc +++ b/src/lib/launchpad-glib/util.cc @@ -14,7 +14,7 @@ * limitations under the License. */ -#include "launchpad-common/util.hh" +#include "launchpad-glib/util.hh" #include #include @@ -26,8 +26,9 @@ #include #include -#include "launchpad-common/aul_keys.hh" -#include "launchpad-common/log_private.hh" +#include + +#include "launchpad-glib/log_private.hh" namespace fs = std::filesystem; diff --git a/src/lib/launchpad-common/util.hh b/src/lib/launchpad-glib/util.hh similarity index 89% rename from src/lib/launchpad-common/util.hh rename to src/lib/launchpad-glib/util.hh index dec2885..80f9001 100644 --- a/src/lib/launchpad-common/util.hh +++ b/src/lib/launchpad-glib/util.hh @@ -14,8 +14,8 @@ * limitations under the License. */ -#ifndef LIB_LAUNCHPAD_COMMON_UTIL_HH_ -#define LIB_LAUNCHPAD_COMMON_UTIL_HH_ +#ifndef LIB_LAUNCHPAD_GLIB_UTIL_HH_ +#define LIB_LAUNCHPAD_GLIB_UTIL_HH_ #include @@ -33,4 +33,4 @@ class EXPORT_API Util { } // namespace launchpad -#endif // LIB_LAUNCHPAD_COMMON_UTIL_HH_ +#endif // LIB_LAUNCHPAD_GLIB_UTIL_HH_ diff --git a/src/lib/launchpad-common/vconf.cc b/src/lib/launchpad-glib/vconf.cc similarity index 97% rename from src/lib/launchpad-common/vconf.cc rename to src/lib/launchpad-glib/vconf.cc index 85ff0b2..88320dc 100644 --- a/src/lib/launchpad-common/vconf.cc +++ b/src/lib/launchpad-glib/vconf.cc @@ -14,7 +14,7 @@ * limitations under the License. */ -#include "launchpad-common/vconf.hh" +#include "launchpad-glib/vconf.hh" #include @@ -22,7 +22,7 @@ #include #include -#include "launchpad-common/log_private.hh" +#include "launchpad-glib/log_private.hh" namespace launchpad { diff --git a/src/lib/launchpad-common/vconf.hh b/src/lib/launchpad-glib/vconf.hh similarity index 93% rename from src/lib/launchpad-common/vconf.hh rename to src/lib/launchpad-glib/vconf.hh index 3f0e8ab..0242b2b 100644 --- a/src/lib/launchpad-common/vconf.hh +++ b/src/lib/launchpad-glib/vconf.hh @@ -14,8 +14,8 @@ * limitations under the License. */ -#ifndef LIB_LAUNCHPAD_COMMON_VCONF_HH_ -#define LIB_LAUNCHPAD_COMMON_VCONF_HH_ +#ifndef LIB_LAUNCHPAD_GLIB_VCONF_HH_ +#define LIB_LAUNCHPAD_GLIB_VCONF_HH_ #include @@ -83,4 +83,4 @@ class EXPORT_API Vconf { } // namespace launchpad -#endif // LIB_LAUNCHPAD_COMMON_VCONF_HH_ +#endif // LIB_LAUNCHPAD_GLIB_VCONF_HH_ diff --git a/src/lib/launchpad-hydra/CMakeLists.txt b/src/lib/launchpad-hydra/CMakeLists.txt index 6dec4bf..29d092d 100644 --- a/src/lib/launchpad-hydra/CMakeLists.txt +++ b/src/lib/launchpad-hydra/CMakeLists.txt @@ -1,18 +1,15 @@ -AUX_SOURCE_DIRECTORY(${CMAKE_CURRENT_SOURCE_DIR}/src LAUNCHPAD_HYDRA_SRCS) -SET(COMMON_SOCKET_SRCS - ${CMAKE_CURRENT_SOURCE_DIR}/../common/src/launchpad_socket.c) +AUX_SOURCE_DIRECTORY(${CMAKE_CURRENT_SOURCE_DIR} LAUNCHPAD_HYDRA_SRCS) + +ADD_LIBRARY(${TARGET_LAUNCHPAD_HYDRA} SHARED ${LAUNCHPAD_HYDRA_SRCS}) -ADD_LIBRARY(${TARGET_LAUNCHPAD_HYDRA} SHARED - ${COMMON_SOCKET_SRCS} - ${LAUNCHPAD_HYDRA_SRCS}) SET_TARGET_PROPERTIES(${TARGET_LAUNCHPAD_HYDRA} PROPERTIES SOVERSION ${MAJORVER}) SET_TARGET_PROPERTIES(${TARGET_LAUNCHPAD_HYDRA} PROPERTIES VERSION ${VERSION}) TARGET_INCLUDE_DIRECTORIES(${TARGET_LAUNCHPAD_HYDRA} PUBLIC - ${CMAKE_CURRENT_SOURCE_DIR}/inc) -TARGET_INCLUDE_DIRECTORIES(${TARGET_LAUNCHPAD_HYDRA} PUBLIC + ${CMAKE_CURRENT_SOURCE_DIR}/ + ${CMAKE_CURRENT_SOURCE_DIR}/inc ${CMAKE_CURRENT_SOURCE_DIR}/../common/inc) APPLY_PKG_CONFIG(${TARGET_LAUNCHPAD_HYDRA} PUBLIC @@ -20,7 +17,8 @@ APPLY_PKG_CONFIG(${TARGET_LAUNCHPAD_HYDRA} PUBLIC LIBSYSTEMD_DEPS ) -TARGET_LINK_LIBRARIES(${TARGET_LAUNCHPAD_HYDRA} PUBLIC "-ldl") +TARGET_LINK_LIBRARIES(${TARGET_LAUNCHPAD_HYDRA} PUBLIC + ${TARGET_LAUNCHPAD_COMMON} "-ldl" ) INSTALL(TARGETS ${TARGET_LAUNCHPAD_HYDRA} DESTINATION ${LIB_INSTALL_DIR} COMPONENT RuntimeLibraries) diff --git a/src/lib/launchpad-hydra/event_loop.cc b/src/lib/launchpad-hydra/event_loop.cc new file mode 100644 index 0000000..db7ddaa --- /dev/null +++ b/src/lib/launchpad-hydra/event_loop.cc @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "launchpad-hydra/event_loop.hh" + +#include + +#include "launchpad-hydra/log_private.hh" + +namespace launchpad { + +EventLoop& EventLoop::GetInst() { + static EventLoop inst; + inst.Init(); + return inst; +} + +EventLoop::~EventLoop() { Dispose(); } + +void EventLoop::Init() { + if (!disposed_) + return; + + int ret = sd_event_default(&event_); + if (ret < 0) { + _E("sd_event_default() is failed. error(%d)", ret); + return; + } + + disposed_ = false; +} + +void EventLoop::Dispose() { + if (disposed_) + return; + + if (event_ != nullptr) { + sd_event_unref(event_); + event_ = nullptr; + } + + disposed_ = true; +} + +void EventLoop::Run() { + _D("Run main loop"); + int ret = sd_event_loop(event_); + if (ret < 0) { + _E("sd_event_loop() is failed. error(%d)", ret); + THROW(ret); + } +} + +void EventLoop::Exit() { + _D("Exit main loop"); + if (event_ == nullptr) + return; + + sd_event_exit(event_, 0); +} + +sd_event* EventLoop::GetHandle() const { + return event_; +} + +} // namespace launchpad diff --git a/src/lib/launchpad-hydra/event_loop.hh b/src/lib/launchpad-hydra/event_loop.hh new file mode 100644 index 0000000..90efef2 --- /dev/null +++ b/src/lib/launchpad-hydra/event_loop.hh @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef LIB_LAUNCHPAD_HYDRA_EVENT_LOOP_HH_ +#define LIB_LAUNCHPAD_HYDRA_EVENT_LOOP_HH_ + +#include + +namespace launchpad { + +class EventLoop { + public: + static EventLoop& GetInst(); + void Dispose(); + + EventLoop(const EventLoop&) = delete; + EventLoop& operator=(const EventLoop&) = delete; + + void Run(); + void Exit(); + sd_event* GetHandle() const; + + private: + EventLoop() = default; + ~EventLoop(); + void Init(); + + private: + bool disposed_ = true; + sd_event* event_ = nullptr; +}; + +} // namespace launchpad + +#endif // LIB_LAUNCHPAD_HYDRA_EVENT_LOOP_HH_ diff --git a/src/lib/launchpad-hydra/executor.cc b/src/lib/launchpad-hydra/executor.cc new file mode 100644 index 0000000..06fe350 --- /dev/null +++ b/src/lib/launchpad-hydra/executor.cc @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "launchpad-hydra/executor.hh" + +#include +#include +#include +#include + +#include + +#include "launchpad-hydra/log_private.hh" + +namespace launchpad { +namespace { + +constexpr const char kLibSecurityManagerClient[] = + "libsecurity-manager-client.so.3"; + +int SecurityManagerPrepareAppCandidate() { + void* handle = dlopen(kLibSecurityManagerClient, RTLD_LAZY | RTLD_LOCAL); + if (handle == nullptr) { + _E("dlopen() is failed. error: %s", dlerror()); + return -1; + } + + auto security_manager_prepare_app_candidate_func = reinterpret_cast( + dlsym(handle, "security_manager_prepare_app_candidate")); + if (security_manager_prepare_app_candidate_func == nullptr) { + _E("dlsym() is failed"); + return -1; + } + + _W("security_manager_prepare_app_candidate ++"); + int ret = security_manager_prepare_app_candidate_func(); + _W("security_manager_prepare_app_candidate --"); + if (ret != 0) + return -1; + + return 0; +} + +void SetPriority(int priority) { + int ret = setpriority(PRIO_PROCESS, 0, priority); + if (ret != 0) { + _E("Failed to set process priority. priority(%d), errno(%d)", + priority, errno); + } else { + _D("Setting priority(%d) is successful", priority); + } +} + +} // namespace + +Executor::Executor(Executor::Delegator* delegator) : delegator_(delegator) {} + +pid_t Executor::Execute(int argc, char** argv, int priority) { + pid_t pid = fork(); + if (pid == -1) { + _E("Failed to create child process. errno(%d)", errno); + return -1; + } + + if (pid == 0) { + if (priority != 0) + SetPriority(priority); + + int ret = SecurityManagerPrepareAppCandidate(); + if (ret != 0) { + _E("Failed to prepare app candidate process. error(%d)", ret); + exit(1); + } + + Stdio::Setup(); + delegator_->OnExecution(argc, argv); + } + + return pid; +} + +} // namespace launchpad diff --git a/src/lib/launchpad-hydra/executor.hh b/src/lib/launchpad-hydra/executor.hh new file mode 100644 index 0000000..0521c52 --- /dev/null +++ b/src/lib/launchpad-hydra/executor.hh @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef LIB_LAUNCHPAD_HYDRA_EXECUTOR_HH_ +#define LIB_LAUNCHPAD_HYDRA_EXECUTOR_HH_ + +#include + +namespace launchpad { + +class Executor { + public: + class Delegator { + public: + virtual ~Delegator() = default; + virtual void OnExecution(int argc, char** argv) = 0; + }; + + explicit Executor(Delegator* delegator); + virtual ~Executor() = default; + + pid_t Execute(int argc, char** argv, int priority = 0); + + private: + Delegator* delegator_; +}; + +} // namespace launchpad + +#endif // LIB_LAUNCHPAD_HYDRA_EXECUTOR_HH_ diff --git a/src/lib/launchpad-hydra/hydra_args.cc b/src/lib/launchpad-hydra/hydra_args.cc new file mode 100644 index 0000000..b4d0cc8 --- /dev/null +++ b/src/lib/launchpad-hydra/hydra_args.cc @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "launchpad-hydra/hydra_args.hh" + +namespace launchpad { + +HydraArgs& HydraArgs::GetInst() { + static HydraArgs inst; + return inst; +} + +void HydraArgs::Set(int argc, char** args) { + argc_ = argc; + args_ = args; +} + +int HydraArgs::GetArgc() const { + return argc_; +} + +char** HydraArgs::GetArgs() const { + return args_; +} + +} // namespace launchpad diff --git a/src/lib/launchpad-hydra/hydra_args.hh b/src/lib/launchpad-hydra/hydra_args.hh new file mode 100644 index 0000000..111818e --- /dev/null +++ b/src/lib/launchpad-hydra/hydra_args.hh @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef LIB_LAUNCHPAD_HYDRA_HYDRA_ARGS_HH_ +#define LIB_LAUNCHPAD_HYDRA_HYDRA_ARGS_HH_ + +namespace launchpad { + +class HydraArgs { + public: + HydraArgs(const HydraArgs&) = delete; + HydraArgs& operator=(const HydraArgs&) = delete; + + static HydraArgs& GetInst(); + void Set(int argc, char** args); + + int GetArgc() const; + char** GetArgs() const; + + private: + HydraArgs() = default; + ~HydraArgs() = default; + + private: + int argc_ = 0; + char** args_ = 0; +}; + +} // namespace launchpad + +#endif // LIB_LAUNCHPAD_HYDRA_HYDRA_ARGS_HH_ diff --git a/src/lib/launchpad-hydra/io_event.cc b/src/lib/launchpad-hydra/io_event.cc new file mode 100644 index 0000000..b29f02e --- /dev/null +++ b/src/lib/launchpad-hydra/io_event.cc @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "launchpad-hydra/io_event.hh" + +#include + +#include + +#include "launchpad-hydra/log_private.hh" +#include "launchpad-hydra/event_loop.hh" + +namespace launchpad { + +IOEvent::IOEvent(int fd, uint32_t events, IOEvent::IEvent* listener) + : fd_(fd), events_(events), listener_(listener) { + int ret = sd_event_add_io(EventLoop::GetInst().GetHandle(), &event_source_, + fd_, events_, EventCb, this); + if (ret != 0) { + _E("sd_event_add_io() is failed. error(%d)", ret); + THROW(ret); + } +} + +IOEvent::~IOEvent() { + if (event_source_ != nullptr) + sd_event_source_unref(event_source_); + + if (do_close_ && fd_ >= 0) + close(fd_); +} + +void IOEvent::SetCloseOnDestroy(bool do_close) { + do_close_ = do_close; +} + +int IOEvent::EventCb(sd_event_source* source, int fd, + uint32_t revents, void* user_data) { + auto* io_event = static_cast(user_data); + auto* listener = io_event->listener_; + if (listener != nullptr) + listener->OnIOEventReceived(fd, revents); + + return 0; +} + +} // namespace launchpad diff --git a/src/lib/launchpad-hydra/io_event.hh b/src/lib/launchpad-hydra/io_event.hh new file mode 100644 index 0000000..8efee97 --- /dev/null +++ b/src/lib/launchpad-hydra/io_event.hh @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef LIB_LAUNCHPAD_HYDRA_IO_EVENT_HH_ +#define LIB_LAUNCHPAD_HYDRA_IO_EVENT_HH_ + +#include + +namespace launchpad { + +class IOEvent { + public: + class IEvent { + public: + virtual ~IEvent() = default; + virtual void OnIOEventReceived(int fd, uint32_t revents) = 0; + }; + + IOEvent(int fd, uint32_t events, IEvent* listener); + virtual ~IOEvent(); + + IOEvent(const IOEvent&) = delete; + IOEvent& operator=(const IOEvent&) = delete; + + void SetCloseOnDestroy(bool do_close); + + private: + static int EventCb(sd_event_source* source, int fd, uint32_t revents, + void* user_data); + + private: + int fd_; + uint32_t events_; + IEvent* listener_; + sd_event_source* event_source_ = nullptr; + bool do_close_ = true; +}; + +} // namespace launchpad + +#endif // LIB_LAUNCHPAD_HYDRA_IO_EVENT_HH_ diff --git a/src/lib/launchpad-hydra/launchpad_hydra.cc b/src/lib/launchpad-hydra/launchpad_hydra.cc new file mode 100644 index 0000000..8d26dc0 --- /dev/null +++ b/src/lib/launchpad-hydra/launchpad_hydra.cc @@ -0,0 +1,280 @@ +/* + * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "launchpad-hydra/launchpad_hydra.hh" + +#include +#include + +#include +#include + +#include +#include +#include +#include + +#include "common/inc/launchpad_common.h" +#include "common/inc/launchpad_types.h" + +#include "launchpad-hydra/log_private.hh" +#include "launchpad-hydra/event_loop.hh" +#include "launchpad-hydra/hydra_args.hh" + +#ifndef API +#define API __attribute__ ((visibility("default"))) +#endif + +namespace launchpad { +namespace { + +constexpr const char kHydraLoaderSocketName[] = ".hydra-loader"; +constexpr const char kHydraSigchldSocketName[] = ".hydra-sigchld-sock"; +const int kSocketMaxBufferSize = 131071; +const int kLoaderArgMax = 1024; + +} // namespace + +LaunchpadHydra::LaunchpadHydra(int argc, char** argv) + : argc_(argc), argv_(argv) { + if (argc_ < 4) { + _E("Too few arguments"); + THROW(-EINVAL); + } + + type_ = argv_[LOADER_ARG_TYPE][0] - '0'; + if (type_ < 0 || type_ >= LAUNCHPAD_LOADER_TYPE_MAX) { + _E("Invalid argument. type(%d)", type_); + THROW(-EINVAL); + } + + int hydra_mode = argv_[LOADER_ARG_HYDRA][0] - '0'; + _D("Hydra mode: %d", hydra_mode); + if (!hydra_mode) { + _W("Run in non hydra mode"); + THROW(-EINVAL); + } + + argv_[LOADER_ARG_HYDRA] = const_cast("0"); + loader_id_ = atoi(argv_[LOADER_ARG_ID]); + + HydraArgs::GetInst().Set(argc_, argv_); + std::string env = std::to_string( + reinterpret_cast(argv_[0])); + setenv("TIZEN_LOADER_ARGS", env.c_str(), 1); +} + +LaunchpadHydra::~LaunchpadHydra() { +} + +void LaunchpadHydra::Run(hydra_lifecycle_callback_s* callback, + void* user_data) { + if (callback == nullptr) { + _E("Invalid argument"); + THROW(-EINVAL); + } + + callback_ = *callback; + user_data_ = user_data; + OnPreCreate(); + OnCreate(); + + executor_.reset(new LoaderExecutor(this)); + candidate_pid_ = executor_->Execute(argc_, argv_); + _D("Candidate process(%d)", candidate_pid_); + socket_->Send(&candidate_pid_, sizeof(candidate_pid_)); + + EventLoop::GetInst().Run(); + OnTerminate(); +} + +void LaunchpadHydra::Exit() { + EventLoop::GetInst().Exit(); +} + +void LaunchpadHydra::OnPreCreate() { + SignalManager::GetInst().SetEventListener(this); + + try { + std::string endpoint = "/run/aul/daemons/" + std::to_string(getuid()) + + "/" + std::string(kHydraLoaderSocketName) + std::to_string(GetType()) + + "-" + std::to_string(GetLoaderId()); + socket_.reset(new ClientSocket()); + socket_->Connect(endpoint); + socket_->SetReceiveBufferSize(kSocketMaxBufferSize); + socket_->SetReceiveTimeout(5000); + + pid_t pid = getpid(); + int ret = socket_->Send(static_cast(&pid), sizeof(pid)); + if (ret != 0) { + _E("Send() is failed. error(%d)", ret); + THROW(ret); + } + + io_event_.reset(new IOEvent(socket_->GetFd(), EPOLLIN, this)); + io_event_->SetCloseOnDestroy(false); + } catch (const Exception& e) { + _E("Exception occurs. error: %s(%d)", e.what(), e.GetErrorCode()); + THROW(e.GetErrorCode()); + } + + if (callback_.precreate != nullptr) + callback_.precreate(user_data_); +} + +void LaunchpadHydra::OnCreate() { + if (callback_.create != nullptr) + callback_.create(user_data_); +} + +void LaunchpadHydra::OnTerminate() { + if (callback_.terminate != nullptr) { + int ret = callback_.terminate(user_data_); + if (ret < 0) + THROW(ret); + } +} + +int LaunchpadHydra::GetType() const { + return type_; +} + +int LaunchpadHydra::GetLoaderId() const { + return loader_id_; +} + +void LaunchpadHydra::HandleLaunchEvent(const HydraRequest& request) { + pid_t pid = -1; + if (request.GetCommand() == LAUNCH_CANDIDATE) { + _W("LAUNCH_CANDIDATE"); + pid = executor_->Execute(argc_, argv_); + } else if (request.GetCommand() == LAUNCH_CANDIDATE_WITH_ARGS) { + _W("LAUNCH_CANDIDATE_WITH_ARGS"); + pid = executor_->Execute(request.GetArgc(), request.GetArgv()); + } else { + _W("Unknown command(%d)", request.GetCommand()); + } + + _W("Candidate process(%d)", pid); + socket_->Send(static_cast(&pid), sizeof(pid)); +} + +void LaunchpadHydra::HandleSigchldEvent(pid_t pid, int status) { + try { + std::string endpoint = "/run/aul/daemons/" + std::to_string(getuid()) + + "/" + std::string(kHydraSigchldSocketName); + auto socket = std::make_shared(); + socket->Connect(endpoint); + socket->SetSendBufferSize(kSocketMaxBufferSize); + + SigchldInfo info(pid, status); + tizen_base::Parcel parcel; + parcel.WriteParcelable(info); + + size_t data_size = parcel.GetDataSize(); + int ret = socket->Send(static_cast(&data_size), sizeof(data_size)); + if (ret != 0) { + _E("Send() is failed. error(%d)", ret); + return; + } + + ret = socket->Send(parcel.GetData(), data_size); + if (ret != 0) + _E("Send() is failed. error(%d)", ret); + } catch (const Exception& e) { + _E("Exception occurs. error: %s(%d)", e.what(), e.GetErrorCode()); + } +} + +void LaunchpadHydra::OnIOEventReceived(int fd, uint32_t revents) { + _W("IO event received: fd(%d) revents(%u)", fd, revents); + size_t data_size = 0; + int ret = socket_->Receive(&data_size, sizeof(data_size)); + if (ret != 0) { + _E("Recv() is failed. error(%d)", ret); + return; + } + + uint8_t* data = static_cast(malloc(data_size)); + if (data == nullptr) { + _E("malloc() failed"); + return; + } + + std::unique_ptr data_auto(data, free); + ret = socket_->Receive(data, data_size); + if (ret != 0) { + _E("Recv() is failed. error(%d)", ret); + return; + } + + tizen_base::Parcel parcel(data_auto.release(), data_size, false); + HydraRequest request; + parcel.ReadParcelable(&request); + HandleLaunchEvent(request); +} + +void LaunchpadHydra::OnSigchldReceived(pid_t pid, int status) { + _W("Sigchld received. pid(%d), status(%d)", pid, status); + HandleSigchldEvent(pid, status); +} + +void LaunchpadHydra::OnLoaderExecution(int argc, char** argv) { + _D("Run loader. pid(%d)", getpid()); + setsid(); + SignalManager::GetInst().Dispose(); + EventLoop::GetInst().Exit(); + + int ret = 0; + if (callback_.fork != nullptr) { + memset(argv_[0], '\0', kLoaderArgMax); + snprintf(argv_[0], kLoaderArgMax, "%s candidate", argv[0]); + + ret = callback_.fork(argc, argv, user_data_); + } + + exit(ret); +} + +} // namespace launchpad + +namespace { + +std::unique_ptr context; + +} // namespace + +extern "C" API int launchpad_hydra_main(int argc, char** argv, + hydra_lifecycle_callback_s* callback, void* user_data) { + try { + if (!context) + context.reset(new launchpad::LaunchpadHydra(argc, argv)); + + context->Run(callback, user_data); + } catch (const launchpad::Exception& e) { + _E("Exception occurs. error: %s(%d)", e.what(), e.GetErrorCode()); + return e.GetErrorCode(); + } + + return 0; +} + +extern "C" API void launchpad_hydra_exit() { + if (!context) + return; + + context->Exit(); +} diff --git a/src/lib/launchpad-hydra/launchpad_hydra.hh b/src/lib/launchpad-hydra/launchpad_hydra.hh new file mode 100644 index 0000000..43ea3b2 --- /dev/null +++ b/src/lib/launchpad-hydra/launchpad_hydra.hh @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef LIB_LAUNCHPAD_HYDRA_LAUNCHPAD_HYDRA_HH_ +#define LIB_LAUNCHPAD_HYDRA_LAUNCHPAD_HYDRA_HH_ + +#include + +#include +#include + +#include "launchpad-hydra/inc/launchpad_hydra.h" + +#include "launchpad-hydra/loader_executor.hh" +#include "launchpad-hydra/io_event.hh" +#include "launchpad-hydra/signal_manager.hh" + +namespace launchpad { + +class LaunchpadHydra : public IOEvent::IEvent, + public SignalManager::IEvent, + public LoaderExecutor::IEvent { + public: + LaunchpadHydra(int argc, char** argv); + virtual ~LaunchpadHydra(); + + void Run(hydra_lifecycle_callback_s* callback, void* user_data); + void Exit(); + + private: + void OnPreCreate(); + void OnCreate(); + void OnTerminate(); + + int GetType() const; + int GetLoaderId() const; + + void HandleLaunchEvent(const HydraRequest& request); + void HandleSigchldEvent(pid_t pid, int status); + + void OnIOEventReceived(int fd, uint32_t revents) override; + void OnSigchldReceived(pid_t pid, int status) override; + void OnLoaderExecution(int argc, char** argv) override; + + private: + int argc_; + char** argv_; + std::unique_ptr executor_; + int type_ = -1; + int loader_id_ = -1; + hydra_lifecycle_callback_s callback_ = { nullptr, }; + void* user_data_ = nullptr; + std::unique_ptr socket_; + std::unique_ptr io_event_; + pid_t candidate_pid_ = -1; +}; + +} // namespace launchpad + +#endif // LIB_LAUNCHPAD_HYDRA_LAUNCHPAD_HYDRA_HH_ diff --git a/src/lib/launchpad-hydra/loader_executor.cc b/src/lib/launchpad-hydra/loader_executor.cc new file mode 100644 index 0000000..9f5b8b7 --- /dev/null +++ b/src/lib/launchpad-hydra/loader_executor.cc @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "launchpad-hydra/loader_executor.hh" + +#include +#include +#include + +#include + +#include +#include + +#include "launchpad-hydra/log_private.hh" +#include "launchpad-hydra/signal_manager.hh" + +namespace launchpad { +namespace { + +class LoaderArgs : public tizen_base::Parcelable { + public: + explicit LoaderArgs(int argc, char** argv) { + for (int i = 0; i < argc; ++i) + args_.push_back(argv[i]); + } + + LoaderArgs() = default; + ~LoaderArgs() = default; + + void WriteToParcel(tizen_base::Parcel* parcel) const override { + parcel->WriteInt32(args_.size()); + for (size_t i = 0; i < args_.size(); ++i) + parcel->WriteString(args_[i]); + } + + void ReadFromParcel(tizen_base::Parcel* parcel) override { + int data_size = 0; + parcel->ReadInt32(&data_size); + args_.resize(data_size); + for (int i = 0; i < data_size; ++i) + args_[i] = parcel->ReadString(); + } + + const std::vector& GetArgs() const { + return args_; + } + + private: + std::vector args_; +}; + +} // namespace + +LoaderExecutor::LoaderExecutor(IEvent* listener) + : Executor(this), listener_(listener), + process_pool_(new ProcessPool("hydra-loader", 1, this)) {} + +pid_t LoaderExecutor::Execute(int argc, char** argv, int priority) { + if (process_pool_->IsPrepared()) { + LoaderArgs loader_args(argc, argv); + tizen_base::Parcel parcel; + parcel.WriteParcelable(loader_args); + return process_pool_->Execute(parcel); + } + + return Executor::Execute(argc, argv, priority); +} + +void LoaderExecutor::OnExecution(int argc, char** argv) { + for (int i = 0; i < argc; ++i) { + if (i != (argc - 1)) + SECURE_LOGD("loader argument %d : %s##", i, argv[i]); + } + + if (listener_ != nullptr) + listener_->OnLoaderExecution(argc, argv); +} + +void LoaderExecutor::OnRequestReceived(tizen_base::Parcel* parcel) { + _W("Request received"); + LoaderArgs loader_args; + parcel->ReadParcelable(&loader_args); + + auto& args = loader_args.GetArgs(); + std::vector loader_argv(args.size() + 1); + int argc = args.size(); + for (int i = 0; i < argc; ++i) + loader_argv[i] = const_cast(args[i].c_str()); + + OnExecution(argc, loader_argv.data()); +} + +} // namespace launchpad diff --git a/src/lib/launchpad-hydra/loader_executor.hh b/src/lib/launchpad-hydra/loader_executor.hh new file mode 100644 index 0000000..e438580 --- /dev/null +++ b/src/lib/launchpad-hydra/loader_executor.hh @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef LIB_LAUNCHPAD_HYDRA_LOADER_EXECUTOR_HH_ +#define LIB_LAUNCHPAD_HYDRA_LOADER_EXECUTOR_HH_ + +#include +#include +#include + +#include "launchpad-hydra/executor.hh" +#include "launchpad-hydra/process_pool.hh" + +namespace launchpad { + +class LoaderExecutor : public Executor::Delegator, + public Executor, + public ProcessPool::IEvent { + public: + class IEvent { + public: + virtual ~IEvent() = default; + virtual void OnLoaderExecution(int argc, char** argv) = 0; + }; + + explicit LoaderExecutor(IEvent* listener); + ~LoaderExecutor() = default; + + LoaderExecutor(const LoaderExecutor&) = delete; + LoaderExecutor& operator=(const LoaderExecutor&) = delete; + LoaderExecutor(LoaderExecutor&&) = delete; + LoaderExecutor& operator=(LoaderExecutor&&) = delete; + + pid_t Execute(int argc, char** argv, int priority = 0); + + private: + void OnExecution(int argc, char** argv) override; + void OnRequestReceived(tizen_base::Parcel* parcel) override; + + private: + IEvent* listener_; + std::unique_ptr process_pool_; +}; + +} // namespace launchpad + +#endif // LIB_LAUNCHPAD_HYDRA_LOADER_EXECUTOR_HH_ diff --git a/src/lib/launchpad-hydra/log_private.hh b/src/lib/launchpad-hydra/log_private.hh new file mode 100644 index 0000000..3b3f84c --- /dev/null +++ b/src/lib/launchpad-hydra/log_private.hh @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef LIB_LAUNCHPAD_HYDRA_LOG_PRIVATE_HH_ +#define LIB_LAUNCHPAD_HYDRA_LOG_PRIVATE_HH_ + +#include + +#undef LOG_TAG +#define LOG_TAG "LAUNCHPAD_HYDRA" + +#undef _E +#define _E LOGE + +#undef _W +#define _W LOGW + +#undef _I +#define _I LOGI + +#undef _D +#define _D LOGD + +#endif // LIB_LAUNCHPAD_HYDRA_LOG_PRIVATE_HH_ diff --git a/src/lib/launchpad-hydra/process_pool.cc b/src/lib/launchpad-hydra/process_pool.cc new file mode 100644 index 0000000..afe3cfc --- /dev/null +++ b/src/lib/launchpad-hydra/process_pool.cc @@ -0,0 +1,212 @@ +/* + * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "launchpad-hydra/process_pool.hh" + +#include +#include +#include +#include +#include +#include + +#include + +#include "launchpad-hydra/event_loop.hh" +#include "launchpad-hydra/hydra_args.hh" +#include "launchpad-hydra/log_private.hh" + +namespace launchpad { +namespace { + +constexpr const char kProcessPool[] = "process-pool"; +const int kLoaderArgMax = 1024; + +} // namespace + +ProcessPool::ProcessPool(std::string name, int num_processes, + IEvent* event_listener = nullptr) + : Executor(this), + name_(std::move(name)), + num_processes_(num_processes), + event_listener_(event_listener) { + PrepareProcess(); +} + +ProcessPool::~ProcessPool() { + Dispose(); +} + +bool ProcessPool::IsPrepared() const { + return !queue_.empty(); +} + +pid_t ProcessPool::Execute(const tizen_base::Parcel& parcel) { + SetTimer(); + if (!IsPrepared()) + return -1; + + auto process = std::move(queue_.front()); + queue_.pop(); + process->Send(parcel); + return process->GetPid(); +} + +void ProcessPool::Dispose() { + while (!queue_.empty()) { + auto process = std::move(queue_.front()); + queue_.pop(); + process->Kill(); + _D("Kill process(%d)", process->GetPid()); + } + + UnsetTimer(); +} + +ProcessPool::Process::Process(pid_t pid, int fd) + : pid_(pid), socket_(new Socket(fd)) { +} + +pid_t ProcessPool::Process::GetPid() const { + return pid_; +} + +int ProcessPool::Process::Send(const tizen_base::Parcel& parcel) { + _W("Send execution request. process ID: %d", pid_); + size_t data_size = parcel.GetDataSize(); + int ret = socket_->Write(static_cast(&data_size), sizeof(data_size)); + if (ret != 0) { + _E("Write() is failed. error(%d)", ret); + return ret; + } + + return socket_->Write(parcel.GetData(), parcel.GetDataSize()); +} + +void ProcessPool::Process::Kill() { + socket_->Close(); + if (kill(pid_, SIGKILL) == -1) { + _E("Failed to send kill signal to the process. pid(%d), errno(%d)", + pid_, errno); + } +} + +void ProcessPool::OnExecution(int argc, char** argv) { + _W("Candidate Process"); + memset(argv[0], '\0', kLoaderArgMax); + snprintf(argv[0], kLoaderArgMax, "/usr/bin/%s <%s>", + kProcessPool, name_.c_str()); + + close(pipe_fd_[1]); + int ret = WaitForRequest(std::make_unique(pipe_fd_[0])); + exit(ret); +} + +void ProcessPool::PrepareProcess() { + int current_process_count = static_cast(queue_.size()); + for (int i = current_process_count; i < num_processes_; ++i) { + pipe_fd_[0] = -1; + pipe_fd_[1] = -1; + if (pipe(pipe_fd_) == -1) { + _E("Failed to create pipe. errno(%d)", errno); + return; + } + + if (fcntl(pipe_fd_[0], F_SETPIPE_SZ, Socket::kSocketMaxBufferSize) == -1) + _E("Failed to set pipe size. errno(%d)", errno); + + if (fcntl(pipe_fd_[1], F_SETPIPE_SZ, Socket::kSocketMaxBufferSize) == -1) + _E("Failed to set pipe size. errno(%d)", errno); + + auto& inst = HydraArgs::GetInst(); + pid_t pid = Executor::Execute(inst.GetArgc(), inst.GetArgs()); + if (pid == -1) { + _E("Failed to fork process. errno(%d)", errno); + close(pipe_fd_[0]); + close(pipe_fd_[1]); + return; + } + + close(pipe_fd_[0]); + queue_.push(std::make_shared(pid, pipe_fd_[1])); + } +} + +int ProcessPool::WaitForRequest(std::unique_ptr socket) { + tizen_base::Parcel parcel; + int ret = 0; + do { + size_t data_size = 0; + ret = socket->Read(static_cast(&data_size), sizeof(data_size)); + if (ret != 0) { + _E("Failed to read from socket. error(%d)", ret); + return -1; + } + + std::vector data(data_size); + ret = socket->Read(data.data(), data.size()); + if (ret != 0) { + _E("Failed to read from socket. error(%d)", ret); + return -1; + } + + parcel.Write(data.data(), data.size()); + } while (ret != 0); + + if (event_listener_ != nullptr) + event_listener_->OnRequestReceived(&parcel); + + return 0; +} + +void ProcessPool::SetTimer() { + if (timer_ != nullptr) + return; + + uint64_t now; + int ret = sd_event_now(EventLoop::GetInst().GetHandle(), CLOCK_MONOTONIC, + &now); + if (ret < 0) { + _E("sd_event_now() is failed. error(%d)", ret); + return; + } + + ret = sd_event_add_time(EventLoop::GetInst().GetHandle(), &timer_, + CLOCK_MONOTONIC, now + 1000000, 0, OnTimeout, this); + if (ret < 0) { + _E("sd_event_add_time() is failed. error(%d)", ret); + return; + } +} + +void ProcessPool::UnsetTimer() { + if (timer_ != nullptr) { + sd_event_source_set_enabled(timer_, SD_EVENT_OFF); + timer_ = sd_event_source_unref(timer_); + timer_ = nullptr; + } +} + +int ProcessPool::OnTimeout(sd_event_source* source, uint64_t usec, + void* user_data) { + auto* process_pool = static_cast(user_data); + process_pool->PrepareProcess(); + process_pool->UnsetTimer(); + return 0; +} + +} // namespace launchpad + diff --git a/src/lib/launchpad-hydra/process_pool.hh b/src/lib/launchpad-hydra/process_pool.hh new file mode 100644 index 0000000..50fe51d --- /dev/null +++ b/src/lib/launchpad-hydra/process_pool.hh @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef LIB_LAUNCHPAD_HYDRA_PROCESS_POOL_HH_ +#define LIB_LAUNCHPAD_HYDRA_PROCESS_POOL_HH_ + +#include +#include + +#include +#include +#include +#include + +#include +#include + +#include "launchpad-hydra/executor.hh" + +namespace launchpad { + +class ProcessPool : public Executor::Delegator, + public Executor { + public: + class IEvent { + public: + virtual ~IEvent() = default; + virtual void OnRequestReceived(tizen_base::Parcel* parcel) = 0; + }; + + explicit ProcessPool(std::string name, int num_processes, + IEvent* event_listener); + virtual ~ProcessPool(); + + bool IsPrepared() const; + pid_t Execute(const tizen_base::Parcel& parcel); + void Dispose(); + void SetTimer(); + + private: + class Process { + public: + Process(pid_t pid, int fd); + + pid_t GetPid() const; + int Send(const tizen_base::Parcel& parcel); + void Kill(); + + private: + pid_t pid_; + std::unique_ptr socket_; + }; + + void OnExecution(int argc, char** argv) override; + void UnsetTimer(); + void PrepareProcess(); + int WaitForRequest(std::unique_ptr socket); + static int OnTimeout(sd_event_source* source, uint64_t usec, void* user_data); + + private: + std::string name_; + int num_processes_; + IEvent* event_listener_; + int pipe_fd_[2] = { -1, -1 }; + std::queue> queue_; + sd_event_source* timer_ = 0; +}; + +} // namespace launchpad + +#endif // LIB_LAUNCHPAD_HYDRA_PROCESS_POOL_HH_ diff --git a/src/lib/launchpad-hydra/signal_manager.cc b/src/lib/launchpad-hydra/signal_manager.cc new file mode 100644 index 0000000..71daa33 --- /dev/null +++ b/src/lib/launchpad-hydra/signal_manager.cc @@ -0,0 +1,130 @@ +/* + * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "launchpad-hydra/signal_manager.hh" + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "launchpad-hydra/event_loop.hh" +#include "launchpad-hydra/log_private.hh" + +namespace launchpad { + +SignalManager& SignalManager::GetInst() { + static SignalManager inst; + inst.Init(); + return inst; +} + +void SignalManager::Dispose() { + if (disposed_) + return; + + io_event_.reset(); + + if (getpid() != current_pid_) + socket_->RemoveFd(); + + socket_.reset(); + disposed_ = true; +} + +void SignalManager::Init() { + if (!disposed_) + return; + + if (BlockSigchld() != 0) + return; + + int sfd = GetSigchldFd(); + if (sfd < 0) + return; + + socket_.reset(new Socket(sfd)); + io_event_.reset(new IOEvent(socket_->GetFd(), EPOLLIN, this)); + io_event_->SetCloseOnDestroy(false); + disposed_ = false; +} + +void SignalManager::SetEventListener(SignalManager::IEvent* listener) { + listener_ = listener; +} + +void SignalManager::UnblockSigchld() { + if (sigprocmask(SIG_SETMASK, &old_mask_, nullptr) < 0) + _E("sigprocmask(SIG_SETMASK) is failed. errno(%d)", errno); +} + +SignalManager::~SignalManager() { + Dispose(); +} + +int SignalManager::BlockSigchld() { + sigemptyset(&mask_); + sigaddset(&mask_, SIGCHLD); + if (sigprocmask(SIG_BLOCK, &mask_, &old_mask_) < 0) { + int ret = -errno; + _E("sigprocmask(SIG_BLOCK) is failed. errno(%d)", errno); + return ret; + } + + return 0; +} + +int SignalManager::GetSigchldFd() { + int sfd = signalfd(-1, &mask_, SFD_NONBLOCK | SFD_CLOEXEC); + if (sfd < 0) { + sfd = -errno; + _E("signalfd() is failed. errno(%d)", errno); + } + + return sfd; +} + +void SignalManager::OnIOEventReceived(int fd, uint32_t revents) { + struct signalfd_siginfo info; + pid_t child_pid; + int status; + int ret; + + do { + ret = socket_->Read(&info, sizeof(info)); + if (ret < 0) + break; + + pid_t child_pgid = getpgid(info.ssi_pid); + _W("[SIGCHLD] pid(%d), pgid(%d), status(%d)", + info.ssi_pid, child_pgid, info.ssi_status); + + while ((child_pid = waitpid(-1, &status, WNOHANG)) > 0) { + if (child_pid == child_pgid) + killpg(child_pgid, SIGKILL); + + if (listener_ != nullptr) + listener_->OnSigchldReceived(child_pid, status); + } + } while (ret == 0); +} + +} // namespace launchpad diff --git a/src/lib/launchpad-hydra/signal_manager.hh b/src/lib/launchpad-hydra/signal_manager.hh new file mode 100644 index 0000000..b5b5fd1 --- /dev/null +++ b/src/lib/launchpad-hydra/signal_manager.hh @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef LIB_LAUNCHPAD_HYDRA_SIGNAL_MANAGER_HH_ +#define LIB_LAUNCHPAD_HYDRA_SIGNAL_MANAGER_HH_ + +#include +#include +#include + +#include + +#include + +#include "launchpad-hydra/io_event.hh" + +namespace launchpad { + +class SignalManager : public IOEvent::IEvent { + public: + class IEvent { + public: + virtual ~IEvent() = default; + virtual void OnSigchldReceived(pid_t pid, int status) = 0; + }; + + SignalManager(const SignalManager&) = delete; + SignalManager& operator = (const SignalManager&) = delete; + SignalManager(SignalManager&&) = delete; + SignalManager& operator = (SignalManager&&) = delete; + + static SignalManager& GetInst(); + void Dispose(); + + void SetEventListener(IEvent* listener); + void UnblockSigchld(); + + private: + SignalManager() = default; + ~SignalManager(); + + void Init(); + int GetSigchldFd(); + int BlockSigchld(); + + void OnIOEventReceived(int fd, uint32_t revents) override; + + private: + bool disposed_ = true; + IEvent* listener_ = nullptr; + sigset_t mask_; + sigset_t old_mask_; + std::unique_ptr socket_; + std::unique_ptr io_event_; + pid_t current_pid_ = getpid(); +}; + +} // namespace launchpad + +#endif // LIB_LAUNCHPAD_HYDRA_SIGNAL_MANAGER_HH_ diff --git a/src/lib/launchpad-hydra/src/launchpad_hydra.c b/src/lib/launchpad-hydra/src/launchpad_hydra.c deleted file mode 100644 index e4a2eda..0000000 --- a/src/lib/launchpad-hydra/src/launchpad_hydra.c +++ /dev/null @@ -1,462 +0,0 @@ -/* - * Copyright (c) 2019 Samsung Electronics Co., Ltd All Rights Reserved - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#define _GNU_SOURCE -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include "launchpad_hydra.h" -#include "launchpad_sigchld.h" -#include "launchpad_types.h" -#include "log_private.h" - -#ifndef API -#define API __attribute__ ((visibility("default"))) -#endif - -typedef enum { - LAUNCHPAD_TYPE_UNSUPPORTED = -1, - LAUNCHPAD_TYPE_USER = 1, - LAUNCHPAD_TYPE_DYNAMIC = 100, - LAUNCHPAD_TYPE_MAX -} launchpad_type_e; - -typedef struct hydra_context_s { - sigset_t oldmask; - sd_event *event; - sd_event_source *fd_source; - sd_event_source *sig_source; - int signal_fd; - int client_fd; - int candidate_pid; - int argc; - char **argv; - hydra_lifecycle_callback_s *hydra_callbacks; - void *user_data; -} hydra_context_t; - -static hydra_context_t __context; - -static void __fini_hydra(void); - -static int __init_signal(void) -{ - sigset_t mask; - int sfd; - - _D("[__HYDRA__] init signal"); - sigemptyset(&mask); - sigaddset(&mask, SIGCHLD); - - if (sigprocmask(SIG_BLOCK, &mask, &__context.oldmask) < 0) - _E("sigprocmask() is failed. errno(%d)", errno); - else - _D("SIGCHLD blocked"); - - sfd = signalfd(-1, &mask, SFD_NONBLOCK | SFD_CLOEXEC); - if (sfd < 0) { - _E("Failed to create SIGCHLD fd. errno(%d)", errno); - return -1; - } - - return sfd; -} - -static void __fini_signal(void) -{ - _D("[__HYDRA__] finish signal"); - if (sigprocmask(SIG_SETMASK, &__context.oldmask, NULL) < 0) - _E("sigprocmask() is failed. errno(%d)", errno); - else - _D("SIGCHLD unblocked"); -} - -static int (*__security_manager_prepare_app_candidate)(void); -static int __load_security_manager_func(void) -{ -#define PATH_SECURITY_MANAGER_CLIENT LIBDIR"/libsecurity-manager-client.so.3" - void *handle; - - handle = dlopen(PATH_SECURITY_MANAGER_CLIENT, RTLD_LAZY | RTLD_LOCAL); - if (!handle) { - _E("Failed to open security manager client library. error(%s)", - dlerror()); - return -1; - } - - __security_manager_prepare_app_candidate = dlsym(handle, - "security_manager_prepare_app_candidate"); - if (!__security_manager_prepare_app_candidate) { - _E("Failed to load security_manager_prepare_app_candidate()"); - return -1; - } - - return 0; -} - -static int __fork_process(int (*child_fn)(void *), void *arg) -{ - int ret; - pid_t pid; - - pid = fork(); - if (pid < 0) { - _E("[__HYDRA__] Failed to create a child process. errno(%d)", - errno); - return pid; - } - - if (pid == 0) { - __load_security_manager_func(); - - if (__security_manager_prepare_app_candidate) { - _W("security_manager_prepare_app_candidate ++"); - ret = __security_manager_prepare_app_candidate(); - _W("security_manager_prepare_app_candidate --"); - if (ret != 0) { - _E("Failed to prepare app candidate process. error(%d)", - ret); - exit(1); - } - } - - ret = child_fn(arg); - _E("Failed to exec child process. errno(%d)", errno); - exit(ret); - } - - return pid; -} - -static int __run_loader(void *arg) -{ - int ret = 0; - - _D("[__HYDRA__] Run loader. pid(%d)", getpid()); - __fini_signal(); - - /* Set new sesssion ID & new process group ID */ - setsid(); - - launchpad_hydra_exit(); - __fini_hydra(); - - if (__context.hydra_callbacks->fork) { - ret = __context.hydra_callbacks->fork(__context.argc, - __context.argv, __context.user_data); - } - - return ret; -} - -static int __handle_launch_event(sd_event_source *s, - int fd, uint32_t revents, void *user_data) -{ - enum hydra_cmd cmd = -1; - int len; - -retry_recv: - len = recv(fd, &cmd, sizeof(cmd), MSG_WAITALL); - if (len < 0) { - if (errno == EINTR) - goto retry_recv; - } - - if (len < sizeof(cmd)) { - _E("[__HYDRA__] Failed to recv data. errno(%d)", errno); - goto err; - } - - if (cmd == LAUNCH_CANDIDATE) { - _D("[__HYDRA__] Launch new child"); - } else { - _E("[__HYDRA__] Unknown command(%d)", cmd); - goto err; - } - - __context.candidate_pid = __fork_process(__run_loader, NULL); - _D("[__HYDRA__] candidate process(%d)", __context.candidate_pid); - len = send(fd, &__context.candidate_pid, - sizeof(__context.candidate_pid), MSG_NOSIGNAL); - if (len == -1) - _E("[__HYDRA__] send() is failed. errno(%d)", errno); - - return 0; -err: - __fini_hydra(); - exit(-1); - return -1; -} - -static int __process_sigchld(struct signalfd_siginfo *info) -{ - int status; - pid_t child_pid; - pid_t child_pgid; - - child_pgid = getpgid(info->ssi_pid); - _W("[__HYDRA__] Dead pid(%d), pgid(%d), signo(%d), status(%d)", - info->ssi_pid, child_pgid, info->ssi_signo, - info->ssi_status); - - while ((child_pid = waitpid(-1, &status, WNOHANG)) > 0) { - if (child_pid == child_pgid) - killpg(child_pgid, SIGKILL); - - _sigchld_send(child_pid); - } - - return 0; -} - -static int __handle_sigchld_event(sd_event_source *s, - int fd, uint32_t revents, void *user_data) -{ - struct signalfd_siginfo siginfo; - ssize_t size; - - do { - size = read(fd, &siginfo, sizeof(struct signalfd_siginfo)); - if (size == 0) - break; - - if (size != sizeof(struct signalfd_siginfo)) - break; - - __process_sigchld(&siginfo); - } while (size > 0); - - return 0; -} - -static int __create_client_socket(int type, int id) -{ - struct sockaddr_un addr = { 0, }; - int retry = CONNECT_RETRY_COUNT; - int fd; - - fd = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0); - if (fd < 0) { - _E("Failed to create socket(%d:%d). errno(%d)", - type, id, errno); - return -1; - } - - addr.sun_family = AF_UNIX; - snprintf(addr.sun_path, sizeof(addr.sun_path), - "%s/daemons/%d/%s%d-%d", - SOCKET_PATH, getuid(), HYDRA_LOADER_SOCKET_NAME, - type, id); - while (connect(fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) { - if (errno != ETIMEDOUT || retry <= 0) { - _E("Failed to connect socket(%s). errno(%d)", - addr.sun_path, errno); - close(fd); - return -1; - } - - usleep(CONNECT_RETRY_TIME); - retry--; - _W("Retry(%d) to connect %s", retry, addr.sun_path); - } - - return fd; -} - -int __connect_to_launchpad_hydra(int type, int id) -{ - int fd; - int send_ret; - pid_t client_pid; - - - _D("[hydra] enter, type: %d", type); - - fd = __create_client_socket(type, id); - if (fd < 0) - return -1; - - client_pid = getpid(); - send_ret = send(fd, &client_pid, sizeof(client_pid), MSG_NOSIGNAL); - _D("send(%d) : %d", client_pid, send_ret); - if (send_ret == -1) { - _E("send error"); - close(fd); - return -1; - } - - SECURE_LOGD("[hydra] done, connect fd: %d", fd); - return fd; -} - -static int __init_hydra(int loader_type, int loader_id) -{ - int ret; - - _D("[__HYDRA__] init hydra"); - __context.signal_fd = __init_signal(); - if (__context.signal_fd < 0) { - _E("Failed to initialize signal"); - return -1; - } - - __context.client_fd = __connect_to_launchpad_hydra(loader_type, - loader_id); - if (__context.client_fd < 0) { - _E("Failed to connect to launchpad"); - return -1; - } - - ret = sd_event_default(&__context.event); - if (ret < 0) { - _E("Failed to create default sd event. error(%d)", ret); - return ret; - } - - sd_event_add_io(__context.event, &__context.fd_source, - __context.client_fd, EPOLLIN, - __handle_launch_event, NULL); - sd_event_add_io(__context.event, &__context.sig_source, - __context.signal_fd, EPOLLIN, - __handle_sigchld_event, NULL); - - return 0; -} - -static void __fini_hydra(void) -{ - _D("[__HYDRA__] finish hydra"); - if (__context.sig_source) - sd_event_source_unref(__context.sig_source); - - if (__context.fd_source) - sd_event_source_unref(__context.fd_source); - - if (__context.event) - sd_event_unref(__context.event); - - if (__context.client_fd > 0) - close(__context.client_fd); - - if (__context.signal_fd > 0) - close(__context.signal_fd); -} - -static void __run_loop(void) -{ - int ret; - - ret = sd_event_loop(__context.event); - if (ret < 0) - _E("Failed to run sd event loop. error(%d)", ret); - - _D("[__HYDRA__] Run main loop"); -} - -static void __exit_loop(void) -{ - if (__context.event) - sd_event_exit(__context.event, 0); - - _D("[__HYDRA__] Exit main loop"); -} - -API int launchpad_hydra_main(int argc, char **argv, - hydra_lifecycle_callback_s *hydra_callbacks, - void *user_data) -{ - int loader_type; - int loader_id; - int is_hydra; - int ret = 0; - - if (argc < 4) { - _E("[__HYDRA__] too few argument"); - return -EINVAL; - } - - loader_type = argv[LOADER_ARG_TYPE][0] - '0'; - if (loader_type < 0 || loader_type >= LAUNCHPAD_TYPE_MAX) { - _E("[__HYDRA__] Invalid argument. type(%d)", loader_type); - return -EINVAL; - } - - if (!hydra_callbacks) { - _E("[__HYDRA__] Invalid argument"); - return -EINVAL; - } - - is_hydra = argv[LOADER_ARG_HYDRA][0] - '0'; - _D("[__HYDRA__] mode: %d", is_hydra); - if (!is_hydra) { - _W("Run in non hydra mode"); - return -EINVAL; - } - - argv[LOADER_ARG_HYDRA] = "0"; - loader_id = atoi(argv[LOADER_ARG_ID]); - - __context.argc = argc; - __context.argv = argv; - __context.hydra_callbacks = hydra_callbacks; - __context.user_data = user_data; - - ret = __init_hydra(loader_type, loader_id); - if (ret < 0) { - _E("Failed to initialize hydra loader"); - return ret; - } - - if (__context.hydra_callbacks->precreate) - __context.hydra_callbacks->precreate(user_data); - - if (__context.hydra_callbacks->create) - __context.hydra_callbacks->create(__context.user_data); - - __context.candidate_pid = __fork_process(__run_loader, NULL); - _D("[__HYDRA__] candidate process(%d)", __context.candidate_pid); - if (send(__context.client_fd, &__context.candidate_pid, - sizeof(__context.candidate_pid), - MSG_NOSIGNAL) == -1) - _E("[__HYDRA__] send() is failed. errno(%d)", errno); - - __run_loop(); - - if (__context.hydra_callbacks->terminate) - ret = __context.hydra_callbacks->terminate(__context.user_data); - - __fini_hydra(); - - return ret; -} - -API void launchpad_hydra_exit(void) -{ - __exit_loop(); -} diff --git a/src/lib/launchpad-hydra/src/launchpad_sigchld.c b/src/lib/launchpad-hydra/src/launchpad_sigchld.c deleted file mode 100644 index 487cf99..0000000 --- a/src/lib/launchpad-hydra/src/launchpad_sigchld.c +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright (c) 2020 Samsung Electronics Co., Ltd All Rights Reserved - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#define _GNU_SOURCE -#include -#include -#include -#include - -#include "launchpad_sigchld.h" -#include "launchpad_socket.h" -#include "log_private.h" - -#define HYDRA_SIGCHLD_SOCK ".hydra-sigchld-sock" - -int _sigchld_send(int pid) -{ - socket_h sock; - char path[LAUNCHPAD_SOCKET_PATH_SIZE]; - int ret; - - if (pid <= 1) { - _E("Invalid parameter"); - return -EINVAL; - } - - snprintf(path, sizeof(path), "/run/aul/daemons/%u/%s", - getuid(), HYDRA_SIGCHLD_SOCK); - ret = _socket_create(path, true, &sock); - if (ret < 0) - return ret; - - ret = _socket_send(sock, &pid, sizeof(pid)); - _socket_destroy(sock); - - return ret; -} diff --git a/src/lib/launchpad/src/launchpad_lib.c b/src/lib/launchpad/src/launchpad_lib.c index a96f468..4df635d 100644 --- a/src/lib/launchpad/src/launchpad_lib.c +++ b/src/lib/launchpad/src/launchpad_lib.c @@ -207,6 +207,8 @@ static int __candidate_process_launchpad_main_loop(app_pkt_t *pkt, const char *app_path = NULL; int tmp_argc = 0; char **tmp_argv = NULL; + const char *env; + char *loader_args = NULL; int ret = -1; int i; @@ -288,6 +290,13 @@ static int __candidate_process_launchpad_main_loop(app_pkt_t *pkt, } if (out_app_path != NULL && out_argc != NULL && out_argv != NULL) { + env = getenv("TIZEN_LOADER_ARGS"); + if (env != NULL) { + loader_args = (char *)strtoul(env, NULL, 10); + if (loader_args != NULL) + out_app_path = loader_args; + } + memset(out_app_path, '\0', strlen(out_app_path)); snprintf(out_app_path, LOADER_ARG_LEN, "%s", app_path); diff --git a/tests/launchpad-process-pool-unittest/CMakeLists.txt b/tests/launchpad-process-pool-unittest/CMakeLists.txt index e2e0ff3..9dd8db5 100644 --- a/tests/launchpad-process-pool-unittest/CMakeLists.txt +++ b/tests/launchpad-process-pool-unittest/CMakeLists.txt @@ -21,6 +21,7 @@ TARGET_INCLUDE_DIRECTORIES(${TARGET_LAUNCHPAD_PROCESS_POOL_UNITTEST} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/../../src/lib/common/inc ${CMAKE_CURRENT_SOURCE_DIR}/../../src/ ${CMAKE_CURRENT_SOURCE_DIR}/../../src/lib/launchpad-common + ${CMAKE_CURRENT_SOURCE_DIR}/../../src/lib/launchpad-glib ) APPLY_PKG_CONFIG(${TARGET_LAUNCHPAD_PROCESS_POOL_UNITTEST} PUBLIC @@ -45,6 +46,6 @@ APPLY_PKG_CONFIG(${TARGET_LAUNCHPAD_PROCESS_POOL_UNITTEST} PUBLIC SET_TARGET_PROPERTIES(${TARGET_LAUNCHPAD_PROCESS_POOL_UNITTEST} PROPERTIES COMPILE_FLAGS "${EXTRA_CFLAGS}") TARGET_LINK_LIBRARIES(${TARGET_LAUNCHPAD_PROCESS_POOL_UNITTEST} - PUBLIC ${TARGET_LAUNCHPAD_COMMON} "-ldl") + PUBLIC ${TARGET_LAUNCHPAD_COMMON} ${TARGET_LAUNCHPAD_GLIB} "-ldl") INSTALL(TARGETS ${TARGET_LAUNCHPAD_PROCESS_POOL_UNITTEST} DESTINATION /usr/bin/) -- 2.7.4 From 0f7933177e2378b54d1ef636ae4384cbe620ccf8 Mon Sep 17 00:00:00 2001 From: Hwankyu Jhun Date: Tue, 9 May 2023 09:33:28 +0000 Subject: [PATCH 13/16] Add ProcessPool config This patch adds process pool config to provide changes in the number of process pool. The product or platform developer can modify the number of process pool using the config file. The default value of the number of the process pool is one. Change-Id: I8d7d4688de66dff70d3b39a4f589d2b2c0617add Signed-off-by: Hwankyu Jhun --- src/launchpad-process-pool/app_executor.cc | 6 +++- src/launchpad-process-pool/conf/launchpad.conf.in | 4 +++ src/launchpad-process-pool/config.cc | 36 ++++++++++++++++++++++- src/launchpad-process-pool/config.hh | 14 +++++++++ src/launchpad-process-pool/loader_executor.cc | 9 ++++-- 5 files changed, 65 insertions(+), 4 deletions(-) diff --git a/src/launchpad-process-pool/app_executor.cc b/src/launchpad-process-pool/app_executor.cc index e99c17e..3bc2525 100644 --- a/src/launchpad-process-pool/app_executor.cc +++ b/src/launchpad-process-pool/app_executor.cc @@ -31,6 +31,7 @@ #include #include +#include "launchpad-process-pool/config.hh" #include "launchpad-process-pool/debug.hh" #include "launchpad-process-pool/log_private.hh" #include "launchpad-process-pool/signal_manager.hh" @@ -87,7 +88,10 @@ AppExecutor::AppExecutor() : Executor(this) { std::bind(&AppExecutor::StepPrepareAppSocketAndIdFile, this)); prepare_funcs_.push_back( std::bind(&AppExecutor::StepSendStartupSignal, this)); - process_pool_ = std::unique_ptr(new ProcessPool("app", 1, this)); + + auto& process_pool_config = Config::GetInst().GetProcessPool(); + process_pool_ = std::unique_ptr( + new ProcessPool("app", process_pool_config.GetNumberOfProcesses(), this)); } pid_t AppExecutor::Execute(const AppInfo* app_info) { diff --git a/src/launchpad-process-pool/conf/launchpad.conf.in b/src/launchpad-process-pool/conf/launchpad.conf.in index 0812a64..f85ba2f 100644 --- a/src/launchpad-process-pool/conf/launchpad.conf.in +++ b/src/launchpad-process-pool/conf/launchpad.conf.in @@ -14,3 +14,7 @@ MaxCount=10 [Logger] Path=/run/aul/log Enable=1 + +[ProcessPool] +NumberOfProcesses=1 +NumberOfLoaderProcesses=1 \ No newline at end of file diff --git a/src/launchpad-process-pool/config.cc b/src/launchpad-process-pool/config.cc index 7f99de4..875c27a 100644 --- a/src/launchpad-process-pool/config.cc +++ b/src/launchpad-process-pool/config.cc @@ -43,6 +43,11 @@ constexpr const char kTagLogger[] = "Logger"; constexpr const char kKeyLoggerPath[] = "Path"; constexpr const char kKeyLoggerEnable[] = "Enable"; +constexpr const char kTagProcessPool[] = "ProcessPool"; +constexpr const char kKeyProcessPoolNumberOfProcesses[] = "NumberOfProcesses"; +constexpr const char kKeyProcessPoolNumberOfLoaderProcesses[] = + "NumberOfLoaderProcesses"; + } // namespace const std::string& Config::MemoryStatus::GetLowKey() const { @@ -145,6 +150,30 @@ Config::Logger::Logger(const IniParser& parser) { path_.c_str(), enable_ ? "true" : "false"); } +Config::ProcessPool::ProcessPool(const IniParser& parser) { + auto number_of_processes = parser.Get(kTagProcessPool, + kKeyProcessPoolNumberOfProcesses); + if (!number_of_processes.empty() && std::isdigit(number_of_processes[0])) + number_of_processes_ = std::stoi(number_of_processes); + + auto number_of_loader_processes = parser.Get(kTagProcessPool, + kKeyProcessPoolNumberOfLoaderProcesses); + if (!number_of_loader_processes.empty() && + std::isdigit(number_of_loader_processes[0])) + number_of_loader_processes_ = std::stoi(number_of_loader_processes); + + _W("[ProcessPool] processes: %d, loader processes: %d", + number_of_processes_, number_of_loader_processes_); +} + +const int Config::ProcessPool::GetNumberOfProcesses() const { + return number_of_processes_; +} + +const int Config::ProcessPool::GetNumberOfLoaderProcesses() const { + return number_of_loader_processes_; +} + Config& Config::GetInst() { static Config inst; return inst; @@ -155,7 +184,8 @@ Config::Config() memory_status_(Config::MemoryStatus(parser_)), memory_monitor_(Config::MemoryMonitor(parser_)), cpu_checker_(Config::CPUChecker(parser_)), - logger_(Config::Logger(parser_)) { + logger_(Config::Logger(parser_)), + process_pool_(Config::ProcessPool(parser_)) { } const Config::MemoryStatus& Config::GetMemoryStatus() const { @@ -174,4 +204,8 @@ const Config::Logger& Config::GetLogger() const { return logger_; } +const Config::ProcessPool& Config::GetProcessPool() const { + return process_pool_; +} + } // namespace launchpad diff --git a/src/launchpad-process-pool/config.hh b/src/launchpad-process-pool/config.hh index 6355d9a..6bff3e2 100644 --- a/src/launchpad-process-pool/config.hh +++ b/src/launchpad-process-pool/config.hh @@ -79,6 +79,18 @@ class Config { bool enable_ = false; }; + class ProcessPool { + public: + explicit ProcessPool(const IniParser& parser); + + const int GetNumberOfProcesses() const; + const int GetNumberOfLoaderProcesses() const; + + private: + int number_of_processes_ = 1; + int number_of_loader_processes_ = 1; + }; + Config(const Config&) = delete; Config& operator = (const Config&) = delete; Config(Config&&) = delete; @@ -90,6 +102,7 @@ class Config { const MemoryMonitor& GetMemoryMonitor() const; const CPUChecker& GetCPUChecker() const; const Logger& GetLogger() const; + const ProcessPool& GetProcessPool() const; private: Config(); @@ -101,6 +114,7 @@ class Config { MemoryMonitor memory_monitor_; CPUChecker cpu_checker_; Logger logger_; + ProcessPool process_pool_; }; } // namespace launchpad diff --git a/src/launchpad-process-pool/loader_executor.cc b/src/launchpad-process-pool/loader_executor.cc index f0c03fd..cdf9f4a 100644 --- a/src/launchpad-process-pool/loader_executor.cc +++ b/src/launchpad-process-pool/loader_executor.cc @@ -24,6 +24,7 @@ #include +#include "launchpad-process-pool/config.hh" #include "launchpad-process-pool/log_private.hh" #include "launchpad-process-pool/signal_manager.hh" #include "lib/common/inc/launchpad_common.h" @@ -50,8 +51,12 @@ std::vector CreateArgvFromParcel(tizen_base::Parcel* parcel) { } // namespace -LoaderExecutor::LoaderExecutor() - : Executor(this), process_pool_(new ProcessPool("loader", 1, this)) {} +LoaderExecutor::LoaderExecutor() : Executor(this) { + auto& process_pool_config = Config::GetInst().GetProcessPool(); + process_pool_ = std::unique_ptr( + new ProcessPool("loader", + process_pool_config.GetNumberOfLoaderProcesses(), this)); +} LoaderExecutor& LoaderExecutor::GetInst() { static LoaderExecutor inst; -- 2.7.4 From 7288bc68567616443d57462988ca0c7f130e262d Mon Sep 17 00:00:00 2001 From: Hwankyu Jhun Date: Fri, 12 May 2023 04:50:21 +0000 Subject: [PATCH 14/16] Enable Cpu checker The default value of the cpu checker enablement is changed to "true". Change-Id: I00c8df8b593469cb629c2e4387c84d73e64c9e1f Signed-off-by: Hwankyu Jhun --- src/launchpad-process-pool/config.cc | 2 ++ src/launchpad-process-pool/config.hh | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/launchpad-process-pool/config.cc b/src/launchpad-process-pool/config.cc index 875c27a..65a1e9f 100644 --- a/src/launchpad-process-pool/config.cc +++ b/src/launchpad-process-pool/config.cc @@ -120,6 +120,8 @@ Config::CPUChecker::CPUChecker(const IniParser& parser) { auto enable = parser.Get(kTagCpuChecker, kKeyCpuCheckerEnable); if (enable == "0" || enable == "false") enable_ = false; + else if (enable == "1" || enable == "true") + enable_ = true; _W("[CPUChecker] max_count: %d, enable: %s", max_count_, enable_ ? "true" : "false"); diff --git a/src/launchpad-process-pool/config.hh b/src/launchpad-process-pool/config.hh index 6bff3e2..22a8241 100644 --- a/src/launchpad-process-pool/config.hh +++ b/src/launchpad-process-pool/config.hh @@ -76,7 +76,7 @@ class Config { private: std::string path_ = "/var/log/appfw"; - bool enable_ = false; + bool enable_ = true; }; class ProcessPool { -- 2.7.4 From 165e3a08862a69ccb6c93c312f2cfc8897568386 Mon Sep 17 00:00:00 2001 From: Hwankyu Jhun Date: Fri, 12 May 2023 04:58:39 +0000 Subject: [PATCH 15/16] Release version 0.31.0 Changes: - Fix a bug about app-defined-loader - Modify app-defined-loader for linux container - Refactor Launchpad Hydra - Add ProcessPool config - Enable Cpu checker Change-Id: Ic7f0fd33eec0769294662f9e7a9afb2f078fa117 Signed-off-by: Hwankyu Jhun --- packaging/launchpad.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packaging/launchpad.spec b/packaging/launchpad.spec index ece4c6f..2f802bc 100644 --- a/packaging/launchpad.spec +++ b/packaging/launchpad.spec @@ -1,6 +1,6 @@ Name: launchpad Summary: Launchpad for launching applications -Version: 0.30.8 +Version: 0.31.0 Release: 1 Group: Application Framework/Daemons License: Apache-2.0 -- 2.7.4 From b81e3adc4381f9c1709e9b8852c1d4b60422f9ab Mon Sep 17 00:00:00 2001 From: Hwankyu Jhun Date: Tue, 16 May 2023 04:01:54 +0000 Subject: [PATCH 16/16] Send result while handling the launch request Even if the loader process is not prepared, the launchpad-process-pool sends the result to the amd. If the initialization of the loader process is delayed, the caller process cannot get the launched process ID. To ensure consistency of operation of handling the launch request, the caller has to get the result from the amd. Change-Id: Idd523c2a1d3743a39d743833adc801ddb02e2f1a Signed-off-by: Hwankyu Jhun --- src/launchpad-process-pool/launchpad.cc | 1 + src/launchpad-process-pool/request.cc | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/src/launchpad-process-pool/launchpad.cc b/src/launchpad-process-pool/launchpad.cc index 3176a54..d4f0ba4 100644 --- a/src/launchpad-process-pool/launchpad.cc +++ b/src/launchpad-process-pool/launchpad.cc @@ -481,6 +481,7 @@ Launchpad::LaunchResult Launchpad::LaunchRequestDo( CheckAndPrepareLoaderContext(loader_context.get()); CPUBoostController::DoBoost(loader_context->GetPid(), CPUBoostController::Level::Strong, 10000); + request->SendResult(loader_context->GetPid()); pending_requests_.push_back(std::move(request)); return LaunchResult::Pending; } diff --git a/src/launchpad-process-pool/request.cc b/src/launchpad-process-pool/request.cc index 98a87b5..46d80f6 100644 --- a/src/launchpad-process-pool/request.cc +++ b/src/launchpad-process-pool/request.cc @@ -77,7 +77,11 @@ pid_t Request::GetPid() const { } void Request::SendResult(int result) { + if (client_socket_->IsClosed()) + return; + client_socket_->Send(static_cast(&result), sizeof(result)); + client_socket_->Close(); } void Request::SetLoaderContext(std::shared_ptr context) { -- 2.7.4