From 0f7933177e2378b54d1ef636ae4384cbe620ccf8 Mon Sep 17 00:00:00 2001 From: Hwankyu Jhun Date: Tue, 9 May 2023 09:33:28 +0000 Subject: [PATCH 01/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 02/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 03/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 04/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 From 869b30caef8206c87f2f8575cd596b7345ff5e10 Mon Sep 17 00:00:00 2001 From: Hwankyu Jhun Date: Thu, 18 May 2023 08:19:27 +0000 Subject: [PATCH 05/16] Fix a bug about debugging application When the debugger info is loaded first, the candidate process of the process pool could not load the debugger info properly. This patch modifies that the launchpad behavior after loading the debugger info. To debug application properly, the launchpad terminates the candidate process to make not using it. Change-Id: I483d32b8712712b5f80f9f5579808b1ac493139a Signed-off-by: Hwankyu Jhun --- src/launchpad-process-pool/app_executor.cc | 5 +++++ src/launchpad-process-pool/app_executor.hh | 1 + src/launchpad-process-pool/debug.cc | 5 +++-- src/launchpad-process-pool/debug.hh | 2 +- src/launchpad-process-pool/launchpad.cc | 6 ++++-- 5 files changed, 14 insertions(+), 5 deletions(-) diff --git a/src/launchpad-process-pool/app_executor.cc b/src/launchpad-process-pool/app_executor.cc index 3bc2525..86accb1 100644 --- a/src/launchpad-process-pool/app_executor.cc +++ b/src/launchpad-process-pool/app_executor.cc @@ -105,6 +105,11 @@ pid_t AppExecutor::Execute(const AppInfo* app_info) { return Executor::Execute(); } +void AppExecutor::DisposeCandidateProcess() { + process_pool_->Dispose(); + process_pool_->SetTimer(); +} + void AppExecutor::OnExecution() { UserTracer::Print(std::to_string(getpid()) + "|after calling fork(). " + app_info_->GetAppId()); diff --git a/src/launchpad-process-pool/app_executor.hh b/src/launchpad-process-pool/app_executor.hh index 7d1f8d6..5d1327e 100644 --- a/src/launchpad-process-pool/app_executor.hh +++ b/src/launchpad-process-pool/app_executor.hh @@ -39,6 +39,7 @@ class AppExecutor : public Executor::Delegator, AppExecutor(); pid_t Execute(const AppInfo* app_info); + void DisposeCandidateProcess(); private: void OnExecution() override; diff --git a/src/launchpad-process-pool/debug.cc b/src/launchpad-process-pool/debug.cc index 47fb2de..53f37cc 100644 --- a/src/launchpad-process-pool/debug.cc +++ b/src/launchpad-process-pool/debug.cc @@ -71,12 +71,13 @@ void Debug::Dispose() { disposed_ = true; } -void Debug::Load() { +bool Debug::Load() { if (!debugger_infos_.empty()) - return; + return false; DebuggerInfoInflator inflator; debugger_infos_ = inflator.Inflate(kDebuggerInfoPath); + return true; } void Debug::PrepareDebugger(const tizen_base::Bundle& b) { diff --git a/src/launchpad-process-pool/debug.hh b/src/launchpad-process-pool/debug.hh index 68ed63d..28e21b7 100644 --- a/src/launchpad-process-pool/debug.hh +++ b/src/launchpad-process-pool/debug.hh @@ -41,7 +41,7 @@ class Debug : public FileMonitor::IEvent { static Debug& GetInst(); void Init(); void Dispose(); - void Load(); + bool Load(); void PrepareDebugger(const tizen_base::Bundle& b); std::vector GetExtraArgv() const; std::vector GetArgv() const; diff --git a/src/launchpad-process-pool/launchpad.cc b/src/launchpad-process-pool/launchpad.cc index d4f0ba4..bd5517c 100644 --- a/src/launchpad-process-pool/launchpad.cc +++ b/src/launchpad-process-pool/launchpad.cc @@ -444,8 +444,10 @@ Launchpad::LaunchResult Launchpad::LaunchRequestPrepare( Launchpad::LaunchResult Launchpad::ForkProcessing( std::shared_ptr request) { - if (request->GetBundle().GetType(kAulSdk) != BUNDLE_TYPE_NONE) - Debug::GetInst().Load(); + if (request->GetBundle().GetType(kAulSdk) != BUNDLE_TYPE_NONE) { + if (Debug::GetInst().Load()) + app_executor_->DisposeCandidateProcess(); + } _W("appid: %s", request->GetAppInfo()->GetAppId().c_str()); request->SetPid(app_executor_->Execute(request->GetAppInfo())); -- 2.7.4 From 0d3f8ce8fb8623ebf53293431d5a083d7dbbcd2a Mon Sep 17 00:00:00 2001 From: Hwankyu Jhun Date: Mon, 15 May 2023 23:11:53 +0000 Subject: [PATCH 06/16] Modify plugin initialization of app-defined-loader To avoid delay issue, caling _launchpad_plugin_prepare_app() is moved. Change-Id: I1cf605fc43d1d75712640bb25fd5dcbbc5d2fc47 Signed-off-by: Hwankyu Jhun --- src/app-defined-loader/src/app-defined-loader.cc | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/app-defined-loader/src/app-defined-loader.cc b/src/app-defined-loader/src/app-defined-loader.cc index b5c1d5a..3841cde 100644 --- a/src/app-defined-loader/src/app-defined-loader.cc +++ b/src/app-defined-loader/src/app-defined-loader.cc @@ -125,12 +125,6 @@ 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); @@ -147,6 +141,12 @@ class AppDefinedLoader { setenv("AUL_HWACC", "none", 1); else if (loader_type == LOADER_TYPE_HW) setenv("AUL_HWACC", "hw", 1); + + int ret = _launchpad_plugin_prepare_app(nullptr, extra); + if (ret != 0) { + _E("_launchpad_plugin_prepare_app() is failed. error(%d)", ret); + exit(EXIT_FAILURE); + } } static int OnLaunch(int argc, char** argv, const char* app_path, -- 2.7.4 From 697f121f417f07c77fb0c832b508b6c9cf2d123a Mon Sep 17 00:00:00 2001 From: Hwankyu Jhun Date: Fri, 19 May 2023 01:03:57 +0000 Subject: [PATCH 07/16] Modify launch request handling If the loader context is not prepared, the launchpad does not wait for the loader is ready. Even if it's not prepared, the launchpad wait until the loader is ready when the loader is hydra mode. And, When setting the process ID of the loader context, the launchpad sends the result to the caller if it is pending. Change-Id: I35674ab5727644cacf3e3770e252e4a2a462c9f0 Signed-off-by: Hwankyu Jhun --- src/launchpad-process-pool/launchpad.cc | 32 +++++++++++++++++++++------- src/launchpad-process-pool/launchpad.hh | 3 ++- src/launchpad-process-pool/loader_context.cc | 8 +++++-- src/launchpad-process-pool/loader_context.hh | 1 + src/launchpad-process-pool/loader_manager.cc | 5 +++++ src/launchpad-process-pool/loader_manager.hh | 2 ++ 6 files changed, 40 insertions(+), 11 deletions(-) diff --git a/src/launchpad-process-pool/launchpad.cc b/src/launchpad-process-pool/launchpad.cc index bd5517c..3fdb624 100644 --- a/src/launchpad-process-pool/launchpad.cc +++ b/src/launchpad-process-pool/launchpad.cc @@ -117,7 +117,7 @@ ServerSocket* GetLaunchpadSocket() { auto* socket = new ServerSocket(); const std::string endpoint = kRunAulDaemonsPath + std::to_string(getuid()) + - kLaunchpadProcessPoolSock; + "/" + kLaunchpadProcessPoolSock; socket->Bind(endpoint); socket->SetReceiveBufferSize(kReceivedBufferSize); socket->Listen(kMaxPendingConnection); @@ -157,8 +157,8 @@ int GetLoaderIdFromBundle(const tizen_base::Bundle& b) { } inline bool CanUseLoaderContext(const std::shared_ptr& context) { - return ((LoaderExecutor::GetInst().HasCandidateProcess() || - context->GetPid() > 0) && !context->IsPending()); + return (context->IsHydraMode() || context->GetPid() > 0) && + !context->IsPending(); } inline void CheckAndPrepareLoaderContext(LoaderContext* context) { @@ -168,8 +168,6 @@ inline void CheckAndPrepareLoaderContext(LoaderContext* context) { auto* hydra_loader_context = dynamic_cast(context); if (hydra_loader_context != nullptr) hydra_loader_context->Prepare(); - else - context->Prepare(); } } // namespace @@ -481,9 +479,12 @@ Launchpad::LaunchResult Launchpad::LaunchRequestDo( _W("Loader context is not prepared"); loader_context->SetPending(true); CheckAndPrepareLoaderContext(loader_context.get()); - CPUBoostController::DoBoost(loader_context->GetPid(), - CPUBoostController::Level::Strong, 10000); - request->SendResult(loader_context->GetPid()); + if (loader_context->GetPid() > 0) { + CPUBoostController::DoBoost(loader_context->GetPid(), + CPUBoostController::Level::Strong, 10000); + request->SendResult(loader_context->GetPid()); + } + pending_requests_.push_back(std::move(request)); return LaunchResult::Pending; } @@ -596,6 +597,21 @@ void Launchpad::OnLoaderPrepared(LoaderContext* loader_context) { } } +void Launchpad::OnLoaderLaunched(LoaderContext* loader_context) { + _W("Loader is prepared. name(%s), pid(%d)", + loader_context->GetLoaderName().c_str(), loader_context->GetPid()); + if (!loader_context->IsPending()) + return; + + for (auto& request : pending_requests_) { + auto context = request->GetAvailableLoaderContext(); + if (context != nullptr && context.get() == loader_context) { + request->SendResult(loader_context->GetPid()); + return; + } + } +} + } // namespace launchpad int main(int argc, char** argv) { diff --git a/src/launchpad-process-pool/launchpad.hh b/src/launchpad-process-pool/launchpad.hh index 4a33a10..477a40f 100644 --- a/src/launchpad-process-pool/launchpad.hh +++ b/src/launchpad-process-pool/launchpad.hh @@ -82,7 +82,8 @@ class Launchpad : public IOChannel::IEvent, void OnIOEventReceived(int fd, int condition) override; void OnSigchldReceived(pid_t pid) override; - void OnLoaderPrepared(LoaderContext* loader_context); + void OnLoaderPrepared(LoaderContext* loader_context) override; + void OnLoaderLaunched(LoaderContext* loader_context) override; private: int argc_; diff --git a/src/launchpad-process-pool/loader_context.cc b/src/launchpad-process-pool/loader_context.cc index 13d7b22..a0cc855 100644 --- a/src/launchpad-process-pool/loader_context.cc +++ b/src/launchpad-process-pool/loader_context.cc @@ -289,6 +289,10 @@ pid_t LoaderContext::GetPid() const { void LoaderContext::SetPid(pid_t pid) { pid_ = pid; + if (pid_ > 0) { + if (listener_ != nullptr) + listener_->OnLoaderLaunched(this); + } } pid_t LoaderContext::GetCallerPid() const { @@ -609,7 +613,7 @@ void LoaderContext::HandleLoaderEvent() { client_channel_->SetCloseOnDestroy(false); if (IsHydraMode()) - pid_ = peer_cred->GetPid(); + SetPid(peer_cred->GetPid()); prepared_ = true; if (listener_ != nullptr) @@ -632,7 +636,7 @@ void LoaderContext::HandleLoaderClientEvent(int condition) { if (condition & (IOChannel::IOCondition::IO_HUP | IOChannel::IOCondition::IO_NVAL)) { SECURE_LOGE("Type %d loader was disconnected. pid: %d", GetType(), pid_); - pid_ = 0; + SetPid(0); Dispose(); Prepare(); } diff --git a/src/launchpad-process-pool/loader_context.hh b/src/launchpad-process-pool/loader_context.hh index 0ab3bae..8559ebe 100644 --- a/src/launchpad-process-pool/loader_context.hh +++ b/src/launchpad-process-pool/loader_context.hh @@ -62,6 +62,7 @@ class LoaderContext : public std::enable_shared_from_this, public: virtual ~IEvent() = default; virtual void OnTimeoutEvent(LoaderContext* context) = 0; + virtual void OnLoaderLaunched(LoaderContext* context) = 0; virtual void OnLoaderPrepared(LoaderContext* context) = 0; }; diff --git a/src/launchpad-process-pool/loader_manager.cc b/src/launchpad-process-pool/loader_manager.cc index 549b7ab..ee3b86a 100644 --- a/src/launchpad-process-pool/loader_manager.cc +++ b/src/launchpad-process-pool/loader_manager.cc @@ -530,4 +530,9 @@ void LoaderManager::OnLoaderPrepared(LoaderContext* context) { event_listener_->OnLoaderPrepared(context); } +void LoaderManager::OnLoaderLaunched(LoaderContext* context) { + if (event_listener_ != nullptr) + event_listener_->OnLoaderLaunched(context); +} + } // namespace launchpad diff --git a/src/launchpad-process-pool/loader_manager.hh b/src/launchpad-process-pool/loader_manager.hh index cf8aa4a..028e617 100644 --- a/src/launchpad-process-pool/loader_manager.hh +++ b/src/launchpad-process-pool/loader_manager.hh @@ -46,6 +46,7 @@ class LoaderManager : public AppDefinedLoaderInfoManager::IEvent, class IEvent { public: virtual ~IEvent() = default; + virtual void OnLoaderLaunched(LoaderContext* context) = 0; virtual void OnLoaderPrepared(LoaderContext* context) = 0; }; @@ -105,6 +106,7 @@ class LoaderManager : public AppDefinedLoaderInfoManager::IEvent, bool OnIdleCheck(LoaderContext* context) override; void OnLoaderLaunch(LoaderContext* context) override; void OnLoaderPrepared(LoaderContext* context) override; + void OnLoaderLaunched(LoaderContext* context) override; private: bool disposed_ = true; -- 2.7.4 From 99af1fb3cd3075258478b460412f37e0876583e5 Mon Sep 17 00:00:00 2001 From: Hwankyu Jhun Date: Fri, 19 May 2023 04:16:39 +0000 Subject: [PATCH 08/16] Release version 0.31.1 Changes: - Send result while handling the launch request - Fix a bug about debugging application - Modify plugin initialization of app-defined-loader - Modify launch request handling Change-Id: If637b4dfb33cf079ee35fb2f89713670f8ef3e1f 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 2f802bc..5993518 100644 --- a/packaging/launchpad.spec +++ b/packaging/launchpad.spec @@ -1,6 +1,6 @@ Name: launchpad Summary: Launchpad for launching applications -Version: 0.31.0 +Version: 0.31.1 Release: 1 Group: Application Framework/Daemons License: Apache-2.0 -- 2.7.4 From 1ef6bbe3af02149073124029b09b17d40104010f Mon Sep 17 00:00:00 2001 From: Changgyu Choi Date: Mon, 22 May 2023 18:47:08 +0900 Subject: [PATCH 09/16] Fix gsource timer deletion This implementation error cause invalid removing source. Change-Id: I1dea3071aed99576d737ee4c9be00f7a688f9e6b Signed-off-by: Changgyu Choi --- src/launchpad-process-pool/loader_context.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/src/launchpad-process-pool/loader_context.cc b/src/launchpad-process-pool/loader_context.cc index a0cc855..8ced9b8 100644 --- a/src/launchpad-process-pool/loader_context.cc +++ b/src/launchpad-process-pool/loader_context.cc @@ -419,6 +419,7 @@ unsigned int LoaderContext::GetScore() const { gboolean LoaderContext::TimeoutCb(gpointer user_data) { auto* context = static_cast(user_data); + context->timer_ = 0; auto* listener = context->listener_; if (listener != nullptr) listener->OnTimeoutEvent(context); -- 2.7.4 From 450b0f171e7189808fe8ff9cf7363438e45a5ca0 Mon Sep 17 00:00:00 2001 From: Changgyu Choi Date: Tue, 23 May 2023 10:43:18 +0900 Subject: [PATCH 10/16] Release version 0.31.2 Changes: - Fix gsource timer deletion Change-Id: Ic5e5d901520a38b6bb21194b563f96b7cb2b92ab 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 5993518..e2486a2 100644 --- a/packaging/launchpad.spec +++ b/packaging/launchpad.spec @@ -1,6 +1,6 @@ Name: launchpad Summary: Launchpad for launching applications -Version: 0.31.1 +Version: 0.31.2 Release: 1 Group: Application Framework/Daemons License: Apache-2.0 -- 2.7.4 From 275bcb6711b41f6d4f5828bde60b6cdfb47adef8 Mon Sep 17 00:00:00 2001 From: Changgyu Choi Date: Thu, 25 May 2023 10:52:12 +0900 Subject: [PATCH 11/16] Fix static analysis issues Changes: - Initializes uninitialized attributes. Change-Id: Ieb43c2e5eb9db7d31dd262055b114353bcbe432e Signed-off-by: Changgyu Choi --- src/lib/launchpad-common/hydra_request.hh | 2 +- src/lib/launchpad-glib/app_info.hh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lib/launchpad-common/hydra_request.hh b/src/lib/launchpad-common/hydra_request.hh index f6fdf79..0d06c93 100644 --- a/src/lib/launchpad-common/hydra_request.hh +++ b/src/lib/launchpad-common/hydra_request.hh @@ -42,7 +42,7 @@ class EXPORT_API HydraRequest : public tizen_base::Parcelable { void ReadFromParcel(tizen_base::Parcel* parcel) override; private: - int cmd_; + int cmd_ = 0; int argc_ = 0; char** argv_ = nullptr; }; diff --git a/src/lib/launchpad-glib/app_info.hh b/src/lib/launchpad-glib/app_info.hh index 9e6d27a..a76a862 100644 --- a/src/lib/launchpad-glib/app_info.hh +++ b/src/lib/launchpad-glib/app_info.hh @@ -110,7 +110,7 @@ class EXPORT_API AppInfo : public tizen_base::Parcelable { std::string internal_pool_; std::string root_path_; std::string loader_name_; - bool global_; + bool global_ = true; tizen_base::Bundle b_; }; -- 2.7.4 From 390e2e1be86a10aa67d7828752e4379ac6e04d8b Mon Sep 17 00:00:00 2001 From: Hwankyu Jhun Date: Thu, 25 May 2023 02:32:24 +0000 Subject: [PATCH 12/16] Fix a bug about creating a loader process of hydra loader The argument that is the loader type is overwritten. This patch copies the arguments and uses it when executing a child process. Change-Id: Ic6a86c6a9d544ef90f0976041d92fa1145735551 Signed-off-by: Hwankyu Jhun --- src/lib/launchpad-hydra/launchpad_hydra.cc | 56 ++++++++++++++++++++++++------ src/lib/launchpad-hydra/launchpad_hydra.hh | 3 ++ 2 files changed, 49 insertions(+), 10 deletions(-) diff --git a/src/lib/launchpad-hydra/launchpad_hydra.cc b/src/lib/launchpad-hydra/launchpad_hydra.cc index 8d26dc0..1d301e2 100644 --- a/src/lib/launchpad-hydra/launchpad_hydra.cc +++ b/src/lib/launchpad-hydra/launchpad_hydra.cc @@ -48,36 +48,71 @@ const int kLoaderArgMax = 1024; } // namespace -LaunchpadHydra::LaunchpadHydra(int argc, char** argv) - : argc_(argc), argv_(argv) { +LaunchpadHydra::LaunchpadHydra(int argc, char** argv) : argc_(argc) { if (argc_ < 4) { _E("Too few arguments"); THROW(-EINVAL); } - type_ = argv_[LOADER_ARG_TYPE][0] - '0'; + 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'; + 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]); + argv[LOADER_ARG_HYDRA] = const_cast("0"); + loader_id_ = atoi(argv[LOADER_ARG_ID]); - HydraArgs::GetInst().Set(argc_, argv_); + HydraArgs::GetInst().Set(argc, argv); std::string env = std::to_string( - reinterpret_cast(argv_[0])); + reinterpret_cast(argv[0])); setenv("TIZEN_LOADER_ARGS", env.c_str(), 1); + + if (!CloneArgs(argc, argv)) { + ReleaseArgs(); + THROW(-ENOMEM); + } } LaunchpadHydra::~LaunchpadHydra() { + ReleaseArgs(); +} + +void LaunchpadHydra::ReleaseArgs() { + if (argv_ != nullptr) { + for (int i = 0; i < argc_; ++i) + free(argv_[i]); + + free(argv_); + } +} + +bool LaunchpadHydra::CloneArgs(int argc, char** argv) { + argv_ = static_cast(malloc(argc_ * sizeof(char*))); + if (argv_ == nullptr) { + _E("malloc() is failed"); + return false; + } + + for (int i = 0; i < argc_; ++i) { + argv_[i] = strdup(argv[i]); + if (argv_[i] == nullptr) { + _E("strdup() is failed"); + return false; + } + + if (i != (argc_ - 1)) + SECURE_LOGD("[%d] %s", i, argv_[i]); + } + + return true; } void LaunchpadHydra::Run(hydra_lifecycle_callback_s* callback, @@ -240,8 +275,9 @@ void LaunchpadHydra::OnLoaderExecution(int argc, char** argv) { int ret = 0; if (callback_.fork != nullptr) { - memset(argv_[0], '\0', kLoaderArgMax); - snprintf(argv_[0], kLoaderArgMax, "%s candidate", argv[0]); + char** hydra_args = HydraArgs::GetInst().GetArgs(); + memset(hydra_args[0], '\0', kLoaderArgMax); + snprintf(hydra_args[0], kLoaderArgMax, "%s candidate", argv[0]); ret = callback_.fork(argc, argv, user_data_); } diff --git a/src/lib/launchpad-hydra/launchpad_hydra.hh b/src/lib/launchpad-hydra/launchpad_hydra.hh index 43ea3b2..2f527c8 100644 --- a/src/lib/launchpad-hydra/launchpad_hydra.hh +++ b/src/lib/launchpad-hydra/launchpad_hydra.hh @@ -41,6 +41,9 @@ class LaunchpadHydra : public IOEvent::IEvent, void Exit(); private: + void ReleaseArgs(); + bool CloneArgs(int argc, char** args); + void OnPreCreate(); void OnCreate(); void OnTerminate(); -- 2.7.4 From 7280e2dab9c89062586235bd3985f6f883746497 Mon Sep 17 00:00:00 2001 From: Hwankyu Jhun Date: Wed, 24 May 2023 08:51:34 +0000 Subject: [PATCH 13/16] Modify setting scheduling priority To set the scheduling priority properly, the launchpad-process-pool sends the priority to the child process. And, after calling fork(), the child process creates a new session using setsid(). The argument of the setpriority() is changed to PRIO_PGRP from PRIO_PROCESS. The hydra loader changes the priority to 0 to restore to its original state. Change-Id: Ie5d5d6d55493934c7706b32789d35697d05285d6 Signed-off-by: Hwankyu Jhun --- src/launchpad-process-pool/app_executor.cc | 7 ---- src/launchpad-process-pool/app_executor.hh | 1 - src/launchpad-process-pool/executor.cc | 6 ++-- src/launchpad-process-pool/hydra_loader_context.cc | 2 +- src/launchpad-process-pool/loader_context.cc | 4 +++ src/launchpad-process-pool/loader_context.hh | 1 + src/launchpad-process-pool/loader_executor.cc | 24 ++++++++----- src/lib/common/src/launchpad_common.c | 2 +- src/lib/launchpad-common/hydra_request.cc | 13 +++++-- src/lib/launchpad-common/hydra_request.hh | 6 ++-- src/lib/launchpad-common/sched_priority.cc | 41 ++++++++++++++++++++++ src/lib/launchpad-common/sched_priority.hh | 33 +++++++++++++++++ src/lib/launchpad-glib/util.cc | 10 ------ src/lib/launchpad-glib/util.hh | 1 - src/lib/launchpad-hydra/executor.cc | 14 ++------ src/lib/launchpad-hydra/launchpad_hydra.cc | 10 +++--- src/lib/launchpad-hydra/loader_executor.cc | 19 ++++++++-- 17 files changed, 140 insertions(+), 54 deletions(-) create mode 100644 src/lib/launchpad-common/sched_priority.cc create mode 100644 src/lib/launchpad-common/sched_priority.hh diff --git a/src/launchpad-process-pool/app_executor.cc b/src/launchpad-process-pool/app_executor.cc index 86accb1..ff38056 100644 --- a/src/launchpad-process-pool/app_executor.cc +++ b/src/launchpad-process-pool/app_executor.cc @@ -61,8 +61,6 @@ AppExecutor::AppExecutor() : Executor(this) { launcher_infos_ = inflator.Inflate("/usr/share/aul"); prepare_funcs_.push_back( - std::bind(&AppExecutor::StepCreateNewSession, this)); - prepare_funcs_.push_back( std::bind(&AppExecutor::StepPluginPrepareApp, this)); prepare_funcs_.push_back( std::bind(&AppExecutor::StepEnableExternalPackage, this)); @@ -174,11 +172,6 @@ int AppExecutor::Prepare() { return 0; } -int AppExecutor::StepCreateNewSession() { - setsid(); - return 0; -} - int AppExecutor::StepPluginPrepareApp() { return Plugin::PrepareApp(app_info_->GetAppId(), app_info_->GetBundle()); } diff --git a/src/launchpad-process-pool/app_executor.hh b/src/launchpad-process-pool/app_executor.hh index 5d1327e..94b23fa 100644 --- a/src/launchpad-process-pool/app_executor.hh +++ b/src/launchpad-process-pool/app_executor.hh @@ -46,7 +46,6 @@ class AppExecutor : public Executor::Delegator, void OnRequestReceived(tizen_base::Parcel* parcel) override; int Prepare(); - int StepCreateNewSession(); int StepPluginPrepareApp(); int StepEnableExternalPackage(); int StepEnableTrustAnchor(); diff --git a/src/launchpad-process-pool/executor.cc b/src/launchpad-process-pool/executor.cc index 74541d6..4aea7ca 100644 --- a/src/launchpad-process-pool/executor.cc +++ b/src/launchpad-process-pool/executor.cc @@ -16,9 +16,10 @@ #include "launchpad-process-pool/executor.hh" +#include #include -#include +#include #include "launchpad-process-pool/log_private.hh" @@ -34,8 +35,9 @@ pid_t Executor::Execute(int priority) { } if (pid == 0) { + setsid(); if (priority != 0) - Util::SetPriority(priority); + SchedPriority::Set(priority); _W("security_manager_prepare_app_candidate ++"); int ret = security_manager_prepare_app_candidate(); diff --git a/src/launchpad-process-pool/hydra_loader_context.cc b/src/launchpad-process-pool/hydra_loader_context.cc index b42db39..545e107 100644 --- a/src/launchpad-process-pool/hydra_loader_context.cc +++ b/src/launchpad-process-pool/hydra_loader_context.cc @@ -110,7 +110,7 @@ void HydraLoaderContext::SetHydraPid(pid_t hydra_pid) { void HydraLoaderContext::PrepareCandidateProcess() { _W("Send launch request to hydra loader. fd(%d)", client_socket_->GetFd()); - HydraRequest request(LAUNCH_CANDIDATE); + HydraRequest request(LAUNCH_CANDIDATE, GetSchedPriority()); tizen_base::Parcel parcel; parcel.WriteParcelable(request); diff --git a/src/launchpad-process-pool/loader_context.cc b/src/launchpad-process-pool/loader_context.cc index 8ced9b8..7458bbb 100644 --- a/src/launchpad-process-pool/loader_context.cc +++ b/src/launchpad-process-pool/loader_context.cc @@ -283,6 +283,10 @@ void LoaderContext::SetPrepared(bool prepared) { prepared_ = prepared; } +int LoaderContext::GetSchedPriority() const { + return loader_info_->GetSchedPriority(); +} + pid_t LoaderContext::GetPid() const { return pid_; } diff --git a/src/launchpad-process-pool/loader_context.hh b/src/launchpad-process-pool/loader_context.hh index 8559ebe..1dfbc26 100644 --- a/src/launchpad-process-pool/loader_context.hh +++ b/src/launchpad-process-pool/loader_context.hh @@ -114,6 +114,7 @@ class LoaderContext : public std::enable_shared_from_this, protected: void SetPrepared(bool prepared); void OnIOEventReceived(int fd, int condition) override; + int GetSchedPriority() const; private: void UpdateScore(); diff --git a/src/launchpad-process-pool/loader_executor.cc b/src/launchpad-process-pool/loader_executor.cc index cdf9f4a..43f1d4c 100644 --- a/src/launchpad-process-pool/loader_executor.cc +++ b/src/launchpad-process-pool/loader_executor.cc @@ -23,6 +23,7 @@ #include #include +#include #include "launchpad-process-pool/config.hh" #include "launchpad-process-pool/log_private.hh" @@ -33,20 +34,17 @@ namespace launchpad { namespace { -tizen_base::Parcel CreateParcelFromArgv(const std::vector& argv) { - tizen_base::Bundle b; - b.Add("LOADER_ARGS", argv); - auto b_raw = b.ToRaw(); +tizen_base::Parcel CreateParcelFromBundle(tizen_base::Bundle* b) { + 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 CreateArgvFromParcel(tizen_base::Parcel* parcel) { +tizen_base::Bundle CreateBundleFromParcel(tizen_base::Parcel* parcel) { std::string raw = parcel->ReadString(); - tizen_base::Bundle b(raw); - return b.GetStringArray("LOADER_ARGS"); + return tizen_base::Bundle(raw); } } // namespace @@ -67,7 +65,10 @@ pid_t LoaderExecutor::Execute(const LoaderContext* loader_context, int priority) { loader_argv_ = CreateLoaderArgv(loader_context); if (process_pool_->IsPrepared()) { - auto parcel = CreateParcelFromArgv(loader_argv_); + tizen_base::Bundle b; + b.Add("LOADER_ARGS", loader_argv_); + b.Add("LOADER_PRIORITY", std::to_string(priority)); + auto parcel = CreateParcelFromBundle(&b); return process_pool_->Execute(parcel); } @@ -107,7 +108,12 @@ void LoaderExecutor::OnExecution() { void LoaderExecutor::OnRequestReceived(tizen_base::Parcel* parcel) { _W("Request received"); - loader_argv_ = CreateArgvFromParcel(parcel); + tizen_base::Bundle b = CreateBundleFromParcel(parcel); + int priority = std::stoi(b.GetString("LOADER_PRIORITY")); + if (priority != 0) + SchedPriority::Set(priority); + + loader_argv_ = b.GetStringArray("LOADER_ARGS"); OnExecution(); } diff --git a/src/lib/common/src/launchpad_common.c b/src/lib/common/src/launchpad_common.c index b12f10d..9f75801 100644 --- a/src/lib/common/src/launchpad_common.c +++ b/src/lib/common/src/launchpad_common.c @@ -1051,7 +1051,7 @@ int _set_priority(int prio) { int ret; - ret = setpriority(PRIO_PROCESS, 0, prio); + ret = setpriority(PRIO_PGRP, 0, prio); if (ret != 0) { SECURE_LOGE("Failed to set process(%d) priority(%d) - err(%d)", getpid(), prio, errno); diff --git a/src/lib/launchpad-common/hydra_request.cc b/src/lib/launchpad-common/hydra_request.cc index 3d4fc64..7001680 100644 --- a/src/lib/launchpad-common/hydra_request.cc +++ b/src/lib/launchpad-common/hydra_request.cc @@ -20,15 +20,20 @@ namespace launchpad { -HydraRequest::HydraRequest(int cmd) : cmd_(cmd) {} +HydraRequest::HydraRequest(int cmd, int priority) + : cmd_(cmd), priority_(priority) {} -HydraRequest::HydraRequest(int cmd, int argc, char** argv) - : cmd_(cmd), argc_(argc), argv_(argv) {} +HydraRequest::HydraRequest(int cmd, int priority, int argc, char** argv) + : cmd_(cmd), priority_(priority), argc_(argc), argv_(argv) {} int HydraRequest::GetCommand() const { return cmd_; } +int HydraRequest::GetPriority() const { + return priority_; +} + int HydraRequest::GetArgc() const { return argc_; } @@ -39,6 +44,7 @@ char** HydraRequest::GetArgv() const { void HydraRequest::WriteToParcel(tizen_base::Parcel* parcel) const { parcel->WriteInt32(cmd_); + parcel->WriteInt32(priority_); parcel->WriteInt32(argc_); for (int i = 0; i < argc_; ++i) parcel->WriteCString(argv_[i]); @@ -52,6 +58,7 @@ void HydraRequest::ReadFromParcel(tizen_base::Parcel* parcel) { argv_ = nullptr; parcel->ReadInt32(&cmd_); + parcel->ReadInt32(&priority_); parcel->ReadInt32(&argc_); if (argc_ == 0) return; diff --git a/src/lib/launchpad-common/hydra_request.hh b/src/lib/launchpad-common/hydra_request.hh index 0d06c93..fcffdd6 100644 --- a/src/lib/launchpad-common/hydra_request.hh +++ b/src/lib/launchpad-common/hydra_request.hh @@ -29,12 +29,13 @@ namespace launchpad { class EXPORT_API HydraRequest : public tizen_base::Parcelable { public: - explicit HydraRequest(int cmd); - HydraRequest(int cmd, int argc, char** argv); + explicit HydraRequest(int cmd, int priority); + HydraRequest(int cmd, int priority, int argc, char** argv); HydraRequest() = default; virtual ~HydraRequest() = default; int GetCommand() const; + int GetPriority() const; int GetArgc() const; char** GetArgv() const; @@ -43,6 +44,7 @@ class EXPORT_API HydraRequest : public tizen_base::Parcelable { private: int cmd_ = 0; + int priority_ = 0; int argc_ = 0; char** argv_ = nullptr; }; diff --git a/src/lib/launchpad-common/sched_priority.cc b/src/lib/launchpad-common/sched_priority.cc new file mode 100644 index 0000000..68d5e48 --- /dev/null +++ b/src/lib/launchpad-common/sched_priority.cc @@ -0,0 +1,41 @@ +/* + * 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/sched_priority.hh" + +#include +#include + +#include "launchpad-common/log_private.hh" + +namespace launchpad { + +void SchedPriority::Set(int priority) { + int ret = setpriority(PRIO_PGRP, 0, priority); + if (ret != 0) { + _E("Failed to set process priority. priority(%d), errno(%d)", + priority, errno); + } else { + _D("Setting priority(%d) is sucessful", priority); + } +} + +int SchedPriority::Get() { + return getpriority(PRIO_PGRP, 0); +} + + +} // namespace launchpad diff --git a/src/lib/launchpad-common/sched_priority.hh b/src/lib/launchpad-common/sched_priority.hh new file mode 100644 index 0000000..6e8d197 --- /dev/null +++ b/src/lib/launchpad-common/sched_priority.hh @@ -0,0 +1,33 @@ +/* + * 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_SCHED_PRIORITY_HH_ +#define LIB_LAUNCHPAD_COMMON_SCHED_PRIORITY_HH_ + +#undef EXPORT_API +#define EXPORT_API __attribute__((visibility("default"))) + +namespace launchpad { + +class EXPORT_API SchedPriority { + public: + static void Set(int priority); + static int Get(); +}; + +} // namespace launchpad + +#endif // LIB_LAUNCHPAD_COMMON_SCHED_PRIORITY_HH_ diff --git a/src/lib/launchpad-glib/util.cc b/src/lib/launchpad-glib/util.cc index 3839f17..2d4e5cf 100644 --- a/src/lib/launchpad-glib/util.cc +++ b/src/lib/launchpad-glib/util.cc @@ -130,16 +130,6 @@ void Util::SetEnvironments(const AppInfo* app_info) { setenv("GCOV_PREFIX", "/tmp", 1); } -void Util::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 sucessful", priority); - } -} - void Util::DeleteSocketPath(pid_t pid, uid_t uid) { std::string path ="/run/aul/apps/" + std::to_string(uid) + "/" + std::to_string(pid); diff --git a/src/lib/launchpad-glib/util.hh b/src/lib/launchpad-glib/util.hh index 80f9001..0589202 100644 --- a/src/lib/launchpad-glib/util.hh +++ b/src/lib/launchpad-glib/util.hh @@ -27,7 +27,6 @@ namespace launchpad { class EXPORT_API Util { public: static void SetEnvironments(const AppInfo* app_info); - static void SetPriority(int priority); static void DeleteSocketPath(pid_t pid, uid_t uid); }; diff --git a/src/lib/launchpad-hydra/executor.cc b/src/lib/launchpad-hydra/executor.cc index 06fe350..92191a6 100644 --- a/src/lib/launchpad-hydra/executor.cc +++ b/src/lib/launchpad-hydra/executor.cc @@ -21,6 +21,7 @@ #include #include +#include #include #include "launchpad-hydra/log_private.hh" @@ -54,16 +55,6 @@ int SecurityManagerPrepareAppCandidate() { 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) {} @@ -76,8 +67,9 @@ pid_t Executor::Execute(int argc, char** argv, int priority) { } if (pid == 0) { + setsid(); if (priority != 0) - SetPriority(priority); + SchedPriority::Set(priority); int ret = SecurityManagerPrepareAppCandidate(); if (ret != 0) { diff --git a/src/lib/launchpad-hydra/launchpad_hydra.cc b/src/lib/launchpad-hydra/launchpad_hydra.cc index 1d301e2..c08106b 100644 --- a/src/lib/launchpad-hydra/launchpad_hydra.cc +++ b/src/lib/launchpad-hydra/launchpad_hydra.cc @@ -24,8 +24,9 @@ #include #include -#include #include +#include +#include #include "common/inc/launchpad_common.h" #include "common/inc/launchpad_types.h" @@ -131,6 +132,7 @@ void LaunchpadHydra::Run(hydra_lifecycle_callback_s* callback, candidate_pid_ = executor_->Execute(argc_, argv_); _D("Candidate process(%d)", candidate_pid_); socket_->Send(&candidate_pid_, sizeof(candidate_pid_)); + SchedPriority::Set(0); EventLoop::GetInst().Run(); OnTerminate(); @@ -195,10 +197,11 @@ void LaunchpadHydra::HandleLaunchEvent(const HydraRequest& request) { pid_t pid = -1; if (request.GetCommand() == LAUNCH_CANDIDATE) { _W("LAUNCH_CANDIDATE"); - pid = executor_->Execute(argc_, argv_); + pid = executor_->Execute(argc_, argv_, request.GetPriority()); } else if (request.GetCommand() == LAUNCH_CANDIDATE_WITH_ARGS) { _W("LAUNCH_CANDIDATE_WITH_ARGS"); - pid = executor_->Execute(request.GetArgc(), request.GetArgv()); + pid = executor_->Execute(request.GetArgc(), request.GetArgv(), + request.GetPriority()); } else { _W("Unknown command(%d)", request.GetCommand()); } @@ -269,7 +272,6 @@ void LaunchpadHydra::OnSigchldReceived(pid_t pid, int status) { void LaunchpadHydra::OnLoaderExecution(int argc, char** argv) { _D("Run loader. pid(%d)", getpid()); - setsid(); SignalManager::GetInst().Dispose(); EventLoop::GetInst().Exit(); diff --git a/src/lib/launchpad-hydra/loader_executor.cc b/src/lib/launchpad-hydra/loader_executor.cc index 9f5b8b7..d4929b4 100644 --- a/src/lib/launchpad-hydra/loader_executor.cc +++ b/src/lib/launchpad-hydra/loader_executor.cc @@ -18,12 +18,15 @@ #include #include +#include +#include #include #include #include #include +#include #include "launchpad-hydra/log_private.hh" #include "launchpad-hydra/signal_manager.hh" @@ -33,7 +36,8 @@ namespace { class LoaderArgs : public tizen_base::Parcelable { public: - explicit LoaderArgs(int argc, char** argv) { + explicit LoaderArgs(int priority, int argc, char** argv) + : priority_(priority) { for (int i = 0; i < argc; ++i) args_.push_back(argv[i]); } @@ -42,12 +46,14 @@ class LoaderArgs : public tizen_base::Parcelable { ~LoaderArgs() = default; void WriteToParcel(tizen_base::Parcel* parcel) const override { + parcel->WriteInt32(priority_); parcel->WriteInt32(args_.size()); for (size_t i = 0; i < args_.size(); ++i) parcel->WriteString(args_[i]); } void ReadFromParcel(tizen_base::Parcel* parcel) override { + parcel->ReadInt32(&priority_); int data_size = 0; parcel->ReadInt32(&data_size); args_.resize(data_size); @@ -55,11 +61,16 @@ class LoaderArgs : public tizen_base::Parcelable { args_[i] = parcel->ReadString(); } + int GetPriority() const { + return priority_; + } + const std::vector& GetArgs() const { return args_; } private: + int priority_ = 0; std::vector args_; }; @@ -71,7 +82,7 @@ LoaderExecutor::LoaderExecutor(IEvent* listener) pid_t LoaderExecutor::Execute(int argc, char** argv, int priority) { if (process_pool_->IsPrepared()) { - LoaderArgs loader_args(argc, argv); + LoaderArgs loader_args(priority, argc, argv); tizen_base::Parcel parcel; parcel.WriteParcelable(loader_args); return process_pool_->Execute(parcel); @@ -95,6 +106,10 @@ void LoaderExecutor::OnRequestReceived(tizen_base::Parcel* parcel) { LoaderArgs loader_args; parcel->ReadParcelable(&loader_args); + int priority = loader_args.GetPriority(); + if (priority != 0) + SchedPriority::Set(priority); + auto& args = loader_args.GetArgs(); std::vector loader_argv(args.size() + 1); int argc = args.size(); -- 2.7.4 From a40a61abb33e6107c9de532f3a1f715c23404f11 Mon Sep 17 00:00:00 2001 From: Hwankyu Jhun Date: Thu, 25 May 2023 04:47:47 +0000 Subject: [PATCH 14/16] Release version 0.31.3 Changes: - Fix static analysis issues - Fix a bug about creating a loader process of hydra loader - Modify setting scheduling priority Change-Id: I780741702fa9cb1b91958dad069435b9053ceecf 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 e2486a2..9d338df 100644 --- a/packaging/launchpad.spec +++ b/packaging/launchpad.spec @@ -1,6 +1,6 @@ Name: launchpad Summary: Launchpad for launching applications -Version: 0.31.2 +Version: 0.31.3 Release: 1 Group: Application Framework/Daemons License: Apache-2.0 -- 2.7.4 From f8328913bbac074ddb013f01bc6fba0ddfd3f21c Mon Sep 17 00:00:00 2001 From: Hwankyu Jhun Date: Fri, 26 May 2023 01:15:30 +0000 Subject: [PATCH 15/16] Refactor Launchpad Library The launchpad library is impemented using C++ language. Change-Id: I191aca9713f8771806a2516374d0710185ab9993 Signed-off-by: Hwankyu Jhun --- src/launchpad-process-pool/launchpad.cc | 2 - src/launchpad-process-pool/launchpad.hh | 4 +- src/launchpad-process-pool/loader_context.cc | 25 +- src/lib/launchpad-common/sched_priority.cc | 4 +- src/lib/launchpad-common/sched_priority.hh | 2 +- .../launchpad-glib}/language_config.cc | 4 +- .../launchpad-glib}/language_config.hh | 6 +- .../launchpad-glib}/region_format_config.cc | 4 +- .../launchpad-glib}/region_format_config.hh | 11 +- src/lib/launchpad/CMakeLists.txt | 6 +- src/lib/launchpad/launchpad_loader.cc | 378 +++++++++++ src/lib/launchpad/launchpad_loader.hh | 83 +++ src/lib/launchpad/log_private.hh | 37 ++ src/lib/launchpad/src/launchpad_lib.c | 703 --------------------- src/lib/launchpad/step_prepare_execution.cc | 201 ++++++ src/lib/launchpad/step_prepare_execution.hh | 54 ++ src/lib/launchpad/thread_control.cc | 152 +++++ src/lib/launchpad/thread_control.hh | 62 ++ 18 files changed, 1003 insertions(+), 735 deletions(-) rename src/{launchpad-process-pool => lib/launchpad-glib}/language_config.cc (92%) rename src/{launchpad-process-pool => lib/launchpad-glib}/language_config.hh (85%) rename src/{launchpad-process-pool => lib/launchpad-glib}/region_format_config.cc (92%) rename src/{launchpad-process-pool => lib/launchpad-glib}/region_format_config.hh (75%) create mode 100644 src/lib/launchpad/launchpad_loader.cc create mode 100644 src/lib/launchpad/launchpad_loader.hh create mode 100644 src/lib/launchpad/log_private.hh delete mode 100644 src/lib/launchpad/src/launchpad_lib.c create mode 100644 src/lib/launchpad/step_prepare_execution.cc create mode 100644 src/lib/launchpad/step_prepare_execution.hh create mode 100644 src/lib/launchpad/thread_control.cc create mode 100644 src/lib/launchpad/thread_control.hh diff --git a/src/launchpad-process-pool/launchpad.cc b/src/launchpad-process-pool/launchpad.cc index 3fdb624..4e25d5b 100644 --- a/src/launchpad-process-pool/launchpad.cc +++ b/src/launchpad-process-pool/launchpad.cc @@ -42,14 +42,12 @@ #include "launchpad-process-pool/config.hh" #include "launchpad-process-pool/dbus.hh" #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" #include "launchpad-process-pool/memory_monitor.hh" -#include "launchpad-process-pool/region_format_config.hh" #include "launchpad-process-pool/signal_manager.hh" #include "launchpad-process-pool/tracer.hh" #include "launchpad-process-pool/user_tracer.hh" diff --git a/src/launchpad-process-pool/launchpad.hh b/src/launchpad-process-pool/launchpad.hh index 477a40f..690af31 100644 --- a/src/launchpad-process-pool/launchpad.hh +++ b/src/launchpad-process-pool/launchpad.hh @@ -25,12 +25,12 @@ #include #include +#include #include +#include #include #include "launchpad-process-pool/app_executor.hh" -#include "launchpad-process-pool/language_config.hh" -#include "launchpad-process-pool/region_format_config.hh" #include "launchpad-process-pool/request.hh" #include "launchpad-process-pool/signal_manager.hh" #include "launchpad-process-pool/loader_manager.hh" diff --git a/src/launchpad-process-pool/loader_context.cc b/src/launchpad-process-pool/loader_context.cc index 7458bbb..8ced6a7 100644 --- a/src/launchpad-process-pool/loader_context.cc +++ b/src/launchpad-process-pool/loader_context.cc @@ -92,17 +92,6 @@ int VerifyLoaderCaps(const std::string& executable_file) { return 0; } -int SendAppPacket(ClientSocket* client_socket, app_pkt_t *app_packet) { - if (client_socket == nullptr || app_packet == nullptr) { - _E("Invalid parameter"); - return -EINVAL; - } - - const size_t size = sizeof(app_packet->cmd) + sizeof(app_packet->opt) + - sizeof(app_packet->len) + app_packet->len; - return client_socket->Send(static_cast(app_packet), size); -} - } // namespace LoaderContext::Builder& LoaderContext::Builder::SetLoaderInfo( @@ -242,9 +231,19 @@ pid_t LoaderContext::Prepare() { pid_t LoaderContext::Deploy(const AppInfo* app_info, app_pkt_t* app_packet) { Util::DeleteSocketPath(pid_, getuid()); - int ret = SendAppPacket(client_socket_.get(), app_packet); + tizen_base::Parcel parcel; + parcel.WriteParcelable(*app_info); + size_t data_size = parcel.GetDataSize(); + int ret = client_socket_->Send(static_cast(&data_size), + sizeof(data_size)); + if (ret != 0) { + _E("Failed to send request. pid(%d)", pid_); + return ret; + } + + ret = client_socket_->Send(parcel.GetData(), data_size); if (ret != 0) { - _E("Failed to send request to the loader. pid(%d)", pid_); + _E("Failed to send request. pid(%d)", pid_); return ret; } diff --git a/src/lib/launchpad-common/sched_priority.cc b/src/lib/launchpad-common/sched_priority.cc index 68d5e48..19ccc91 100644 --- a/src/lib/launchpad-common/sched_priority.cc +++ b/src/lib/launchpad-common/sched_priority.cc @@ -23,7 +23,7 @@ namespace launchpad { -void SchedPriority::Set(int priority) { +int SchedPriority::Set(int priority) { int ret = setpriority(PRIO_PGRP, 0, priority); if (ret != 0) { _E("Failed to set process priority. priority(%d), errno(%d)", @@ -31,6 +31,8 @@ void SchedPriority::Set(int priority) { } else { _D("Setting priority(%d) is sucessful", priority); } + + return ret; } int SchedPriority::Get() { diff --git a/src/lib/launchpad-common/sched_priority.hh b/src/lib/launchpad-common/sched_priority.hh index 6e8d197..5b6e58a 100644 --- a/src/lib/launchpad-common/sched_priority.hh +++ b/src/lib/launchpad-common/sched_priority.hh @@ -24,7 +24,7 @@ namespace launchpad { class EXPORT_API SchedPriority { public: - static void Set(int priority); + static int Set(int priority); static int Get(); }; diff --git a/src/launchpad-process-pool/language_config.cc b/src/lib/launchpad-glib/language_config.cc similarity index 92% rename from src/launchpad-process-pool/language_config.cc rename to src/lib/launchpad-glib/language_config.cc index 8902c7a..030fb33 100644 --- a/src/launchpad-process-pool/language_config.cc +++ b/src/lib/launchpad-glib/language_config.cc @@ -14,11 +14,11 @@ * limitations under the License. */ -#include "launchpad-process-pool/language_config.hh" +#include "launchpad-glib/language_config.hh" #include -#include "launchpad-process-pool/log_private.hh" +#include "launchpad-glib/log_private.hh" namespace launchpad { diff --git a/src/launchpad-process-pool/language_config.hh b/src/lib/launchpad-glib/language_config.hh similarity index 85% rename from src/launchpad-process-pool/language_config.hh rename to src/lib/launchpad-glib/language_config.hh index bff07b6..e00ee65 100644 --- a/src/launchpad-process-pool/language_config.hh +++ b/src/lib/launchpad-glib/language_config.hh @@ -14,8 +14,8 @@ * limitations under the License. */ -#ifndef LAUNCHPAD_PROCESS_POOL_LANGUAGE_CONFIG_HH_ -#define LAUNCHPAD_PROCESS_POOL_LANGUAGE_CONFIG_HH_ +#ifndef LIB_LAUNCHPAD_GLIB_LANGUAGE_CONFIG_HH_ +#define LIB_LAUNCHPAD_GLIB_LANGUAGE_CONFIG_HH_ #include @@ -39,4 +39,4 @@ class LanguageConfig : public Vconf::IEvent { } // namespace launchpad -#endif // LAUNCHPAD_PROCESS_POOL_LANGUAGE_CONFIG_HH_ +#endif // LIB_LAUNCHPAD_GLIB_LANGUAGE_CONFIG_HH_ diff --git a/src/launchpad-process-pool/region_format_config.cc b/src/lib/launchpad-glib/region_format_config.cc similarity index 92% rename from src/launchpad-process-pool/region_format_config.cc rename to src/lib/launchpad-glib/region_format_config.cc index b62a60c..a084172 100644 --- a/src/launchpad-process-pool/region_format_config.cc +++ b/src/lib/launchpad-glib/region_format_config.cc @@ -14,11 +14,11 @@ * limitations under the License. */ -#include "launchpad-process-pool/region_format_config.hh" +#include "launchpad-glib/region_format_config.hh" #include -#include "launchpad-process-pool/log_private.hh" +#include "launchpad-glib/log_private.hh" namespace launchpad { diff --git a/src/launchpad-process-pool/region_format_config.hh b/src/lib/launchpad-glib/region_format_config.hh similarity index 75% rename from src/launchpad-process-pool/region_format_config.hh rename to src/lib/launchpad-glib/region_format_config.hh index 9a5039b..50b4e21 100644 --- a/src/launchpad-process-pool/region_format_config.hh +++ b/src/lib/launchpad-glib/region_format_config.hh @@ -14,16 +14,19 @@ * limitations under the License. */ -#ifndef LAUNCHPAD_PROCESS_POOL_REGION_FORMAT_CONFIG_HH_ -#define LAUNCHPAD_PROCESS_POOL_REGION_FORMAT_CONFIG_HH_ +#ifndef LIB_LAUNCHPAD_GLIB_REGION_FORMAT_CONFIG_HH_ +#define LIB_LAUNCHPAD_GLIB_REGION_FORMAT_CONFIG_HH_ #include #include +#undef EXPORT_API +#define EXPORT_API __attribute__((visibility("default"))) + namespace launchpad { -class RegionFormatConfig : public Vconf::IEvent { +class EXPORT_API RegionFormatConfig : public Vconf::IEvent { public: RegionFormatConfig(); @@ -39,4 +42,4 @@ class RegionFormatConfig : public Vconf::IEvent { } // namespace launchpad -#endif // LAUNCHPAD_PROCESS_POOL_REGION_FORMAT_CONFIG_HH_ +#endif // LIB_LAUNCHPAD_GLIB_REGION_FORMAT_CONFIG_HH_ diff --git a/src/lib/launchpad/CMakeLists.txt b/src/lib/launchpad/CMakeLists.txt index 053920b..8761499 100644 --- a/src/lib/launchpad/CMakeLists.txt +++ b/src/lib/launchpad/CMakeLists.txt @@ -1,9 +1,10 @@ -AUX_SOURCE_DIRECTORY(${CMAKE_CURRENT_SOURCE_DIR}/src LAUNCHPAD_SRCS) +AUX_SOURCE_DIRECTORY(${CMAKE_CURRENT_SOURCE_DIR} LAUNCHPAD_SRCS) AUX_SOURCE_DIRECTORY(${CMAKE_CURRENT_SOURCE_DIR}/../common/src LIB_COMMON_SRCS) ADD_LIBRARY(${TARGET_LAUNCHPAD} SHARED ${LAUNCHPAD_SRCS} ${LIB_COMMON_SRCS}) + SET_TARGET_PROPERTIES(${TARGET_LAUNCHPAD} PROPERTIES SOVERSION ${MAJORVER}) SET_TARGET_PROPERTIES(${TARGET_LAUNCHPAD} PROPERTIES VERSION ${VERSION}) @@ -26,7 +27,8 @@ APPLY_PKG_CONFIG(${TARGET_LAUNCHPAD} PUBLIC TANCHOR_DEPS ) -TARGET_LINK_LIBRARIES(${TARGET_LAUNCHPAD} PUBLIC "-ldl") +TARGET_LINK_LIBRARIES(${TARGET_LAUNCHPAD} PUBLIC + ${TARGET_LAUNCHPAD_COMMON} ${TARGET_LAUNCHPAD_GLIB} "-ldl") INSTALL(TARGETS ${TARGET_LAUNCHPAD} DESTINATION ${LIB_INSTALL_DIR} COMPONENT RuntimeLibraries) diff --git a/src/lib/launchpad/launchpad_loader.cc b/src/lib/launchpad/launchpad_loader.cc new file mode 100644 index 0000000..b9092af --- /dev/null +++ b/src/lib/launchpad/launchpad_loader.cc @@ -0,0 +1,378 @@ +/* + * 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/launchpad_loader.hh" + +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "common/inc/launchpad_common.h" +#include "common/inc/launchpad_types.h" +#include "launchpad/log_private.hh" +#include "launchpad/step_prepare_execution.hh" +#include "launchpad/thread_control.hh" + +namespace launchpad { +namespace { + +const uint32_t kMaxRetryingCount = 600; +constexpr const char kLaunchpadLoaderSocketName[] = ".launchpad-type"; + +tizen_base::Bundle loader_bundle; +std::unique_ptr context; + +} // namespace + +LaunchpadLoader::LaunchpadLoader(int argc, char** argv) + : argc_(argc), argv_(argv) { + if (argc_ < 4) { + _E("Too few argument"); + THROW(-EINVAL); + } + + int is_hydra = argv_[LOADER_ARG_HYDRA][0] - '0'; + if (is_hydra) { + _E("Cannot run in hydra mode"); + THROW(-EINVAL); + } + + loader_type_ = atoi(argv_[LOADER_ARG_TYPE]); + if (loader_type_ < 0 || loader_type_ >= LAUNCHPAD_TYPE_MAX) { + _E("Invalid argument. type: %d", loader_type_); + THROW(-EINVAL); + } + + loader_id_ = atoi(argv_[LOADER_ARG_ID]); + _W("loader type: %d, loader id: %d", loader_type_, loader_id_); + context.reset(this); +} + +LaunchpadLoader::~LaunchpadLoader() { + if (app_argv_ != nullptr) { + for (int i = 0; i < app_argc_; ++i) + free(app_argv_[i]); + + free(app_argv_); + } +} + +void LaunchpadLoader::Run(loader_lifecycle_callback_s* callback, + loader_adapter_s* adapter, void* user_data) { + if (callback == nullptr || adapter == nullptr) { + _E("Invalid argument"); + THROW(-EINVAL); + } + + if (adapter->loop_begin == nullptr || adapter->loop_quit == nullptr || + adapter->add_fd == nullptr || adapter->remove_fd == nullptr) { + _E("Invalid argument. adapter callback is nullptr"); + THROW(-EINVAL); + } + + callback_ = *callback; + adapter_callback_ = *adapter; + user_data_ = user_data; + + if (!OnCreate()) { + _E("OnCreate() returns false"); + THROW(-1); + } + + SchedPriority::Set(0); + OnAdapterLoopBegin(); + OnTerminate(); +} + +void LaunchpadLoader::Quit() { + OnAdapterLoopQuit(); +} + +const tizen_base::Bundle& LaunchpadLoader::GetBundle() const { + return app_info_.GetBundle(); +} + +void LaunchpadLoader::ResetArgs() { + memset(argv_[LOADER_ARG_TYPE], 0, strlen(argv_[LOADER_ARG_TYPE])); + memset(argv_[LOADER_ARG_ID], 0, strlen(argv_[LOADER_ARG_ID])); + memset(argv_[LOADER_ARG_EXTRA], 0, strlen(argv_[LOADER_ARG_EXTRA])); +} + +void LaunchpadLoader::WaitForThreads(int threads) { + uint32_t retrying_count = 0; + + if (threads <= 1) + return; + + _W("Thread count = %u", threads); + do { + int thread_count = ThreadControl::GetInst().GetCount(); + if (thread_count >= threads) { + _E("Threads(%u) are ready", thread_count); + return; + } + + _D("Current thread count = %u", thread_count); + usleep(50 * 1000); + retrying_count++; + } while (retrying_count < kMaxRetryingCount); + _E("Maximum retyring count exceeded"); +} + +int LaunchpadLoader::ConnectToLaunchpad() { + std::string endpoint = "/run/aul/daemons/" + std::to_string(getuid()) + + "/" + std::string(kLaunchpadLoaderSocketName) + + std::to_string(loader_type_) + "-" + std::to_string(loader_id_); + ClientSocket client_socket; + client_socket.Connect(endpoint); + client_socket.SetReceiveBufferSize(Socket::kSocketMaxBufferSize); + client_socket.SetReceiveTimeout(5000); + + pid_t pid = getpid(); + int ret = client_socket.Send(static_cast(&pid), sizeof(pid)); + if (ret != 0) { + _E("Send() is failed. error: %d", ret); + return ret; + } + + return client_socket.RemoveFd(); +} + +bool LaunchpadLoader::OnCreate() { + setsid(); + tizen_base::Bundle extra(argv_[LOADER_ARG_EXTRA]); + ResetArgs(); + + if (callback_.create == nullptr) { + _E("create callback is nullptr"); + return false; + } + + int threads = 0; + std::string threads_str = extra.GetString("threads"); + if (!threads_str.empty() && std::isdigit(threads_str[0])) { + _W("threads: %s", threads_str.c_str()); + threads = std::stoi(threads_str); + } + + callback_.create(extra.GetHandle(), loader_type_, user_data_); + aul_launch_worker_init(); + WaitForThreads(threads); + malloc_trim(0); + + try { + int fd = ConnectToLaunchpad(); + if (fd < 0) { + _E("Connection to launchpad was failed. error: %d", fd); + return false; + } + + OnAdapterAddFd(fd); + } catch (const Exception& e) { + _E("Exception occurs. error: %s", e.what()); + return false; + } + + language_config_.reset(new LanguageConfig()); + region_format_config_.reset(new RegionFormatConfig()); + return true; +} + +void LaunchpadLoader::OnPrelaunch(int argc, char** argv, AppInfo* app_info) { + if (callback_.prelaunch) { + int ret = callback_.prelaunch(argc, argv, app_info->GetAppPath().c_str(), + app_info->GetAppId().c_str(), app_info->GetPkgId().c_str(), + app_info->GetPkgType().c_str(), user_data_); + if (ret < 0) { + _E("prelaunch returns an error: %d", ret); + exit(-1); + } + } +} + +void LaunchpadLoader::DefaultLaunch(AppInfo* app_info) { + StepPrepareExecution step_prepare_execution; + if (step_prepare_execution.Prepare(app_info) != 0) { + _E("Failed to prepare execution"); + exit(-1); + } +} + +void LaunchpadLoader::ChangeArgs(int argc, char** argv) { + auto* env = getenv("TIZEN_LOADER_ARGS"); + if (env != nullptr) { + auto* loader_args = reinterpret_cast(strtoul(env, nullptr, 10)); + if (loader_args != nullptr) + argv_[0] = loader_args; + } + + memset(argv_[0], '\0', strlen(argv_[0])); + snprintf(argv_[0], LOADER_ARG_LEN, "%s", argv[0]); +} + +int LaunchpadLoader::OnLaunch(int argc, char** argv, AppInfo* app_info) { + if (callback_.launch == nullptr) + return -1; + + return callback_.launch(argc, argv, app_info->GetAppPath().c_str(), + app_info->GetAppId().c_str(), app_info->GetPkgId().c_str(), + app_info->GetPkgType().c_str(), user_data_); +} + +void LaunchpadLoader::OnTerminate() { + _W("Terminating..."); + region_format_config_.reset(); + language_config_.reset(); + + if (callback_.terminate != nullptr) { + int ret = callback_.terminate(app_argc_, app_argv_, user_data_); + if (ret != 0) + exit(ret); + } +} + +void LaunchpadLoader::OnAdapterLoopBegin() { + _W("Loop begin"); + adapter_callback_.loop_begin(user_data_); +} + +void LaunchpadLoader::OnAdapterLoopQuit() { + _W("Loop quit"); + adapter_callback_.loop_quit(user_data_); +} + +void LaunchpadLoader::OnAdapterAddFd(int fd) { + _W("Add fd: %d", fd); + adapter_callback_.add_fd(user_data_, fd, ReceiverCb); +} + +void LaunchpadLoader::OnAdapterRemovefd(int fd) { + _W("Remove fd: %d", fd); + adapter_callback_.remove_fd(user_data_, fd); +} + +void LaunchpadLoader::HandleReceiverEvent(int fd) { + _D("fd: %d", fd); + ClientSocket socket(fd); + size_t data_size = 0; + int ret = socket.Receive(static_cast(&data_size), sizeof(data_size)); + if (ret != 0) { + _E("Failed to receive the data from socket. error(%d)", ret); + return; + } + + std::vector data(data_size); + ret = socket.Receive(data.data(), data.size()); + if (ret != 0) { + _E("Failed to receive the data from socket. error(%d)", ret); + return; + } + + tizen_base::Parcel parcel(data.data(), data.size()); + OnAdapterRemovefd(fd); + + ProcessLaunchRequest(&parcel); + if (ret >= 0) + Quit(); +} + +void LaunchpadLoader::ReceiverCb(int fd) { + context->HandleReceiverEvent(fd); +} + +void LaunchpadLoader::ProcessLaunchRequest(tizen_base::Parcel* parcel) { + parcel->ReadParcelable(&app_info_); + SECURE_LOGD("App Id: %s, Package Id: %s, Loader Type: %d", + app_info_.GetAppId().c_str(), app_info_.GetPkgId().c_str(), loader_type_); + if (app_info_.GetAppPath().empty() || app_info_.GetAppPath()[0] != '/') { + _E("AppPath is not absolute path"); + exit(-1); + } + + Util::SetEnvironments(&app_info_); + auto exported_args = app_info_.GetBundle().Export(); + exported_args[0] = app_info_.GetAppPath(); + app_argc_ = exported_args.size(); + app_argv_ = static_cast(calloc(app_argc_, sizeof(char*))); + if (app_argv_ == nullptr) { + _E("calloc() is failed"); + exit(-ENOMEM); + } + + for (int i = 0; i < app_argc_; ++i) { + app_argv_[i] = strdup(exported_args[i].c_str()); + if (app_argv_[i] == nullptr) { + _E("strdup() is failed. [%d] %s", i, exported_args[i].c_str()); + exit(-ENOMEM); + } + + SECURE_LOGD("Input argument %d : %s##", i, app_argv_[i]); + } + + OnPrelaunch(app_argc_, app_argv_, &app_info_); + DefaultLaunch(&app_info_); + OnLaunch(app_argc_, app_argv_, &app_info_); + ChangeArgs(app_argc_, app_argv_); +} + +} // namespace launchpad + +using namespace launchpad; + +extern "C" EXPORT_API bundle* launchpad_loader_get_bundle(void) { + if (!::context) + return nullptr; + + return ::context->GetBundle().GetHandle(); +} + +extern "C" EXPORT_API int launchpad_loader_main(int argc, char** argv, + loader_lifecycle_callback_s* callback, loader_adapter_s* adapter, + void* user_data) { + try { + LaunchpadLoader loader(argc, argv); + loader.Run(callback, adapter, user_data); + } catch (const Exception& e) { + _E("Exception occurs. error: %s", e.what()); + return e.GetErrorCode(); + } + + return 0; +} + +extern "C" EXPORT_API int launchpad_loader_set_priority(int prio) { + return SchedPriority::Set(prio); +} + +extern "C" EXPORT_API int launchpad_loader_block_threads(void) { + return ThreadControl::GetInst().BlockThreads(); +} + +extern "C" EXPORT_API int launchpad_loader_unblock_threads(void) { + return ThreadControl::GetInst().UnblockThreads(); +} diff --git a/src/lib/launchpad/launchpad_loader.hh b/src/lib/launchpad/launchpad_loader.hh new file mode 100644 index 0000000..6e77eaa --- /dev/null +++ b/src/lib/launchpad/launchpad_loader.hh @@ -0,0 +1,83 @@ +/* + * 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_LAUNCHPAD_LOADER_HH_ +#define LIB_LAUNCHPAD_LAUNCHPAD_LOADER_HH_ + +#include + +#include +#include +#include + +#include +#include +#include +#include + +#include "inc/launchpad.h" + +namespace launchpad { + +class LaunchpadLoader { + public: + LaunchpadLoader(int argc, char** argv); + virtual ~LaunchpadLoader(); + + void Run(loader_lifecycle_callback_s* callback, loader_adapter_s* adapter, + void* user_data); + void Quit(); + const tizen_base::Bundle& GetBundle() const; + + private: + void WaitForThreads(int threads); + int ConnectToLaunchpad(); + void DefaultLaunch(AppInfo* app_info); + void ResetArgs(); + void ChangeArgs(int argc, char** argv); + + bool OnCreate(); + void OnPrelaunch(int argc, char** argv, AppInfo* app_info); + int OnLaunch(int argc, char** argv, AppInfo* app_info); + void OnTerminate(); + + void OnAdapterLoopBegin(); + void OnAdapterLoopQuit(); + void OnAdapterAddFd(int fd); + void OnAdapterRemovefd(int fd); + + void HandleReceiverEvent(int fd); + void ProcessLaunchRequest(tizen_base::Parcel* parcel); + static void ReceiverCb(int fd); + + private: + int argc_; + char** argv_; + int loader_type_; + int loader_id_; + loader_lifecycle_callback_s callback_ = { nullptr, }; + loader_adapter_s adapter_callback_ = { nullptr, }; + void* user_data_ = nullptr; + AppInfo app_info_; + std::unique_ptr language_config_; + std::unique_ptr region_format_config_; + int app_argc_ = 0; + char** app_argv_ = nullptr; +}; + +} // namespace launchpad + +#endif // LIB_LAUNCHPAD_LAUNCHPAD_LOADER_HH_ diff --git a/src/lib/launchpad/log_private.hh b/src/lib/launchpad/log_private.hh new file mode 100644 index 0000000..8514d5e --- /dev/null +++ b/src/lib/launchpad/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_LOG_PRIVATE_HH_ +#define LIB_LAUNCHPAD_LOG_PRIVATE_HH_ + +#include + +#undef LOG_TAG +#define LOG_TAG "LIB_LAUNCHPAD" + +#undef _E +#define _E LOGE + +#undef _W +#define _W LOGW + +#undef _I +#define _I LOGI + +#undef _D +#define _D LOGD + +#endif // LIB_LAUNCHPAD_LOG_PRIVATE_HH_ diff --git a/src/lib/launchpad/src/launchpad_lib.c b/src/lib/launchpad/src/launchpad_lib.c deleted file mode 100644 index 4df635d..0000000 --- a/src/lib/launchpad/src/launchpad_lib.c +++ /dev/null @@ -1,703 +0,0 @@ -/* - * Copyright (c) 2015 - 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 -#include -#include - -#include "launchpad.h" -#include "launchpad_common.h" -#include "launchpad_types.h" -#include "preexec.h" - -#ifndef API -#define API __attribute__ ((visibility("default"))) -#endif - -#define AUL_PR_NAME 16 -#define SIGRTINT (SIGRTMIN + 2) - -typedef struct thread_handler_s { - struct sigaction old; - GMutex mutex; - GCond cond; - gint count; - gint num; - bool blocked; - bool done; -} thread_handler_t; - -static loader_lifecycle_callback_s *__loader_callbacks; -static loader_adapter_s *__loader_adapter; -static void *__loader_user_data; -static int __argc; -static char **__argv; -static bundle *__bundle; -static int __loader_type = LAUNCHPAD_TYPE_UNSUPPORTED; -static int __loader_id; -static bool __loop_quit; -static thread_handler_t __thread_handler; - -static void __at_exit_to_release_bundle(void) -{ - if (__bundle) - bundle_free(__bundle); -} - -static int __prepare_exec(const char *appid, const char *app_path, - const char *pkg_type, int type, const char* pkgid, - const char *root_path, bool global, bundle *kb) -{ - const char *file_name = NULL; - const char *enabled_light_user; - char process_name[AUL_PR_NAME] = { 0, }; - int ret; - struct buxton_client *bxt_cli; - - __preexec_run(pkg_type, appid, app_path); - - ret = _enable_external_pkg(kb, pkgid, global ? GLOBAL_USER : getuid()); - if (ret < 0) - return -1; - - /* SET PRIVILEGES*/ - SECURE_LOGD("[candidate] appid : %s / pkg_type : %s / app_path : %s", - appid, pkg_type, app_path); - - if (global) - ret = trust_anchor_launch(pkgid, GLOBAL_USER); - else - ret = trust_anchor_launch(pkgid, getuid()); - - if (ret != TRUST_ANCHOR_ERROR_NONE && - ret != TRUST_ANCHOR_ERROR_NOT_INSTALLED) { - _E("trust_anchor_launch() returns %d", ret); - return -1; - } - - ret = _mount_res_dir(root_path, kb); - if (ret < 0) - return -1; - - enabled_light_user = bundle_get_val(kb, AUL_K_ENABLED_LIGHT_USER); - _W("security_manager_prepare_app2 ++ %s", appid); - ret = security_manager_prepare_app2(appid, enabled_light_user); - _W("security_manager_prepare_app2 -- %s", appid); - if (ret != SECURITY_MANAGER_SUCCESS) { - _E("Failed to set privileges %s:%d", appid, ret); - return -1; - } - - _setup_stdio(basename(app_path)); - - ret = buxton_open(&bxt_cli, NULL, NULL); - if (ret != 0) { - _E("buxton_open() failed, errno(%d)", errno); - return -1; - } - ret = buxton_update_client_label_sync(bxt_cli); - if (ret != 0) { - _E("buxton_update_client_label() failed, errno(%d)", errno); - buxton_close(bxt_cli); - return -1; - } - buxton_close(bxt_cli); - - /* - * SET DUMPABLE - for coredump - * This dumpable flag should be set after - * calling perm_app_set_privilege(). - */ - prctl(PR_SET_DUMPABLE, 1); - - /* SET PROCESS NAME*/ - if (app_path == NULL) { - _D("app_path should not be NULL - check menu db"); - return -1; - } - - file_name = strrchr(app_path, '/'); - if (file_name == NULL) { - _D("file_name is NULL"); - return -1; - } - - file_name++; - if (*file_name == '\0') { - _D("can't locate file name to execute"); - return -1; - } - - memset(process_name, '\0', AUL_PR_NAME); - snprintf(process_name, AUL_PR_NAME, "%s", file_name); - prctl(PR_SET_NAME, process_name); - - ret = _wait_tep_mount(kb); - if (ret < 0) - return -1; - - ret = _prepare_app_socket(); - if (ret < 0) - return -1; - - ret = _prepare_id_file(); - if (ret < 0) - return -1; - - _send_cmd_to_amd(APP_STARTUP_SIGNAL); - return 0; -} - -static int __default_launch_cb(bundle *kb, const char *appid, - const char *app_path, const char *root_path, - const char *pkgid, const char *pkg_type, int loader_type, bool global) -{ - char err_str[MAX_LOCAL_BUFSZ] = { 0, }; - int r; - - r = __prepare_exec(appid, app_path, pkg_type, loader_type, pkgid, - root_path, global, kb); - if (r < 0) { - _E("__candidate_process_prepare_exec() failed"); - if (access(app_path, F_OK | R_OK)) { - SECURE_LOGE("access() failed for file: \"%s\", " \ - "error: %d (%s)", app_path, errno, - strerror_r(errno, err_str, sizeof(err_str))); - } - exit(-1); - } - - return 0; -} - -static int __candidate_process_launchpad_main_loop(app_pkt_t *pkt, - char *out_app_path, int *out_argc, char ***out_argv, int type) -{ - bundle *kb; - appinfo_t *menu_info = NULL; - 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; - - kb = bundle_decode(pkt->data, pkt->len); - if (!kb) { - _E("bundle decode error"); - exit(-1); - } - - if (__bundle != NULL) - bundle_free(__bundle); - - __bundle = kb; - atexit(__at_exit_to_release_bundle); - - menu_info = _appinfo_create(kb); - if (menu_info == NULL) { - _D("such pkg no found"); - exit(-1); - } - - if (menu_info->appid == NULL) { - _E("Unable to get app_id"); - exit(-1); - } - - if (type < 0) { - _E("Invalid launchpad type: %d", type); - exit(-1); - } - - SECURE_LOGD("app id: %s, launchpad type: %d", menu_info->appid, type); - - app_path = _appinfo_get_app_path(menu_info); - if (app_path == NULL) { - _E("app_path is NULL"); - exit(-1); - } - - if (app_path[0] != '/') { - _E("app_path is not absolute path"); - exit(-1); - } - - _modify_bundle(kb, /*cr.pid - unused parameter*/ 0, menu_info, - pkt->cmd); - - if (menu_info->pkgid == NULL) { - _E("unable to get pkg_id from menu_info"); - exit(-1); - } - - SECURE_LOGD("pkg id: %s", menu_info->pkgid); - - /* Set environments */ - _set_env(menu_info, kb); - - tmp_argv = _create_argc_argv(kb, &tmp_argc); - - if (__loader_callbacks->prelaunch) { - ret = __loader_callbacks->prelaunch(tmp_argc, tmp_argv, - app_path, menu_info->appid, menu_info->pkgid, - menu_info->pkg_type, __loader_user_data); - - if (ret < 0) { - _E("prelaunch callback fail (%d)", ret); - exit(-1); - } - } - - __default_launch_cb(kb, menu_info->appid, app_path, - menu_info->root_path, menu_info->pkgid, - menu_info->pkg_type, type, menu_info->global); - - if (__loader_callbacks->launch) { - ret = __loader_callbacks->launch(tmp_argc, tmp_argv, app_path, - menu_info->appid, menu_info->pkgid, - menu_info->pkg_type, __loader_user_data); - } - - 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); - - *out_argv = tmp_argv; - *out_argc = tmp_argc; - (*out_argv)[LOADER_ARG_PATH] = out_app_path; - - for (i = 0; i < *out_argc; i++) { - SECURE_LOGD("input argument %d : %s##", i, - (*out_argv)[i]); - } - } else { - exit(-1); - } - - if (menu_info != NULL) - _appinfo_free(menu_info); - - if (__bundle) { - bundle_free(__bundle); - __bundle = NULL; - } - - return ret; -} - -static void __receiver_cb(int fd) -{ - int ret = -1; - app_pkt_t *pkt; - - _D("[candidate] ECORE_FD_READ"); - pkt = _recv_pkt_raw(fd); - if (!pkt) { - _D("[candidate] _recv_pkt_raw error!"); - exit(-1); - } - - __loader_adapter->remove_fd(__loader_user_data, fd); - close(fd); - ret = __candidate_process_launchpad_main_loop(pkt, - __argv[LOADER_ARG_PATH], &__argc, &__argv, - __loader_type); - SECURE_LOGD("[candidate] real app argv[0]: %s, real app argc: %d", - __argv[LOADER_ARG_PATH], __argc); - free(pkt); - - if (ret >= 0) { - __loader_adapter->loop_quit(__loader_user_data); - _D("[candidate] ecore main loop quit"); - __loop_quit = true; - } -} - -static void __update_lang(keynode_t *node, void *user_data) -{ - char *lang; - - lang = vconf_keynode_get_str(node); - if (!lang) { - _E("Failed to get language"); - return; - } - - setenv("LANG", lang, 1); -} - -static void __region_format_changed_cb(keynode_t *node, void *user_data) -{ - char *region; - - region = vconf_keynode_get_str(node); - if (!region) { - _E("Failed to get regionformat"); - return; - } - - setenv("LC_CTYPE", region, 1); -} - -#ifndef USE_STATUS -static unsigned int __get_thread_count(void) -{ - DIR *dp; - struct dirent *dentry; - unsigned int count = 0; - - dp = opendir("/proc/self/task"); - if (dp == NULL) { - _E("opendir() is failed. errno(%d)", errno); - return 0; - } - - while ((dentry = readdir(dp)) != NULL) { - if (!isdigit(dentry->d_name[0])) - continue; - - count++; - } - - closedir(dp); - return count; -} -#else -static unsigned int __get_thread_count(void) -{ - unsigned int count = 0; - char line[LINE_MAX]; - FILE *fp; - - fp = fopen("/proc/self/status", "r"); - if (fp == NULL) { - _E("fopen() is failed"); - return 0; - } - - while (fgets(line, sizeof(line), fp)) { - if (sscanf(line, "Threads: %u", &count) == 1) - break; - } - - fclose(fp); - return count; -} -#endif - -static void __wait_for_threads(unsigned int threads) -{ -#define MAX_RETRYING_COUNT 600 - unsigned int thread_count; - unsigned int retrying_count = 0; - - if (threads <= 1) - return; - - _W("Thread count = %u", threads); - do { - thread_count = __get_thread_count(); - if (thread_count >= threads) { - _E("Threads(%u) are ready", thread_count); - return; - } - - _D("Current thread count = %u", thread_count); - usleep(50 * 1000); - retrying_count++; - } while (retrying_count < MAX_RETRYING_COUNT); - _E("Maximum retrying count exceeded"); -} - -static int __before_loop(int argc, char **argv) -{ - int client_fd; - int ret = -1; - bundle *extra = NULL; - const char *val; - unsigned int threads = 0; - int r; - - if (_verify_proc_caps() < 0) - return -1; - - __preexec_init(argc, argv); - - /* Set new session ID & new process group ID*/ - /* In linux, child can set new session ID without check permission */ - /* TODO : should be add to check permission in the kernel*/ - setsid(); - - memset(argv[LOADER_ARG_TYPE], 0, strlen(argv[LOADER_ARG_TYPE])); - memset(argv[LOADER_ARG_ID], 0, strlen(argv[LOADER_ARG_ID])); - if (argc > 3) { - extra = bundle_decode((bundle_raw *)argv[LOADER_ARG_EXTRA], - strlen(argv[LOADER_ARG_EXTRA])); - memset(argv[LOADER_ARG_EXTRA], 0, - strlen(argv[LOADER_ARG_EXTRA])); - } - - if (__loader_callbacks->create) { - val = bundle_get_val(extra, "threads"); - if (val && isdigit(val[0])) { - _D("threads: %s", val); - threads = atoi(val); - } - - __loader_callbacks->create(extra, __loader_type, - __loader_user_data); - ret = 0; - aul_launch_worker_init(); - __wait_for_threads(threads); - } - - if (extra) - bundle_free(extra); - - malloc_trim(0); - - client_fd = _connect_to_launchpad(__loader_type, __loader_id); - if (client_fd == -1) { - _D("Connecting to candidate process was failed."); - return -1; - } - - __loader_adapter->add_fd(__loader_user_data, client_fd, __receiver_cb); - - r = vconf_notify_key_changed(VCONFKEY_LANGSET, __update_lang, NULL); - if (r != VCONF_OK) - _E("Failed to register callback for langset. error(%d)", r); - - r = vconf_notify_key_changed(VCONFKEY_REGIONFORMAT, - __region_format_changed_cb, NULL); - if (r != VCONF_OK) - _E("Failed to register callback for regionformat. error(%d)", r); - - return ret; -} - -static int __after_loop(void) -{ - vconf_ignore_key_changed(VCONFKEY_REGIONFORMAT, - __region_format_changed_cb); - vconf_ignore_key_changed(VCONFKEY_LANGSET, __update_lang); - - if (__loader_callbacks->terminate) { - return __loader_callbacks->terminate(__argc, __argv, - __loader_user_data); - } - - return -1; -} - -API bundle *launchpad_loader_get_bundle(void) -{ - return __bundle; -} - -API int launchpad_loader_main(int argc, char **argv, - loader_lifecycle_callback_s *callbacks, - loader_adapter_s *adapter, void *user_data) -{ - int is_hydra; - - if (argc < 4) { - _E("too few argument."); - return -1; - } - - is_hydra = argv[LOADER_ARG_HYDRA][0] - '0'; - - if (is_hydra) { - _D("Cannot run in hydra mode"); - return -1; - } - - __loader_type = atoi(argv[LOADER_ARG_TYPE]); - if (__loader_type < 0 || __loader_type >= LAUNCHPAD_TYPE_MAX) { - _E("invalid argument. (type: %d)", __loader_type); - return -1; - } - - __loader_id = atoi(argv[LOADER_ARG_ID]); - - if (callbacks == NULL) { - _E("invalid argument. callback is null"); - return -1; - } - - if (adapter == NULL) { - _E("invalid argument. adapter is null"); - return -1; - } - - if (adapter->loop_begin == NULL || adapter->loop_quit == NULL - || adapter->add_fd == NULL || adapter->remove_fd == NULL) { - _E("invalid argument. adapter callback is null"); - return -1; - } - - __loader_callbacks = callbacks; - __loader_adapter = adapter; - __loader_user_data = user_data; - __argc = argc; - __argv = argv; - - if (__before_loop(argc, argv) != 0) { - _E("Failed to prepare running loader. type(%d)", __loader_type); - return -1; - } - - _set_priority(0); - _D("[candidate] ecore main loop begin"); - __loader_adapter->loop_begin(__loader_user_data); - - if (!__loop_quit) { - _E("[candidate] loop was stopped forcedly"); - return -1; - } - - return __after_loop(); -} - -API int launchpad_loader_set_priority(int prio) -{ - return _set_priority(prio); -} - -static void __signal_handler(int signo) -{ - _D("Block thread"); - g_mutex_lock(&__thread_handler.mutex); - g_atomic_int_set(&__thread_handler.count, - g_atomic_int_get(&__thread_handler.count) - 1); - while (!__thread_handler.done) - g_cond_wait(&__thread_handler.cond, &__thread_handler.mutex); - g_mutex_unlock(&__thread_handler.mutex); - g_atomic_int_inc(&__thread_handler.count); - _D("Unblock thread"); -} - -API int launchpad_loader_block_threads(void) -{ - struct sigaction act; - struct dirent *dentry; - DIR *dp; - pid_t pid = getpid(); - pid_t tid; - gint i; - - if (__thread_handler.blocked) { - _D("Already blocked"); - return 0; - } - - g_mutex_init(&__thread_handler.mutex); - g_cond_init(&__thread_handler.cond); - - memset(&act, '\0', sizeof(act)); - sigemptyset(&act.sa_mask); - act.sa_flags = SA_RESTART; - act.sa_handler = __signal_handler; - - if (sigaction(SIGRTINT, &act, &__thread_handler.old) != 0) { - _E("sigaction() is failed. errno(%d)", errno); - return -1; - } - - __thread_handler.done = false; - __thread_handler.count = 0; - __thread_handler.num = 0; - - dp = opendir("/proc/self/task"); - if (dp == NULL) { - _E("opendir() is failed. errno(%d)", errno); - sigaction(SIGRTINT, &__thread_handler.old, NULL); - return -1; - } - - while ((dentry = readdir(dp)) != NULL) { - if (!isdigit(dentry->d_name[0])) - continue; - - tid = atoi(dentry->d_name); - if (tid != pid) { - _D("Send signal to thread(%d)", tid); - if (tgkill(pid, tid, SIGRTINT) != 0) { - _E("tgkill() is failed. errno(%d)", errno); - } else { - g_atomic_int_inc(&__thread_handler.count); - __thread_handler.num++; - } - } - } - closedir(dp); - - for (i = 1000; g_atomic_int_get(&__thread_handler.count) && i; --i) - usleep(2000); - - __thread_handler.blocked = true; - - return 0; -} - -API int launchpad_loader_unblock_threads(void) -{ - gint i; - - if (!__thread_handler.blocked) - return 0; - - g_mutex_lock(&__thread_handler.mutex); - __thread_handler.done = true; - g_cond_broadcast(&__thread_handler.cond); - g_mutex_unlock(&__thread_handler.mutex); - - for (i = 1000; g_atomic_int_get(&__thread_handler.count) != __thread_handler.num && i; --i) - usleep(2000); - - sigaction(SIGRTINT, &__thread_handler.old, NULL); - g_mutex_clear(&__thread_handler.mutex); - g_cond_clear(&__thread_handler.cond); - __thread_handler.blocked = false; - - return 0; -} diff --git a/src/lib/launchpad/step_prepare_execution.cc b/src/lib/launchpad/step_prepare_execution.cc new file mode 100644 index 0000000..144a086 --- /dev/null +++ b/src/lib/launchpad/step_prepare_execution.cc @@ -0,0 +1,201 @@ +/* + * 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/step_prepare_execution.hh" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "common/inc/launchpad_common.h" +#include "common/inc/launchpad_types.h" +#include "launchpad/log_private.hh" + +namespace launchpad { + +StepPrepareExecution::StepPrepareExecution() { + steps_ = { + std::bind(&StepPrepareExecution::EnableExternalPackage, this, + std::placeholders::_1), + std::bind(&StepPrepareExecution::TrustAnchorLaunch, this, + std::placeholders::_1), + std::bind(&StepPrepareExecution::MountResourceDirectories, this, + std::placeholders::_1), + std::bind(&StepPrepareExecution::SecurityManagerPrepareApp, this, + std::placeholders::_1), + std::bind(&StepPrepareExecution::SetupStdio, this, + std::placeholders::_1), + std::bind(&StepPrepareExecution::BuxtonUpdateClientLabel, this, + std::placeholders::_1), + std::bind(&StepPrepareExecution::SetDumpable, this, + std::placeholders::_1), + std::bind(&StepPrepareExecution::SetProcessName, this, + std::placeholders::_1), + std::bind(&StepPrepareExecution::WaitTepMount, this, + std::placeholders::_1), + std::bind(&StepPrepareExecution::PrepareAppSocket, this, + std::placeholders::_1), + std::bind(&StepPrepareExecution::PrepareIdFile, this, + std::placeholders::_1), + std::bind(&StepPrepareExecution::SendStartupSignal, this, + std::placeholders::_1), + }; +} + +int StepPrepareExecution::Prepare(AppInfo* app_info) { + for (auto& step : steps_) { + if (step(app_info) != 0) + return -1; + } + + return 0; +} + +int StepPrepareExecution::EnableExternalPackage(AppInfo* app_info) { + int ret = _enable_external_pkg(app_info->GetBundle().GetHandle(), + app_info->GetPkgId().c_str(), + app_info->IsGlobal() ? GLOBAL_USER : getuid()); + if (ret < 0) { + _E("Failed to enable external package. error: %d", ret); + return -1; + } + + return 0; +} + +int StepPrepareExecution::TrustAnchorLaunch(AppInfo* app_info) { + int ret = trust_anchor_launch(app_info->GetPkgId().c_str(), + app_info->IsGlobal() ? GLOBAL_USER : getuid()); + if (ret != TRUST_ANCHOR_ERROR_NONE && + ret != TRUST_ANCHOR_ERROR_NOT_INSTALLED) { + _E("trust_anchor_launch() is failed. error: %d", ret); + return -1; + } + + return 0; +} + +int StepPrepareExecution::MountResourceDirectories(AppInfo* app_info) { + int ret = _mount_res_dir(app_info->GetRootPath().c_str(), + app_info->GetBundle().GetHandle()); + if (ret < 0) { + _E("Failed to mount resource direstories. error: %d", ret); + return -1; + } + + return 0; +} + +int StepPrepareExecution::SecurityManagerPrepareApp(AppInfo* app_info) { + auto* enabled_light_user = bundle_get_val(app_info->GetBundle().GetHandle(), + kAulEnabledLightUser); + _W("security_manager_prepare_app2() ++ %s", app_info->GetAppId().c_str()); + int ret = security_manager_prepare_app2(app_info->GetAppId().c_str(), + enabled_light_user); + _W("security_manager_prepare_app2() -- %s", app_info->GetAppId().c_str()); + if (ret != SECURITY_MANAGER_SUCCESS) { + _E("security_manager_prepare_app2() is failed. appid: %s, error: %d", + app_info->GetAppId().c_str(), ret); + return -1; + } + + return 0; +} + +int StepPrepareExecution::SetupStdio(AppInfo* app_info) { + _setup_stdio(basename(app_info->GetAppPath().c_str())); + return 0; +} + +int StepPrepareExecution::BuxtonUpdateClientLabel(AppInfo* app_info) { + struct buxton_client* client = nullptr; + int ret = buxton_open(&client, nullptr, nullptr); + if (ret != 0) { + _E("buxton_open() is failed. errno: %d", errno); + return -1; + } + + ret = buxton_update_client_label_sync(client); + buxton_close(client); + if (ret != 0) { + _E("buxton_update_client_label_sync() is failed. errno: %d", errno); + return -1; + } + + return 0; +} + +int StepPrepareExecution::SetDumpable(AppInfo* app_info) { + prctl(PR_SET_DUMPABLE, 1); + return 0; +} + +int StepPrepareExecution::SetProcessName(AppInfo* app_info) { + char process_name[16] = { 0, }; + snprintf(process_name, sizeof(process_name), "%s", + basename(app_info->GetAppPath().c_str())); + prctl(PR_SET_NAME, process_name); + return 0; +} + +int StepPrepareExecution::WaitTepMount(AppInfo* app_info) { + int ret = _wait_tep_mount(app_info->GetBundle().GetHandle()); + if (ret < 0) { + _E("Failed to wait tep mount. error: %d", ret); + return -1; + } + + return 0; +} + +int StepPrepareExecution::PrepareAppSocket(AppInfo* app_info) { + int ret = _prepare_app_socket(); + if (ret < 0) { + _E("Failed to prepare app socket. error: %d", ret); + return -1; + } + + return 0; +} + +int StepPrepareExecution::PrepareIdFile(AppInfo* app_info) { + int ret = _prepare_id_file(); + if (ret < 0) { + _E("Failed to prepare id file. error: %d", ret); + return -1; + } + + return 0; +} + +int StepPrepareExecution::SendStartupSignal(AppInfo* app_info) { + if (_send_cmd_to_amd(APP_STARTUP_SIGNAL) != 0) + _W("Failed to send startup signal"); + + return 0; +} + +} // namespace launchpad diff --git a/src/lib/launchpad/step_prepare_execution.hh b/src/lib/launchpad/step_prepare_execution.hh new file mode 100644 index 0000000..f95514b --- /dev/null +++ b/src/lib/launchpad/step_prepare_execution.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_STEP_PREPARE_EXECUTION_HH_ +#define LIB_LAUNCHPAD_STEP_PREPARE_EXECUTION_HH_ + +#include +#include + +#include + +namespace launchpad { + +class StepPrepareExecution { + public: + StepPrepareExecution(); + virtual ~StepPrepareExecution() = default; + + int Prepare(AppInfo* app_info); + + private: + int EnableExternalPackage(AppInfo* app_info); + int TrustAnchorLaunch(AppInfo* app_info); + int MountResourceDirectories(AppInfo* app_info); + int SecurityManagerPrepareApp(AppInfo* app_info); + int SetupStdio(AppInfo* app_info); + int BuxtonUpdateClientLabel(AppInfo* app_info); + int SetDumpable(AppInfo* app_info); + int SetProcessName(AppInfo* app_info); + int WaitTepMount(AppInfo* app_info); + int PrepareAppSocket(AppInfo* app_info); + int PrepareIdFile(AppInfo* app_info); + int SendStartupSignal(AppInfo* app_info); + + private: + std::vector> steps_; +}; + +} // namespace launchpad + +#endif // LIB_LAUNCHPAD_STEP_PREPARE_EXECUTION_HH_ diff --git a/src/lib/launchpad/thread_control.cc b/src/lib/launchpad/thread_control.cc new file mode 100644 index 0000000..2f36b08 --- /dev/null +++ b/src/lib/launchpad/thread_control.cc @@ -0,0 +1,152 @@ +/* + * 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/thread_control.hh" + +#include +#include + +#include +#include +#include + +#include "launchpad/log_private.hh" + +namespace launchpad { +namespace { + +const int SIGRTINT = SIGRTMIN + 2; + +std::vector GetTasks() { + std::vector tasks; + std::filesystem::path task_path("/proc/self/task"); + try { + for (auto& entry : std::filesystem::directory_iterator(task_path)) { + if (!std::isdigit(entry.path().filename().c_str()[0])) + continue; + + tasks.push_back(std::stoi(entry.path().filename().string())); + } + } catch (const std::filesystem::filesystem_error& e) { + _E("Exception occurs. error: %s", e.what()); + } + + return tasks; +} + +} // namespace + +ThreadControl& ThreadControl::GetInst() { + static ThreadControl inst; + return inst; +} + +ThreadControl::~ThreadControl() { + UnblockThreads(); +} + +int ThreadControl::BlockThreads() { + if (blocked_) + return 0; + + if (!ChangeSigaction()) + return -1; + + InterruptThreads(); + WaitThreads(); + blocked_ = true; + return 0; +} + +int ThreadControl::UnblockThreads() { + if (!blocked_) + return 0; + + ContinueThreads(); + WaitThreads(); + RestoreSigaction(); + blocked_ = false; + return 0; +} + +bool ThreadControl::IsBlocked() const { + return blocked_; +} + +int ThreadControl::GetCount() { + return GetTasks().size(); +} + +bool ThreadControl::ChangeSigaction() { + struct sigaction act; + memset(&act, '\0', sizeof(struct sigaction)); + sigemptyset(&act.sa_mask); + act.sa_flags = SA_RESTART | SA_SIGINFO; + act.sa_handler = SignalHandler; + + if (sigaction(SIGRTINT, &act, &old_action_) != 0) { + _E("sigaction() is failed. errno(%d)", errno); + return false; + } + + return true; +} + +void ThreadControl::InterruptThreads() { + pid_t pid = getpid(); + auto tasks = GetTasks(); + count_ = tasks.size() - 1; + _D("tasks count: %d", count_); + for (auto& tid : tasks) { + if (tid != pid) { + _D("Send signal to thread(%d)", tid); + if (tgkill(pid, tid, SIGRTINT) != 0) { + _E("tgkill() is failed. tid(%d), errno(%d)", tid, errno); + count_--; + } + } + } +} + +void ThreadControl::ContinueThreads() { + std::unique_lock lock(mutex_); + count_ = GetTasks().size() - 1; + _D("tasks count: %d", count_); + done_ = true; + cond_.notify_all(); +} + +void ThreadControl::WaitThreads() { + for (int i = 1000; count_ && i; --i) + usleep(2000); +} + +void ThreadControl::RestoreSigaction() { + if (sigaction(SIGRTINT, &old_action_, nullptr) != 0) + _E("sigaction() is failed. errno(%d)", errno); +} + +void ThreadControl::SignalHandler(int signo) { + _W("Block"); + auto& inst = ThreadControl::GetInst(); + std::unique_lock lock(inst.mutex_); + inst.count_--; + inst.cond_.wait(lock, [&] { return inst.done_; }); + inst.count_--; + _W("Unblock"); +} + +} // namespace launchpad diff --git a/src/lib/launchpad/thread_control.hh b/src/lib/launchpad/thread_control.hh new file mode 100644 index 0000000..383adf2 --- /dev/null +++ b/src/lib/launchpad/thread_control.hh @@ -0,0 +1,62 @@ +/* + * 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_THREAD_CONTROL_HH_ +#define LIB_LAUNCHPAD_THREAD_CONTROL_HH_ + +#include +#include +#include +#include + +#include +#include + +namespace launchpad { + +class ThreadControl { + public: + static ThreadControl& GetInst(); + + int BlockThreads(); + int UnblockThreads(); + bool IsBlocked() const; + int GetCount(); + + private: + ThreadControl() = default; + ~ThreadControl(); + + bool ChangeSigaction(); + void InterruptThreads(); + void ContinueThreads(); + void WaitThreads(); + void RestoreSigaction(); + static void SignalHandler(int signo); + + private: + struct sigaction old_action_ = { 0, }; + std::mutex mutex_; + std::condition_variable cond_; + uint32_t count_ = 0; + uint32_t num_ = 0; + bool blocked_ = false; + bool done_ = false; +}; + +} // namespace launchpad + +#endif // LIB_LAUNCHPAD_THREAD_CONTROL_HH_ -- 2.7.4 From 6df8fc067760f6ad140c50adfaba3db9fcbf65c1 Mon Sep 17 00:00:00 2001 From: Hwankyu Jhun Date: Thu, 1 Jun 2023 07:34:05 +0000 Subject: [PATCH 16/16] Block and unblock threads Before calling the security_manager_prepare_app2() function, all threads of the loader process MUST be blocked not to make a new thread or terminate itself. This patch blocks all sub threads using real-time signal and condition variable. After calling the function, the main thread of the loade process sends the signal to unblock all sub threads using condition variable. Change-Id: I60e0e102f62fe8327fa844072b3017075e1692fa Signed-off-by: Hwankyu Jhun --- src/lib/launchpad/step_prepare_execution.cc | 3 +++ src/lib/launchpad/thread_control.cc | 41 ++++++++++++++++++++++++++--- 2 files changed, 40 insertions(+), 4 deletions(-) diff --git a/src/lib/launchpad/step_prepare_execution.cc b/src/lib/launchpad/step_prepare_execution.cc index 144a086..ad8481a 100644 --- a/src/lib/launchpad/step_prepare_execution.cc +++ b/src/lib/launchpad/step_prepare_execution.cc @@ -33,6 +33,7 @@ #include "common/inc/launchpad_common.h" #include "common/inc/launchpad_types.h" #include "launchpad/log_private.hh" +#include "launchpad/thread_control.hh" namespace launchpad { @@ -112,10 +113,12 @@ int StepPrepareExecution::MountResourceDirectories(AppInfo* app_info) { int StepPrepareExecution::SecurityManagerPrepareApp(AppInfo* app_info) { auto* enabled_light_user = bundle_get_val(app_info->GetBundle().GetHandle(), kAulEnabledLightUser); + ThreadControl::GetInst().BlockThreads(); _W("security_manager_prepare_app2() ++ %s", app_info->GetAppId().c_str()); int ret = security_manager_prepare_app2(app_info->GetAppId().c_str(), enabled_light_user); _W("security_manager_prepare_app2() -- %s", app_info->GetAppId().c_str()); + ThreadControl::GetInst().UnblockThreads(); if (ret != SECURITY_MANAGER_SUCCESS) { _E("security_manager_prepare_app2() is failed. appid: %s, error: %d", app_info->GetAppId().c_str(), ret); diff --git a/src/lib/launchpad/thread_control.cc b/src/lib/launchpad/thread_control.cc index 2f36b08..62f6f26 100644 --- a/src/lib/launchpad/thread_control.cc +++ b/src/lib/launchpad/thread_control.cc @@ -20,6 +20,7 @@ #include #include +#include #include #include @@ -47,6 +48,38 @@ std::vector GetTasks() { return tasks; } +std::string GetThreadName(pid_t tid) { + std::string path = "/proc/" + std::to_string(tid) + "/comm"; + std::ifstream proc_file(path); + if (proc_file.is_open()) { + std::string name; + std::getline(proc_file, name); + proc_file.close(); + return name; + } + + _E("Failed to read name. tid(%d)", tid); + return ""; +} + +int GetThreadCountWithoutGmain(const std::vector& tasks) { + int count = tasks.size() - 1; + for (auto tid : tasks) { + if (getpid() != tid) { + // Unfortunately, the signal handler of the gmain thread is not invoked. + // The gmain thread always calls poll(). + // To avoid delay issue of calling usleep(), this function decreases + // the count if the gmain threads exists. + if (GetThreadName(tid) == "gmain") { + _W("%d is gmain thread", tid); + count--; + } + } + } + + return count; +} + } // namespace ThreadControl& ThreadControl::GetInst() { @@ -108,7 +141,7 @@ bool ThreadControl::ChangeSigaction() { void ThreadControl::InterruptThreads() { pid_t pid = getpid(); auto tasks = GetTasks(); - count_ = tasks.size() - 1; + count_ = GetThreadCountWithoutGmain(tasks); _D("tasks count: %d", count_); for (auto& tid : tasks) { if (tid != pid) { @@ -123,7 +156,7 @@ void ThreadControl::InterruptThreads() { void ThreadControl::ContinueThreads() { std::unique_lock lock(mutex_); - count_ = GetTasks().size() - 1; + count_ = GetThreadCountWithoutGmain(GetTasks()); _D("tasks count: %d", count_); done_ = true; cond_.notify_all(); @@ -140,13 +173,13 @@ void ThreadControl::RestoreSigaction() { } void ThreadControl::SignalHandler(int signo) { - _W("Block"); + _D("Block"); auto& inst = ThreadControl::GetInst(); std::unique_lock lock(inst.mutex_); inst.count_--; inst.cond_.wait(lock, [&] { return inst.done_; }); inst.count_--; - _W("Unblock"); + _D("Unblock"); } } // namespace launchpad -- 2.7.4