The launchpad-core library is added. It will be used the sub module.
Change-Id: I57f448e7556743d2cdd73e72256598e56d8d027e
Signed-off-by: Hwankyu Jhun <h.jhun@samsung.com>
SET(TARGET_APP_DEFINED_LOADER "app-defined-loader")
SET(TARGET_LAUNCHPAD "launchpad")
SET(TARGET_LAUNCHPAD_COMMON "launchpad-common")
+SET(TARGET_LAUNCHPAD_CORE "launchpad-core")
SET(TARGET_LAUNCHPAD_GLIB "launchpad-glib")
SET(TARGET_LAUNCHPAD_HYDRA "launchpad-hydra")
SET(TARGET_LAUNCHPAD_LOADER "launchpad-loader")
%__make %{?_smp_mflags}
%check
-export LD_LIBRARY_PATH="../../src/lib/launchpad-common/:../../src/lib/launchpad-glib"
+export LD_LIBRARY_PATH="../../src/lib/launchpad-common/:../../src/lib/launchpad-glib:../../src/lib/launchpad-core"
ctest --verbose %{?_smp_mflags}
%install
%{_datadir}/parser-plugins/*
%attr(0644,root,root) %{_libdir}/liblaunchpad-common.so.*
%attr(0644,root,root) %{_libdir}/liblaunchpad-glib.so.*
+%attr(0644,root,root) %{_libdir}/liblaunchpad-core.so.*
%files devel
%{_includedir}/launchpad/*.h
%{_includedir}/launchpad-common/*.hh
+%{_includedir}/launchpad-core/*.hh
%{_includedir}/launchpad-glib/*.hh
%{_libdir}/*.so
%{_libdir}/pkgconfig/launchpad.pc
%{_libdir}/pkgconfig/liblaunchpad-common.pc
%attr(0644,root,root) %{_libdir}/liblaunchpad-glib.so
%{_libdir}/pkgconfig/liblaunchpad-glib.pc
+%attr(0644,root,root) %{_libdir}/liblaunchpad-core.so
+%{_libdir}/pkgconfig/liblaunchpad-core.pc
%files -n launchpad-loader
%manifest launchpad-loader.manifest
${CMAKE_CURRENT_SOURCE_DIR}/../
${CMAKE_CURRENT_SOURCE_DIR}/../lib/common/inc
${CMAKE_CURRENT_SOURCE_DIR}/../lib/launchpad-common
- ${CMAKE_CURRENT_SOURCE_DIR}/../lib/launchpad-glib
+ ${CMAKE_CURRENT_SOURCE_DIR}/../lib/launchpad-core
+ ${CMAKE_CURRENT_SOURCE_DIR}/../lib/launchpad-glib
)
IF(_TIZEN_FEATURE_PRELINK)
)
TARGET_LINK_LIBRARIES(${TARGET_LAUNCHPAD_PROCESS_POOL} PUBLIC
- ${TARGET_LAUNCHPAD_COMMON} ${TARGET_LAUNCHPAD_GLIB} "-lm -ldl -lpthread")
+ ${TARGET_LAUNCHPAD_COMMON} ${TARGET_LAUNCHPAD_GLIB} ${TARGET_LAUNCHPAD_CORE}
+ "-lm -ldl -lpthread")
CONFIGURE_FILE(${CMAKE_SOURCE_DIR}/packaging/default.debugger.in
${CMAKE_SOURCE_DIR}/packaging/default.debugger @ONLY)
#include <memory>
#include <string_view>
-#include "launchpad-process-pool/file_monitor.hh"
-#include "launchpad-process-pool/loader_info.hh"
+#include <file_monitor.hh>
+#include <loader_info.hh>
namespace launchpad {
+++ /dev/null
-/*
- * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "launchpad-process-pool/app_executor.hh"
-
-#include <errno.h>
-#include <libgen.h>
-#include <malloc.h>
-#include <stdio.h>
-#include <sys/prctl.h>
-#include <trust-anchor.h>
-#include <tzplatform_config.h>
-#include <unistd.h>
-
-#include <filesystem>
-#include <utility>
-
-#include <aul_keys.hh>
-#include <plugin.hh>
-#include <stdio.hh>
-#include <types.hh>
-#include <user_tracer.hh>
-#include <util.hh>
-
-#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"
-
-namespace launchpad {
-namespace fs = std::filesystem;
-namespace {
-
-void ExecuteEcho(const std::string& app_path, const std::string& error) {
- char *argv[] = {
- const_cast<char*>("/usr/bin/echo"),
- const_cast<char*>("Failed to execute a file. path:"),
- const_cast<char*>(app_path.c_str()),
- const_cast<char*>("error:"),
- const_cast<char*>(error.c_str()),
- nullptr,
- };
-
- execv(argv[0], argv);
-}
-
-} // namespace
-
-AppExecutor::AppExecutor() : Executor(this) {
- LauncherInfoInflator inflator;
- launcher_infos_ = inflator.Inflate("/usr/share/aul");
-
- prepare_funcs_.push_back(
- std::bind(&AppExecutor::StepPluginPrepareApp, this));
- prepare_funcs_.push_back(
- std::bind(&AppExecutor::StepEnableExternalPackage, this));
- prepare_funcs_.push_back(
- std::bind(&AppExecutor::StepEnableTrustAnchor, this));
- prepare_funcs_.push_back(
- std::bind(&AppExecutor::StepMountResDir, this));
- prepare_funcs_.push_back(
- std::bind(&AppExecutor::StepChangeMountNamespace, this));
- prepare_funcs_.push_back(
- std::bind(&AppExecutor::StepSecurityPrepareApp, this));
- prepare_funcs_.push_back(
- std::bind(&AppExecutor::StepSetupStdio, this));
- prepare_funcs_.push_back(
- std::bind(&AppExecutor::StepSetDumpable, this));
- prepare_funcs_.push_back(
- std::bind(&AppExecutor::StepSetProcessName, this));
- prepare_funcs_.push_back(
- std::bind(&AppExecutor::StepSetEnvironments, this));
- prepare_funcs_.push_back(
- std::bind(&AppExecutor::StepWaitTepMount, this));
- prepare_funcs_.push_back(
- std::bind(&AppExecutor::StepPrepareAppSocketAndIdFile, this));
- prepare_funcs_.push_back(
- std::bind(&AppExecutor::StepSendStartupSignal, this));
-
- auto& process_pool_config = Config::GetInst().GetProcessPool();
- process_pool_ = std::unique_ptr<ProcessPool>(
- new ProcessPool("app", process_pool_config.GetNumberOfProcesses(), this));
-}
-
-pid_t AppExecutor::Execute(const AppInfo* app_info) {
- if (process_pool_->IsPrepared()) {
- tizen_base::Parcel parcel;
- parcel.WriteParcelable(*app_info);
- pid_t pid = process_pool_->Execute(parcel);
- if (pid > 0)
- return pid;
- }
-
- app_info_ = app_info;
- return Executor::Execute();
-}
-
-void AppExecutor::DisposeCandidateProcess() {
- process_pool_->Dispose();
- process_pool_->SetTimer();
-}
-
-void AppExecutor::HandleSigchld(pid_t pid) {
- process_pool_->HandleSigchld(pid);
-}
-
-void AppExecutor::OnExecution() {
- UserTracer::Print(std::to_string(getpid()) + "|after calling fork(). " +
- app_info_->GetAppId());
- CheckAndPrepareDebugging();
- SignalManager::GetInst().UnblockSigchld();
- Util::DeleteSocketPath(getpid(), getuid());
-
- int ret = Prepare();
- if (ret < 0) {
- _E("Failed to prepare executing application(%s)",
- app_info_->GetAppId().c_str());
- ExecuteEcho(app_info_->GetAppPath(), std::to_string(ret));
- exit(ret);
- }
-
- std::vector<std::string> argv = CreateAppArgv(app_info_->GetAppPath(),
- app_info_->GetBundle(), app_info_->GetAppType());
- char** app_argv = static_cast<char**>(calloc(argv.size() + 1, sizeof(char*)));
- if (app_argv == nullptr) {
- _E("Out of memory");
- ExecuteEcho(app_info_->GetAppPath(), std::to_string(-ENOMEM));
- exit(-1);
- }
-
- int app_argc = argv.size();
- for (int i = 0; i < app_argc; ++i) {
- app_argv[i] = const_cast<char*>(argv[i].c_str());
- SECURE_LOGD("input argument %d : %s##", i, app_argv[i]);
- }
-
- auto lib_dir = Util::GetLibDirectory(app_info_->GetAppPath());
- if (!lib_dir.empty())
- setenv("LD_LIBRARY_PATH", lib_dir.c_str(), 1);
-
- Util::CloseAllFds();
- SECURE_LOGE("Execute application(%s)", app_argv[LoaderArg::Path]);
- if (execv(app_argv[LoaderArg::Path], app_argv) < 0) {
- char err_buf[1024];
- fprintf(stderr, "Failed to execute a file. path: %s, errno: %d(%s)\n",
- app_info_->GetAppPath().c_str(), errno,
- strerror_r(errno, err_buf, sizeof(err_buf)));
- ExecuteEcho(app_info_->GetAppPath(), err_buf);
- exit(EXIT_FAILURE);
- }
-}
-
-void AppExecutor::OnRequestReceived(tizen_base::Parcel* parcel) {
- _W("Request received");
- AppInfo app_info;
- parcel->ReadParcelable(&app_info);
- app_info_ = &app_info;
- OnExecution();
-}
-
-int AppExecutor::Prepare() {
- for (auto& func : prepare_funcs_) {
- if (func() != 0)
- return -1;
- }
-
- return 0;
-}
-
-int AppExecutor::StepPluginPrepareApp() {
- return Plugin::PrepareApp(app_info_->GetAppId(), app_info_->GetBundle());
-}
-
-int AppExecutor::StepEnableExternalPackage() {
- return Util::EnableExternalPackage(app_info_);
-}
-
-int AppExecutor::StepEnableTrustAnchor() {
- 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() returns %d", ret);
- return -2;
- }
-
- return 0;
-}
-
-int AppExecutor::StepMountResDir() {
- int ret = Util::MountGadgetDirectories(app_info_->GetBundle());
- if (ret != 0) {
- _E("Failed to mount gadget resources");
- return ret;
- }
-
- Util::MountLibraryDirectories(app_info_->GetBundle());
- return Util::MountResourceDirectories(app_info_);
-}
-
-int AppExecutor::StepChangeMountNamespace() {
- if (app_info_->GetBundle().GetType(kAulSdk) != BUNDLE_TYPE_NONE)
- Debug::ChangeMountNamespace();
-
- return 0;
-}
-
-int AppExecutor::StepSecurityPrepareApp() {
- auto enabled_light_user = app_info_->GetBundle().GetString(
- 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.empty() ? nullptr : enabled_light_user.c_str());
- _W("security_manager_prepare_app2 -- %s", app_info_->GetAppId().c_str());
- if (ret != SECURITY_MANAGER_SUCCESS) {
- _E("security_manager_prepare_app2() returns %d", ret);
- return -2;
- }
-
- return 0;
-}
-
-int AppExecutor::StepSetupStdio() {
- if (app_info_->GetBundle().GetType(kAulSdk) == BUNDLE_TYPE_NONE)
- Stdio::Setup();
-
- return 0;
-}
-
-int AppExecutor::StepSetDumpable() {
- prctl(PR_SET_DUMPABLE, 1);
- return 0;
-}
-
-int AppExecutor::StepSetProcessName() {
- fs::path file_path(app_info_->GetAppPath());
- fs::path file_name = file_path.filename();
- prctl(PR_SET_NAME, file_name.c_str());
- return 0;
-}
-
-int AppExecutor::StepSetEnvironments() {
- Util::SetEnvironments(app_info_);
- return 0;
-}
-
-int AppExecutor::StepWaitTepMount() {
- return Util::WaitTepMount(app_info_);
-}
-
-int AppExecutor::StepPrepareAppSocketAndIdFile() {
- if (app_info_->GetBundle().GetType(kAulSdk) != BUNDLE_TYPE_NONE)
- return 0;
-
- if (Util::PrepareAppSocket() < 0)
- return -1;
-
- return Util::PrepareAppIdFile(app_info_);
-}
-
-int AppExecutor::StepSendStartupSignal() {
- Util::SendCmdToAmd(AmdCmd::AppStartupSignal);
- return 0;
-}
-
-void AppExecutor::CheckAndPrepareDebugging() {
- auto& debug = Debug::GetInst();
- auto& b = app_info_->GetBundle();
- if (b.GetType(kAulSdk) != BUNDLE_TYPE_NONE)
- debug.PrepareDebugger(b);
-
- debug.CheckAndSetAsanActivation(app_info_->GetAppId());
- debug.CheckWebAppDebugging(b);
-}
-
-LauncherInfoPtr AppExecutor::FindLauncherInfo(const std::string& app_type) {
- for (auto& info : launcher_infos_) {
- for (auto& type : info->GetAppTypes()) {
- if (type == app_type)
- return info;
- }
- }
-
- return nullptr;
-}
-
-std::vector<std::string> AppExecutor::GetLauncherArgv(
- const std::string& app_type) {
- std::vector<std::string> argv;
- auto launcher_info = FindLauncherInfo(app_type);
- if (launcher_info == nullptr) return argv;
-
- argv.insert(argv.end(), launcher_info->GetExe());
- argv.insert(argv.end(), launcher_info->GetExtraArgs().begin(),
- launcher_info->GetExtraArgs().end());
- return argv;
-}
-
-std::vector<std::string> AppExecutor::CreateAppArgv(const std::string& app_path,
- const tizen_base::Bundle& b, const std::string& app_type) {
- auto& inst = launchpad::Debug::GetInst();
- std::vector<std::string> argv = inst.GetArgv();
- if (inst.ShouldAttach())
- return argv;
-
- bool debug_mode = !argv.empty() ? true : false;
- auto launcher_argv = GetLauncherArgv(app_type);
- if (!launcher_argv.empty())
- argv.insert(argv.end(), launcher_argv.begin(), launcher_argv.end());
-
- auto exported_argv = b.Export();
- exported_argv[LoaderArg::Path] = app_path;
- if (debug_mode &&
- exported_argv.size() > static_cast<size_t>(LoaderArg::Type))
- exported_argv[LoaderArg::Type] = "'" + exported_argv[LoaderArg::Type] + "'";
-
- if (!exported_argv.empty())
- argv.insert(argv.end(), exported_argv.begin(), exported_argv.end());
-
- auto extra_argv = inst.GetExtraArgv();
- if (!extra_argv.empty())
- argv.insert(argv.end(), extra_argv.begin(), extra_argv.end());
-
- return argv;
-}
-
-} // namespace launchpad
+++ /dev/null
-/*
- * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef LAUNCHPAD_PROCESS_POOL_APP_EXECUTOR_HH_
-#define LAUNCHPAD_PROCESS_POOL_APP_EXECUTOR_HH_
-
-#include <bundle_cpp.h>
-
-#include <functional>
-#include <string>
-#include <vector>
-#include <memory>
-
-#include <app_info.hh>
-
-#include "launchpad-process-pool/executor.hh"
-#include "launchpad-process-pool/launcher_info.hh"
-#include "launchpad-process-pool/process_pool.hh"
-
-namespace launchpad {
-
-class AppExecutor : public Executor::Delegator,
- public Executor,
- public ProcessPool::IEvent {
- public:
- AppExecutor();
-
- pid_t Execute(const AppInfo* app_info);
- void DisposeCandidateProcess();
- void HandleSigchld(pid_t pid);
-
- private:
- void OnExecution() override;
- void OnRequestReceived(tizen_base::Parcel* parcel) override;
-
- int Prepare();
- int StepPluginPrepareApp();
- int StepEnableExternalPackage();
- int StepEnableTrustAnchor();
- int StepMountResDir();
- int StepChangeMountNamespace();
- int StepSecurityPrepareApp();
- int StepSetupStdio();
- int StepSetDumpable();
- int StepSetProcessName();
- int StepSetEnvironments();
- int StepWaitTepMount();
- int StepPrepareAppSocketAndIdFile();
- int StepSendStartupSignal();
-
- void CheckAndPrepareDebugging();
- std::vector<std::string> GetLauncherArgv(const std::string& app_type);
- std::vector<std::string> CreateAppArgv(const std::string& app_path,
- const tizen_base::Bundle& b, const std::string& app_type);
- LauncherInfoPtr FindLauncherInfo(const std::string& app_type);
-
- private:
- using PrepareFunc = std::function<int()>;
-
- std::vector<LauncherInfoPtr> launcher_infos_;
- std::vector<PrepareFunc> prepare_funcs_;
- std::unique_ptr<ProcessPool> process_pool_;
- const AppInfo* app_info_ = nullptr;
-};
-
-} // namespace launchpad
-
-#endif // LAUNCHPAD_PROCESS_POOL_APP_EXECUTOR_HH_
#include <utility>
+#include <util.hh>
+
#include "launchpad-process-pool/log_private.hh"
-#include "launchpad-process-pool/util.hh"
namespace launchpad {
namespace {
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";
-
constexpr const char kTagLaunchMode[] = "LaunchMode";
constexpr const char kKeyMode[] = "Mode";
constexpr const char kValueModePreviousOperation[] = "PREVIOUS_OPERATION";
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::LaunchMode::LaunchMode(const IniParser& parser) {
auto mode = parser.Get(kTagLaunchMode, kKeyMode);
if (!mode.empty()) {
- mode = ToUpper(mode);
+ mode = Util::ToUpper(mode);
if (mode == kValueModePreviousOperation)
mode_ = LaunchMode::Mode::PreviousOperation;
else if (mode == kValueModeDefaultOperation)
memory_monitor_(Config::MemoryMonitor(parser_)),
cpu_checker_(Config::CPUChecker(parser_)),
logger_(Config::Logger(parser_)),
- process_pool_(Config::ProcessPool(parser_)),
launch_mode_(Config::LaunchMode(parser_)) {
}
return logger_;
}
-const Config::ProcessPool& Config::GetProcessPool() const {
- return process_pool_;
-}
-
const Config::LaunchMode& Config::GetLaunchMode() const {
return launch_mode_;
}
bool enable_ = true;
};
- 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;
- };
-
class LaunchMode {
public:
enum class Mode : int {
const MemoryMonitor& GetMemoryMonitor() const;
const CPUChecker& GetCPUChecker() const;
const Logger& GetLogger() const;
- const ProcessPool& GetProcessPool() const;
const LaunchMode& GetLaunchMode() const;
private:
MemoryMonitor memory_monitor_;
CPUChecker cpu_checker_;
Logger logger_;
- ProcessPool process_pool_;
LaunchMode launch_mode_;
};
#include <utility>
#include <shared-queue.hpp>
+#include <rec_mutex.hh>
#include "launchpad-process-pool/log_private.hh"
-#include "launchpad-process-pool/rec_mutex.hh"
namespace launchpad {
namespace {
+++ /dev/null
-/*
- * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the License);
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an AS IS BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "launchpad-process-pool/debug.hh"
-
-#include <fcntl.h>
-#include <stdio.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-#include <fstream>
-#include <utility>
-
-#include <aul_keys.hh>
-#include <exception.hh>
-
-#include "launchpad-process-pool/log_private.hh"
-
-namespace fs = std::filesystem;
-
-namespace launchpad {
-namespace {
-
-constexpr const char kOptUsrShareAulDebugPath[] = "/opt/usr/share/aul/debug";
-constexpr const char kAsanAppList[] = ".asan_app_list";
-constexpr const char kAsanAppListPath[] =
- "/opt/usr/share/aul/debug/.asan_app_list";
-constexpr const char kDebuggerInfoPath[] = "/usr/share/aul";
-
-std::vector<std::string> GetStringArray(const tizen_base::Bundle& b,
- const std::string& key) {
- std::vector<std::string> values;
- if (b.GetType(key) & BUNDLE_TYPE_ARRAY) {
- values = b.GetStringArray(key);
- } else {
- std::string value = b.GetString(key);
- if (!value.empty())
- values.push_back(std::move(value));
- }
-
- return values;
-}
-
-} // namespace
-
-Debug& Debug::GetInst() {
- static Debug inst;
- inst.Init();
- return inst;
-}
-
-void Debug::Dispose() {
- if (disposed_)
- return;
-
- file_monitor_.reset();
- disposed_ = true;
-}
-
-bool Debug::Load() {
- if (!debugger_infos_.empty())
- return false;
-
- DebuggerInfoInflator inflator;
- debugger_infos_ = inflator.Inflate(kDebuggerInfoPath);
- return true;
-}
-
-void Debug::PrepareDebugger(const tizen_base::Bundle& b) {
- auto debugger = b.GetString(kAulSdk);
- if (debugger.empty())
- return;
-
- _D("[DEBUG] Debugger: %s", debugger.c_str());
- auto found = debugger_infos_.find(debugger);
- if (found == debugger_infos_.end()) {
- _W("Failed to find debugger(%s)", debugger.c_str());
- return;
- }
-
- debugger_info_ = found->second;
- if (debugger == "ASAN")
- setenv("TIZEN_ASAN_ACTIVATION", "1", 1);
-
- ParseAndRedirectStandardFds(b);
- RemoveFiles(debugger_info_->GetUnlinkList());
-
- for (const auto& extra_env : debugger_info_->GetExtraEnvList())
- ParseAndSetEnvironment(b, extra_env);
-
- debug_argv_ = debugger_info_->GetDefaultOptList();
- if (!debugger_info_->GetExe().empty())
- debug_argv_.insert(debug_argv_.begin(), debugger_info_->GetExe());
-
- for (const auto& extra_key : debugger_info_->GetExtraKeyList())
- ParseAndAddArgv(b, extra_key);
-
- for (const auto& last_extra_key : debugger_info_->GetLastExtraKeyList())
- ParseAndAddExtraArgv(b, last_extra_key);
-}
-
-void Debug::ChangeMountNamespace() {
- auto target_pid = std::getenv("TARGET_PID");
- if (target_pid == nullptr)
- return;
-
- std::string mnt_path = "/proc/" + std::string(target_pid) + "/ns/mnt";
- int fd = open(mnt_path.c_str(), O_RDONLY);
- if (fd < 0) {
- _E("open() is failed. path(%s), errno(%d)", mnt_path.c_str(), errno);
- return;
- }
-
- int ret = ::setns(fd, CLONE_NEWNS);
- close(fd);
- if (ret != 0) {
- _E("setns() is failed. errno(%d)", errno);
- return;
- }
-
- _D("setns() is successful");
-}
-
-void Debug::CheckWebAppDebugging(const tizen_base::Bundle& b) {
- if (b.GetType(kAulDebug) != BUNDLE_TYPE_NONE)
- setenv("TIZEN_DEBUGGING_PORT", "1", 1);
-}
-
-bool Debug::CheckAsanApp(const std::string& appid) {
- return asan_app_map_.find(appid) != asan_app_map_.end();
-}
-
-void Debug::CheckAndSetAsanActivation(const std::string& appid) {
- if (CheckAsanApp(appid)) {
- _W("Set TIZEN_ASAN_ACTIVATION. appid: %s", appid.c_str());
- setenv("TIZEN_ASAN_ACTIVATION", "1", 1);
- }
-}
-
-std::vector<std::string> Debug::GetExtraArgv() const {
- return extra_argv_;
-}
-
-std::vector<std::string> Debug::GetArgv() const {
- return debug_argv_;
-}
-
-bool Debug::ShouldAttach() const {
- if (!debugger_info_)
- return false;
-
- return debugger_info_->GetAttachInfo() == "true";
-}
-
-Debug::~Debug() {
- Dispose();
-}
-
-void Debug::Init() {
- if (!disposed_)
- return;
-
- try {
- file_monitor_ = std::make_unique<FileMonitor>(
- kOptUsrShareAulDebugPath, this);
- } catch (const Exception& e) {
- _E("Exception occurs. error: %s", e.what());
- return;
- }
-
- if (fs::exists(kAsanAppListPath))
- LoadAsanAppList();
-
- disposed_ = false;
-}
-
-void Debug::RemoveFiles(const std::vector<std::string>& files) {
- for (const auto& file : files) {
- if (fs::exists(file)) {
- _D("[DEBUG] file: %s", file.c_str());
- fs::remove(file);
- }
- }
-}
-
-void Debug::ParseAndSetEnvironment(const tizen_base::Bundle& b,
- const std::string& key) {
- _D("[DEBUG] key: %s", key.c_str());
- std::vector<std::string> values = GetStringArray(b, key);
- if (values.empty())
- return;
-
- std::string env;
- for (const auto& value : values) {
- if (!env.empty())
- env += ",";
-
- env += value;
- }
-
- const_cast<tizen_base::Bundle&>(b).Delete(key);
- _D("[DEBUG] value: %s", env.c_str());
- setenv(key.c_str(), env.c_str(), 1);
-}
-
-void Debug::ParseAndAddArgv(const tizen_base::Bundle& b,
- const std::string& key) {
- _D("[DEBUG] key: %s", key.c_str());
- std::vector<std::string> values = GetStringArray(b, key);
- if (values.empty())
- return;
-
- for (const auto& arg : values) {
- debug_argv_.push_back(arg);
- if (key == "__DLP_ATTACH_ARG__" && isdigit(arg[0])) {
- _D("[DEBUG] TARGET_PID: %s", arg.c_str());
- setenv("TARGET_PID", arg.c_str(), 1);
- }
- }
-
- const_cast<tizen_base::Bundle&>(b).Delete(key);
-}
-
-void Debug::ParseAndAddExtraArgv(const tizen_base::Bundle& b,
- const std::string& key) {
- _D("[DEBUG] key: %s", key.c_str());
- std::vector<std::string> values = GetStringArray(b, key);
- if (values.empty()) return;
-
- for (const auto& arg : values)
- extra_argv_.push_back(arg);
-
- const_cast<tizen_base::Bundle&>(b).Delete(key);
-}
-
-void Debug::ParseAndRedirectStandardFds(const tizen_base::Bundle& b) {
- pid_t caller_pid = GetCallerPid(b);
- if (caller_pid < 0)
- return;
-
- // stdin
- std::string path = "/proc/" + std::to_string(caller_pid) + "/fd/";
- int fd = open((path + std::to_string(STDIN_FILENO)).c_str(), O_RDONLY);
- if (fd < 0) {
- _E("Failed to open STDIN file descriptor. errno(%d)", errno);
- return;
- }
-
- dup2(fd, STDIN_FILENO);
- close(fd);
-
- // stdout
- fd = open((path + std::to_string(STDOUT_FILENO)).c_str(), O_WRONLY);
- if (fd < 0) {
- _E("Failed to open STDOUT file descriptor. errno(%d)", errno);
- return;
- }
-
- dup2(fd, STDOUT_FILENO);
- close(fd);
-
- // stdout
- fd = open((path + std::to_string(STDERR_FILENO)).c_str(), O_WRONLY);
- if (fd < 0) {
- _E("Failed to open STDERR file descriptor. errno(%d)", errno);
- return;
- }
-
- dup2(fd, STDERR_FILENO);
- close(fd);
-}
-
-pid_t Debug::GetCallerPid(const tizen_base::Bundle& b) {
- auto pid_str = b.GetString(kAulOrgCallerPid);
- if (pid_str.empty())
- pid_str = b.GetString(kAulCallerPid);
-
- if (pid_str.empty())
- return -1;
-
- return std::stoi(pid_str);
-}
-
-void Debug::LoadAsanAppList() {
- asan_app_map_.clear();
- std::ifstream if_stream;
- if_stream.open(kAsanAppListPath);
- if (!if_stream.is_open()) {
- _E("Failed to open %s", kAsanAppListPath);
- return;
- }
-
- std::string appid;
- while (!if_stream.eof()) {
- if_stream >> appid;
- asan_app_map_.insert(std::move(appid));
- }
-}
-
-void Debug::OnFileChanged(const std::string_view name,
- FileMonitor::Event event) {
- if (name != kAsanAppList)
- return;
-
- _W("%s was changed. event(%d)", kAsanAppList, static_cast<int>(event));
- LoadAsanAppList();
-}
-
-} // namespace launchpad
+++ /dev/null
-/*
- * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the License);
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an AS IS BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef LAUNCHPAD_PROCESS_POOL_DEBUG_HH_
-#define LAUNCHPAD_PROCESS_POOL_DEBUG_HH_
-
-#include <bundle_cpp.h>
-
-#include <list>
-#include <memory>
-#include <string>
-#include <unordered_map>
-#include <unordered_set>
-#include <vector>
-
-#include "launchpad-process-pool/debugger_info.hh"
-#include "launchpad-process-pool/file_monitor.hh"
-
-namespace launchpad {
-
-class Debug : public FileMonitor::IEvent {
- public:
- Debug(const Debug&) = delete;
- Debug& operator = (const Debug&) = delete;
- Debug(Debug&&) = delete;
- Debug& operator = (Debug&&) = delete;
-
- static Debug& GetInst();
- void Init();
- void Dispose();
- bool Load();
- void PrepareDebugger(const tizen_base::Bundle& b);
- std::vector<std::string> GetExtraArgv() const;
- std::vector<std::string> GetArgv() const;
- bool ShouldAttach() const;
- bool CheckAsanApp(const std::string& appid);
- void CheckAndSetAsanActivation(const std::string& appid);
-
- static void ChangeMountNamespace();
- static void CheckWebAppDebugging(const tizen_base::Bundle& b);
-
- private:
- Debug() = default;
- ~Debug();
-
- void RemoveFiles(const std::vector<std::string>& files);
- void ParseAndSetEnvironment(
- const tizen_base::Bundle& b, const std::string& key);
- void ParseAndAddArgv(const tizen_base::Bundle& b, const std::string& key);
- void ParseAndAddExtraArgv(const tizen_base::Bundle& b,
- const std::string& key);
- void ParseAndRedirectStandardFds(const tizen_base::Bundle& b);
- pid_t GetCallerPid(const tizen_base::Bundle& b);
-
- void LoadAsanAppList();
- void OnFileChanged(const std::string_view name,
- FileMonitor::Event event) override;
-
- private:
- bool disposed_ = true;
- DebuggerInfoPtr debugger_info_;
- std::unordered_map<std::string, DebuggerInfoPtr> debugger_infos_;
- std::vector<std::string> debug_argv_;
- std::vector<std::string> extra_argv_;
- std::unordered_set<std::string> asan_app_map_;
- std::unique_ptr<launchpad::FileMonitor> file_monitor_;
-};
-
-} // namespace launchpad
-
-#endif // LAUNCHPAD_PROCESS_POOL_DEBUG_HH_
+++ /dev/null
-/*
- * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the License);
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an AS IS BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "launchpad-process-pool/debugger_info.hh"
-
-#include <dirent.h>
-#include <limits.h>
-#include <malloc.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-#include <algorithm>
-#include <fstream>
-#include <sstream>
-#include <utility>
-
-#include "launchpad-process-pool/log_private.hh"
-#include "launchpad-process-pool/util.hh"
-
-namespace launchpad {
-namespace {
-
-constexpr const char kTagDebugger[] = "[DEBUGGER]";
-constexpr const char kTagName[] = "NAME";
-constexpr const char kTagExe[] = "EXE";
-constexpr const char kTagAppType[] = "APP_TYPE";
-constexpr const char kTagExtraKey[] = "EXTRA_KEY";
-constexpr const char kTagExtraEnv[] = "EXTRA_ENV";
-constexpr const char kTagUnlink[] = "UNLINK";
-constexpr const char kTagAttach[] = "ATTACH";
-constexpr const char kTagLastExtraKey[] = "LAST_EXTRA_KEY";
-constexpr const char kTagDefaultOpt[] = "DEFAULT_OPT";
-
-} // namespace
-
-namespace fs = std::filesystem;
-
-DebuggerInfo::Builder& DebuggerInfo::Builder::SetName(std::string name) {
- name_ = std::move(name);
- return *this;
-}
-
-DebuggerInfo::Builder& DebuggerInfo::Builder::SetExe(std::string exe) {
- exe_ = std::move(exe);
- return *this;
-}
-
-DebuggerInfo::Builder& DebuggerInfo::Builder::AddAppType(std::string app_type) {
- app_types_.push_back(std::move(app_type));
- return *this;
-}
-
-DebuggerInfo::Builder& DebuggerInfo::Builder::AddExtraKey(
- std::string extra_key) {
- extra_keys_.push_back(std::move(extra_key));
- return *this;
-}
-DebuggerInfo::Builder& DebuggerInfo::Builder::AddExtraEnv(
- std::string extra_env) {
- extra_envs_.push_back(std::move(extra_env));
- return *this;
-}
-
-DebuggerInfo::Builder& DebuggerInfo::Builder::AddFileToDelete(
- std::string file) {
- delete_files_.push_back(std::move(file));
- return *this;
-}
-
-DebuggerInfo::Builder& DebuggerInfo::Builder::SetAttach(std::string attach) {
- attach_ = std::move(attach);
- return *this;
-}
-
-DebuggerInfo::Builder& DebuggerInfo::Builder::AddLastExtraKey(
- std::string last_extra_key) {
- last_extra_keys_.push_back(std::move(last_extra_key));
- return *this;
-}
-
-DebuggerInfo::Builder& DebuggerInfo::Builder::AddDefaultOpt(
- std::string default_opt) {
- default_opts_.push_back(std::move(default_opt));
- return *this;
-}
-
-DebuggerInfo::Builder& DebuggerInfo::Builder::Reset() {
- name_.clear();
- exe_.clear();
- app_types_.clear();
- extra_keys_.clear();
- extra_envs_.clear();
- delete_files_.clear();
- attach_.clear();
- last_extra_keys_.clear();
- default_opts_.clear();
- return *this;
-}
-
-DebuggerInfo* DebuggerInfo::Builder::Build() {
- return new DebuggerInfo(std::move(name_), std::move(exe_),
- std::move(app_types_), std::move(extra_keys_), std::move(extra_envs_),
- std::move(delete_files_), std::move(attach_),
- std::move(last_extra_keys_), std::move(default_opts_));
-}
-
-DebuggerInfo::DebuggerInfo(std::string name, std::string exe,
- std::vector<std::string> app_types,
- std::vector<std::string> extra_keys,
- std::vector<std::string> extra_envs,
- std::vector<std::string> delete_files,
- std::string attach,
- std::vector<std::string> last_extra_keys,
- std::vector<std::string> default_opts)
- : name_(std::move(name)),
- exe_(std::move(exe)),
- app_types_(std::move(app_types)),
- extra_keys_(std::move(extra_keys)),
- extra_envs_(std::move(extra_envs)),
- delete_files_(std::move(delete_files)),
- attach_(std::move(attach)),
- last_extra_keys_(std::move(last_extra_keys)),
- default_opts_(std::move(default_opts)) {}
-
-const std::string& DebuggerInfo::GetName() const {
- return name_;
-}
-
-const std::string& DebuggerInfo::GetExe() const {
- return exe_;
-}
-
-const std::vector<std::string>& DebuggerInfo::GetAppTypes() const {
- return app_types_;
-}
-
-const std::vector<std::string>& DebuggerInfo::GetExtraKeyList() const {
- return extra_keys_;
-}
-
-const std::vector<std::string>& DebuggerInfo::GetExtraEnvList() const {
- return extra_envs_;
-}
-
-const std::vector<std::string>& DebuggerInfo::GetUnlinkList() const {
- return delete_files_;
-}
-
-const std::string& DebuggerInfo::GetAttachInfo() const {
- return attach_;
-}
-
-const std::vector<std::string>& DebuggerInfo::GetLastExtraKeyList() const {
- return last_extra_keys_;
-}
-
-const std::vector<std::string>& DebuggerInfo::GetDefaultOptList() const {
- return default_opts_;
-}
-
-DebuggerInfoInflator::DebuggerInfoInflator() {
- parsers_ = {
- { kTagName,
- std::bind(&DebuggerInfoInflator::ParseName,
- this, std::placeholders::_1) },
- { kTagExe,
- std::bind(&DebuggerInfoInflator::ParseExe,
- this, std::placeholders::_1) },
- { kTagAppType,
- std::bind(&DebuggerInfoInflator::ParseAppType,
- this, std::placeholders::_1) },
- { kTagExtraKey,
- std::bind(&DebuggerInfoInflator::ParseExtraKey,
- this, std::placeholders::_1) },
- { kTagExtraEnv,
- std::bind(&DebuggerInfoInflator::ParseExtraEnv,
- this, std::placeholders::_1) },
- { kTagUnlink,
- std::bind(&DebuggerInfoInflator::ParseUnlink,
- this, std::placeholders::_1) },
- { kTagAttach,
- std::bind(&DebuggerInfoInflator::ParseAttach,
- this, std::placeholders::_1) },
- { kTagLastExtraKey,
- std::bind(&DebuggerInfoInflator::ParseLastExtraKey,
- this, std::placeholders::_1) },
- { kTagDefaultOpt,
- std::bind(&DebuggerInfoInflator::ParseDefaultOpt,
- this, std::placeholders::_1) },
- };
-}
-
-std::unordered_map<std::string, DebuggerInfoPtr>
-DebuggerInfoInflator::Inflate(const std::string_view path) {
- fs::path input_path(path);
- if (fs::is_directory(input_path) == false)
- return debugger_infos_;
-
- try {
- for (auto& entry : fs::directory_iterator(input_path)) {
- fs::path file(entry.path());
- if (file.extension() == ".debugger")
- Parse(file);
- }
- } catch (const fs::filesystem_error& e) {
- _E("Exception occurs. error(%s:%d)", e.what(), e.code().value());
- }
-
- return debugger_infos_;
-}
-
-void DebuggerInfoInflator::ParseName(std::string token) {
- builder_.SetName(std::move(token));
-}
-
-void DebuggerInfoInflator::ParseExe(std::string token) {
- builder_.SetExe(std::move(token));
-}
-
-void DebuggerInfoInflator::ParseAppType(std::string token) {
- std::string line = std::move(token);
- do {
- auto tokens = Split(line, " |\t\r\n");
- for (auto& app_type : tokens) {
- _D("app-type: %s", app_type.c_str());
- builder_.AddAppType(app_type);
- }
- } while (std::getline(string_stream_, line));
-}
-
-void DebuggerInfoInflator::ParseExtraKey(std::string token) {
- builder_.AddExtraKey(std::move(token));
-}
-
-void DebuggerInfoInflator::ParseExtraEnv(std::string token) {
- builder_.AddExtraEnv(std::move(token));
-}
-
-void DebuggerInfoInflator::ParseUnlink(std::string token) {
- builder_.AddFileToDelete(std::move(token));
-}
-
-void DebuggerInfoInflator::ParseAttach(std::string token) {
- builder_.SetAttach(std::move(token));
-}
-
-void DebuggerInfoInflator::ParseLastExtraKey(std::string token) {
- builder_.AddLastExtraKey(std::move(token));
-}
-
-void DebuggerInfoInflator::ParseDefaultOpt(std::string token) {
- builder_.AddDefaultOpt(std::move(token));
-}
-
-void DebuggerInfoInflator::Parse(const fs::path& path) {
- std::ifstream input_file(path);
- if (!input_file.is_open())
- return;
-
- bool parsing = false;
- std::string input;
- while (std::getline(input_file, input)) {
- string_stream_ = std::istringstream(input);
- std::string token1;
- if (!(string_stream_ >> token1))
- continue;
-
- std::string key = ToUpper(std::move(token1));
- if (key == kTagDebugger) {
- if (parsing)
- InsertDebuggerInfo(std::shared_ptr<DebuggerInfo>(builder_.Build()));
-
- builder_.Reset();
- parsing = true;
- continue;
- }
-
- if (parsing == false)
- continue;
-
- std::string token2;
- if (!(string_stream_ >> token2))
- continue;
-
- auto found = parsers_.find(key);
- if (found == parsers_.end())
- continue;
-
- auto& parser = found->second;
- parser(std::move(token2));
- }
-
- if (parsing)
- InsertDebuggerInfo(std::shared_ptr<DebuggerInfo>(builder_.Build()));
-
- input_file.close();
-}
-
-void DebuggerInfoInflator::InsertDebuggerInfo(DebuggerInfoPtr info) {
- if (debugger_infos_.find(info->name_) != debugger_infos_.end())
- return;
-
- _D("name: %s, exe: %s", info->name_.c_str(), info->exe_.c_str());
- std::string name = info->name_;
- debugger_infos_[std::move(name)] = std::move(info);
-}
-
-} // namespace launchpad
+++ /dev/null
-/*
- * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the License);
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an AS IS BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef LAUNCHPAD_PROCESS_POOL_DEBUGGER_INFO_HH_
-#define LAUNCHPAD_PROCESS_POOL_DEBUGGER_INFO_HH_
-
-#include <filesystem>
-#include <functional>
-#include <memory>
-#include <string>
-#include <string_view>
-#include <unordered_map>
-#include <vector>
-
-namespace launchpad {
-
-class DebuggerInfo {
- public:
- class Builder {
- public:
- Builder& SetName(std::string name);
- Builder& SetExe(std::string exe);
- Builder& AddAppType(std::string app_type);
- Builder& AddExtraKey(std::string extra_key);
- Builder& AddExtraEnv(std::string extra_env);
- Builder& AddFileToDelete(std::string file);
- Builder& SetAttach(std::string attach);
- Builder& AddLastExtraKey(std::string last_extra_key);
- Builder& AddDefaultOpt(std::string default_opt);
- Builder& Reset();
-
- DebuggerInfo* Build();
-
- private:
- std::string name_;
- std::string exe_;
- std::vector<std::string> app_types_;
- std::vector<std::string> extra_keys_;
- std::vector<std::string> extra_envs_;
- std::vector<std::string> delete_files_;
- std::string attach_;
- std::vector<std::string> last_extra_keys_;
- std::vector<std::string> default_opts_;
- };
-
- DebuggerInfo(std::string name, std::string exe,
- std::vector<std::string> app_types,
- std::vector<std::string> extra_keys,
- std::vector<std::string> extra_envs,
- std::vector<std::string> delete_files,
- std::string attach,
- std::vector<std::string> last_extra_keys,
- std::vector<std::string> default_opts);
-
- const std::string& GetName() const;
- const std::string& GetExe() const;
- const std::vector<std::string>& GetAppTypes() const;
- const std::vector<std::string>& GetExtraKeyList() const;
- const std::vector<std::string>& GetExtraEnvList() const;
- const std::vector<std::string>& GetUnlinkList() const;
- const std::string& GetAttachInfo() const;
- const std::vector<std::string>& GetLastExtraKeyList() const;
- const std::vector<std::string>& GetDefaultOptList() const;
-
- private:
- std::string name_;
- std::string exe_;
- std::vector<std::string> app_types_;
- std::vector<std::string> extra_keys_;
- std::vector<std::string> extra_envs_;
- std::vector<std::string> delete_files_;
- std::string attach_;
- std::vector<std::string> last_extra_keys_;
- std::vector<std::string> default_opts_;
-
- friend class DebuggerInfoInflator;
-};
-
-using DebuggerInfoPtr = std::shared_ptr<DebuggerInfo>;
-
-class DebuggerInfoInflator {
- public:
- DebuggerInfoInflator();
-
- std::unordered_map<std::string, DebuggerInfoPtr> Inflate(
- const std::string_view path);
-
- private:
- void ParseName(std::string token);
- void ParseExe(std::string token);
- void ParseAppType(std::string token);
- void ParseExtraKey(std::string token);
- void ParseExtraEnv(std::string token);
- void ParseUnlink(std::string token);
- void ParseAttach(std::string token);
- void ParseLastExtraKey(std::string token);
- void ParseDefaultOpt(std::string token);
- void Parse(const std::filesystem::path& path);
-
- void InsertDebuggerInfo(DebuggerInfoPtr info);
-
- private:
- std::unordered_map<std::string, std::function<void(std::string)>> parsers_;
- std::unordered_map<std::string, DebuggerInfoPtr> debugger_infos_;
- std::istringstream string_stream_;
- DebuggerInfo::Builder builder_;
-};
-
-} // namespace launchpad
-
-#endif // LAUNCHPAD_PROCESS_POOL_DEBUGGER_INFO_HH_
+++ /dev/null
-/*
- * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "launchpad-process-pool/executor.hh"
-
-#include <stdlib.h>
-#include <unistd.h>
-
-#include <sched_priority.hh>
-
-#include "launchpad-process-pool/log_private.hh"
-#include "launchpad-process-pool/rec_mutex.hh"
-
-namespace launchpad {
-
-Executor::Executor(Executor::Delegator* delegator) : delegator_(delegator) {}
-
-pid_t Executor::Execute(int priority) {
- std::lock_guard<std::recursive_mutex> lock(RecMutex::GetInst().GetMutex());
- pid_t pid = fork();
- if (pid == -1) {
- _E("Failed to create child process. errno(%d)", errno);
- return -1;
- }
-
- if (pid == 0) {
- setsid();
- if (priority != 0)
- SchedPriority::Set(priority);
-
- _W("security_manager_prepare_app_candidate ++");
- int ret = security_manager_prepare_app_candidate();
- _W("security_manager_prepare_app_candidate --");
- if (ret != SECURITY_MANAGER_SUCCESS) {
- _E("Failed to prepare app candidate process. error(%d)", ret);
- exit(1);
- }
-
- delegator_->OnExecution();
- }
-
- return pid;
-}
-
-} // namespace launchpad
+++ /dev/null
-/*
- * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef LAUNCHPAD_PROCESS_POOL_EXECUTOR_HH_
-#define LAUNCHPAD_PROCESS_POOL_EXECUTOR_HH_
-
-#include <security-manager.h>
-#include <sys/types.h>
-
-namespace launchpad {
-
-class Executor {
- public:
- class Delegator {
- public:
- virtual ~Delegator() = default;
- virtual void OnExecution() = 0;
- };
-
- explicit Executor(Delegator* delegator);
- virtual ~Executor() = default;
-
- pid_t Execute(int priority = 0);
-
- private:
- Delegator* delegator_;
-};
-
-} // namespace launchpad
-
-#endif // LAUNCHPAD_PROCESS_POOL_EXECUTOR_HH_
+++ /dev/null
-/*
- * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "launchpad-process-pool/file_monitor.hh"
-
-#include <errno.h>
-
-#include <exception.hh>
-
-#include "launchpad-process-pool/log_private.hh"
-
-namespace launchpad {
-
-namespace fs = std::filesystem;
-
-void FileMonitor::OnIOEventReceived(int fd, int condition) {
- alignas(struct inotify_event) char buf[4096];
- const struct inotify_event* event;
- ssize_t len;
- while ((len = read(fd, buf, sizeof(buf))) > 0) {
- for (const char* ptr = buf; ptr < buf + len;
- ptr += sizeof(struct inotify_event) + event->len) {
- event = reinterpret_cast<const struct inotify_event*>(ptr);
- const char* nptr = ptr + sizeof(struct inotify_event) + event->len;
- if (nptr > buf + len)
- break;
-
- if (event->len) {
- if (listener_) {
- if (event->mask & IN_CREATE)
- listener_->OnFileChanged(event->name, Event::Created);
- else if (event->mask & IN_MODIFY)
- listener_->OnFileChanged(event->name, Event::Modified);
- else if (event->mask & IN_DELETE)
- listener_->OnFileChanged(event->name, Event::Deleted);
- }
- }
- }
- }
-}
-
-FileMonitor::FileMonitor(const std::string_view path,
- FileMonitor::IEvent* listener)
- : path_(path), listener_(listener) {
- if (!fs::exists(path_)) {
- try {
- if (!fs::create_directories(path_)) {
- _E("Failed to create directory. %s", path_.c_str());
- THROW(-EIO);
- }
- } catch (const std::exception& e) {
- _E("Exception has been occurred: %s", e.what());
- THROW(-EIO);
- }
- }
-
- int fd = inotify_init1(IN_NONBLOCK | IN_CLOEXEC);
- if (fd < 0) {
- int error_code = -errno;
- _E("inotify_init1() is failed. errno: %d", errno);
- THROW(error_code);
- }
-
- int wd = inotify_add_watch(fd, path_.c_str(),
- IN_CREATE | IN_MODIFY | IN_DELETE);
- if (wd < 0) {
- int error_code = -errno;
- _E("inotify_add_watch() is failed. errno: %d", errno);
- close(fd);
- THROW(error_code);
- }
-
- channel_ = std::make_unique<IOChannel>(fd, G_IO_IN, this);
- wd_ = wd;
- fd_ = fd;
-}
-
-FileMonitor::~FileMonitor() {
- channel_.reset();
-
- if (wd_ > 0)
- inotify_rm_watch(fd_, wd_);
-
- if (fd_ > 0)
- close(fd_);
-}
-
-} // namespace launchpad
+++ /dev/null
-/*
- * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef LAUNCHPAD_PROCESS_POOL_FILE_MONITOR_HH_
-#define LAUNCHPAD_PROCESS_POOL_FILE_MONITOR_HH_
-
-#include <sys/inotify.h>
-
-#include <filesystem>
-#include <memory>
-#include <string_view>
-
-#include <io_channel.hh>
-
-namespace launchpad {
-
-class FileMonitor : public IOChannel::IEvent {
- public:
- enum class Event : int {
- Created = IN_CREATE,
- Modified = IN_MODIFY,
- Deleted = IN_DELETE,
- };
-
- class IEvent {
- public:
- virtual ~IEvent() = default;
- virtual void OnFileChanged(const std::string_view name, Event event) = 0;
- };
-
- FileMonitor(const std::string_view path, IEvent *listener);
- virtual ~FileMonitor();
-
- FileMonitor(const FileMonitor &) = delete;
- FileMonitor &operator=(const FileMonitor &) = delete;
-
- private:
- void OnIOEventReceived(int fd, int condition) override;
-
- private:
- std::filesystem::path path_;
- IEvent *listener_;
- int fd_ = 0;
- int wd_ = 0;
- std::unique_ptr<IOChannel> channel_;
-};
-
-} // namespace launchpad
-
-#endif // LAUNCHPAD_PROCESS_POOL_FILE_MONITOR_HH_
+++ /dev/null
-/*
- * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the License);
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an AS IS BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "launchpad-process-pool/launcher_info.hh"
-
-#include <algorithm>
-#include <fstream>
-#include <sstream>
-#include <utility>
-
-#include <util.hh>
-
-#include "launchpad-process-pool/log_private.hh"
-#include "launchpad-process-pool/util.hh"
-
-namespace launchpad {
-namespace {
-
-constexpr const char kTagLauncher[] = "[LAUNCHER]";
-constexpr const char kTagName[] = "NAME";
-constexpr const char kTagExe[] = "EXE";
-constexpr const char kTagAppType[] = "APP_TYPE";
-constexpr const char kTagExtraArg[] = "EXTRA_ARG";
-
-} // namespace
-
-namespace fs = std::filesystem;
-
-LauncherInfo::Builder& LauncherInfo::Builder::SetName(std::string name) {
- name_ = std::move(name);
- return *this;
-}
-
-LauncherInfo::Builder& LauncherInfo::Builder::SetExe(std::string exe) {
- exe_ = std::move(exe);
- return *this;
-}
-
-LauncherInfo::Builder& LauncherInfo::Builder::AddAppType(std::string app_type) {
- app_types_.push_back(std::move(app_type));
- return *this;
-}
-
-LauncherInfo::Builder& LauncherInfo::Builder::AddExtraArg(
- std::string extra_arg) {
- extra_args_.push_back(std::move(extra_arg));
- return *this;
-}
-
-LauncherInfo::Builder& LauncherInfo::Builder::Reset() {
- name_.clear();
- exe_.clear();
- app_types_.clear();
- extra_args_.clear();
- return *this;
-}
-
-LauncherInfo* LauncherInfo::Builder::Build() {
- return new LauncherInfo(std::move(name_), std::move(exe_),
- std::move(app_types_), std::move(extra_args_));
-}
-
-LauncherInfo::LauncherInfo(std::string name, std::string exe,
- std::vector<std::string> app_types, std::vector<std::string> extra_args)
- : name_(std::move(name)),
- exe_(std::move(exe)),
- app_types_(std::move(app_types)),
- extra_args_(std::move(extra_args)) {
-}
-
-const std::string& LauncherInfo::GetName() const {
- return name_;
-}
-
-const std::string& LauncherInfo::GetExe() const {
- return exe_;
-}
-
-const std::vector<std::string>& LauncherInfo::GetAppTypes() const {
- return app_types_;
-}
-
-const std::vector<std::string>& LauncherInfo::GetExtraArgs() const {
- return extra_args_;
-}
-
-LauncherInfoInflator::LauncherInfoInflator() {
- parsers_ = {
- { kTagName,
- std::bind(&LauncherInfoInflator::ParseName,
- this, std::placeholders::_1) },
- { kTagExe,
- std::bind(&LauncherInfoInflator::ParseExe,
- this, std::placeholders::_1) },
- { kTagAppType,
- std::bind(&LauncherInfoInflator::ParseAppType,
- this, std::placeholders::_1) },
- { kTagExtraArg,
- std::bind(&LauncherInfoInflator::ParseExtraArg,
- this, std::placeholders::_1) },
- };
-}
-
-void LauncherInfoInflator::ParseName(std::string token) {
- builder_.SetName(std::move(token));
-}
-
-void LauncherInfoInflator::ParseExe(std::string token) {
- builder_.SetExe(std::move(token));
-}
-
-void LauncherInfoInflator::ParseAppType(std::string token) {
- std::string line = std::move(token);
- do {
- auto tokens = Split(line, " |\t\r\n");
- for (auto& app_type : tokens)
- builder_.AddAppType(app_type);
- } while (std::getline(string_stream_, line));
-}
-
-void LauncherInfoInflator::ParseExtraArg(std::string token) {
- builder_.AddExtraArg(std::move(token));
-}
-
-void LauncherInfoInflator::Parse(const fs::path& path) {
- std::ifstream launcher_file;
- launcher_file.open(path);
- if (launcher_file.fail())
- return;
-
- bool parsing = false;
- std::string line;
- while (std::getline(launcher_file, line)) {
- string_stream_ = std::istringstream(line);
- std::string token1;
- if (!(string_stream_ >> token1))
- continue;
-
- std::string key = ToUpper(std::move(token1));
- if (key == kTagLauncher) {
- if (parsing)
- Insert();
-
- builder_.Reset();
- parsing = true;
- continue;
- }
-
- if (parsing == false)
- continue;
-
- std::string token2;
- if (!(string_stream_ >> token2))
- continue;
-
- auto found = parsers_.find(key);
- if (found == parsers_.end())
- continue;
-
- auto& parser = found->second;
- parser(std::move(token2));
- }
-
- if (parsing)
- Insert();
-
- launcher_file.close();
-}
-
-void LauncherInfoInflator::Insert() {
- launcher_infos_.emplace_back(builder_.Build());
-}
-
-std::vector<LauncherInfoPtr> LauncherInfoInflator::Inflate(
- const std::string_view path) {
- fs::path dir_path(path);
- if (fs::is_directory(dir_path) == false)
- return {};
-
- try {
- for (auto& entry : fs::directory_iterator(dir_path)) {
- fs::path file(entry.path());
- if (file.extension() == ".launcher") {
- Parse(file);
- }
- }
- } catch (const fs::filesystem_error& e) {
- _E("Exception occurs. error(%s:%d)", e.what(), e.code().value());
- }
-
- return launcher_infos_;
-}
-
-} // namespace launchpad
+++ /dev/null
-/*
- * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the License);
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an AS IS BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef LAUNCHPAD_PROCESS_POOL_LAUNCHER_INFO_HH_
-#define LAUNCHPAD_PROCESS_POOL_LAUNCHER_INFO_HH_
-
-#include <filesystem>
-#include <functional>
-#include <memory>
-#include <string>
-#include <string_view>
-#include <unordered_map>
-#include <vector>
-
-namespace launchpad {
-
-class LauncherInfo {
- public:
- class Builder {
- public:
- Builder& SetName(std::string name);
- Builder& SetExe(std::string exe);
- Builder& AddAppType(std::string app_type);
- Builder& AddExtraArg(std::string extra_arg);
- Builder& Reset();
-
- LauncherInfo* Build();
-
- private:
- std::string name_;
- std::string exe_;
- std::vector<std::string> app_types_;
- std::vector<std::string> extra_args_;
- };
-
- LauncherInfo(std::string name, std::string exe,
- std::vector<std::string> app_types, std::vector<std::string> extra_args);
-
- const std::string& GetName() const;
- const std::string& GetExe() const;
- const std::vector<std::string>& GetAppTypes() const;
- const std::vector<std::string>& GetExtraArgs() const;
-
- private:
- friend class LauncherInfoInflator;
-
- std::string name_;
- std::string exe_;
- std::vector<std::string> app_types_;
- std::vector<std::string> extra_args_;
-};
-
-using LauncherInfoPtr = std::shared_ptr<LauncherInfo>;
-
-class LauncherInfoInflator {
- public:
- LauncherInfoInflator();
-
- std::vector<LauncherInfoPtr> Inflate(const std::string_view path);
-
- private:
- void Parse(const std::filesystem::path& path);
-
- void ParseName(std::string token);
- void ParseExe(std::string token);
- void ParseAppType(std::string token);
- void ParseExtraArg(std::string token);
- void Insert();
-
- private:
- std::unordered_map<std::string, std::function<void(std::string)>> parsers_;
- std::istringstream string_stream_;
- LauncherInfo::Builder builder_;
- std::vector<std::shared_ptr<LauncherInfo>> launcher_infos_;
-};
-
-} // namespace launchpad
-
-#endif // LAUNCHPAD_PROCESS_POOL_LAUNCHER_INFO_HH_
#include <app_info.hh>
#include <aul_keys.hh>
#include <cpu_boost_controller.hh>
+#include <debug.hh>
#include <exception.hh>
#include <executor.hh>
+#include <launchpad_args.hh>
+#include <loader_executor.hh>
#include <procfs.hh>
#include <sched_priority.hh>
#include <types.hh>
#include "launchpad-process-pool/config.hh"
#include "launchpad-process-pool/dbus.hh"
-#include "launchpad-process-pool/debug.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/log_private.hh"
#include "launchpad-process-pool/memory_monitor.hh"
#include "launchpad-process-pool/signal_manager.hh"
#include "launchpad-process-pool/tracer.hh"
-#include "launchpad-process-pool/util.hh"
#include "launchpad-process-pool/worker.hh"
namespace launchpad {
#include <unordered_map>
#include <vector>
+#include <app_executor.hh>
#include <language_config.hh>
#include <io_channel.hh>
#include <region_format_config.hh>
#include <server_socket.hh>
-#include "launchpad-process-pool/app_executor.hh"
#include "launchpad-process-pool/config.hh"
#include "launchpad-process-pool/loader_manager.hh"
#include "launchpad-process-pool/request.hh"
+++ /dev/null
-/*
- * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "launchpad-process-pool/launchpad_args.hh"
-
-namespace launchpad {
-
-LaunchpadArgs& LaunchpadArgs::GetInst() {
- static LaunchpadArgs inst;
- return inst;
-}
-
-void LaunchpadArgs::Set(int argc, char** args) {
- argc_ = argc;
- args_ = args;
-}
-
-int LaunchpadArgs::GetArgc() const {
- return argc_;
-}
-
-char** LaunchpadArgs::GetArgs() const {
- return args_;
-}
-
-} // namespace launchpad
+++ /dev/null
-/*
- * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef LAUNCHPAD_PROCESS_POOL_LAUNCHPAD_ARGS_HH_
-#define LAUNCHPAD_PROCESS_POOL_LAUNCHPAD_ARGS_HH_
-
-namespace launchpad {
-
-class LaunchpadArgs {
- public:
- LaunchpadArgs(const LaunchpadArgs&) = delete;
- LaunchpadArgs& operator=(const LaunchpadArgs&) = delete;
-
- static LaunchpadArgs& GetInst();
-
- void Set(int argc, char** args);
-
- int GetArgc() const;
- char** GetArgs() const;
-
- private:
- LaunchpadArgs() = default;
- ~LaunchpadArgs() = default;
-
- private:
- int argc_ = 0;
- char** args_ = nullptr;
-};
-
-} // namespace launchpad
-
-#endif // LAUNCHPAD_PROCESS_POOL_LAUNCHPAD_ARGS_HH_
#include <utility>
#include <exception.hh>
+#include <loader_executor.hh>
#include <peer_credentials.hh>
#include <procfs.hh>
+#include <types.hh>
#include <user_tracer.hh>
#include <util.hh>
-#include <types.hh>
#include "launchpad-process-pool/app_labels_monitor.hh"
#include "launchpad-process-pool/config.hh"
-#include "launchpad-process-pool/loader_executor.hh"
#include "launchpad-process-pool/log.hh"
#include "launchpad-process-pool/log_private.hh"
#include "launchpad-process-pool/memory_monitor.hh"
-#include "launchpad-process-pool/util.hh"
namespace fs = std::filesystem;
VerifyLoaderCaps(executable_file);
}
- loader_extra_ = reinterpret_cast<const char*>(
- loader_info_->GetExtra().ToRaw().first.get());
Listen();
condition_path_exists_ = loader_info_->GetConditionPathExists();
}
pid_t LoaderContext::Prepare() {
bool set_priority = (Config::GetInst().GetLaunchMode().GetMode() !=
Config::LaunchMode::Mode::AlwaysLoaderWithLowPriority);
- pid_ = LoaderExecutor::GetInst().Execute(this,
+ pid_ = LoaderExecutor::GetInst().Execute(
+ loader_info_.get(), loader_id_,
set_priority ? loader_info_->GetSchedPriority() : 0);
_W("Prepare. type(%d), name(%s), pid(%d)",
GetType(), GetLoaderName().c_str(), pid_);
return loader_info_->GetExe();
}
-const std::string& LoaderContext::GetLoaderExtra() const {
- return loader_extra_;
-}
-
int LoaderContext::GetType() const {
return static_cast<int>(loader_info_->GetType());
}
#include <app_info.hh>
#include <client_socket.hh>
#include <io_channel.hh>
+#include <loader_info.hh>
#include <server_socket.hh>
#include "launchpad-process-pool/cpu_checker.hh"
-#include "launchpad-process-pool/loader_info.hh"
-#include "launchpad-process-pool/launcher_info.hh"
#include "launchpad-process-pool/loader_mount.hh"
namespace launchpad {
const std::string& GetLoaderName() const;
const std::string& GetLoaderPath() const;
- const std::string& GetLoaderExtra() const;
int GetType() const;
bool IsPrepared() const;
pid_t GetPid() const;
std::shared_ptr<LoaderMount> loader_mount_;
std::unique_ptr<CPUChecker> cpu_checker_;
unsigned int score_;
- std::string loader_extra_;
std::unique_ptr<ServerSocket> server_socket_;
std::unique_ptr<IOChannel> server_channel_;
std::unique_ptr<ClientSocket> client_socket_;
+++ /dev/null
-/*
- * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the License);
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an AS IS BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "launchpad-process-pool/loader_executor.hh"
-
-#include <errno.h>
-#include <stdio.h>
-#include <unistd.h>
-
-#include <utility>
-
-#include <parcel.hh>
-#include <sched_priority.hh>
-#include <stdio.hh>
-#include <types.hh>
-#include <util.hh>
-
-#include "launchpad-process-pool/config.hh"
-#include "launchpad-process-pool/log_private.hh"
-#include "launchpad-process-pool/signal_manager.hh"
-
-namespace launchpad {
-namespace {
-
-tizen_base::Parcel CreateParcelFromBundle(tizen_base::Bundle* b) {
- auto b_raw = b->ToRaw();
- std::string raw(reinterpret_cast<const char*>(b_raw.first.get()));
- tizen_base::Parcel parcel;
- parcel.WriteString(raw);
- return parcel;
-}
-
-tizen_base::Bundle CreateBundleFromParcel(tizen_base::Parcel* parcel) {
- std::string raw = parcel->ReadString();
- return tizen_base::Bundle(raw);
-}
-
-} // namespace
-
-LoaderExecutor::LoaderExecutor() : Executor(this) {
- auto& process_pool_config = Config::GetInst().GetProcessPool();
- process_pool_ = std::unique_ptr<ProcessPool>(
- new ProcessPool("loader",
- process_pool_config.GetNumberOfLoaderProcesses(), this));
-}
-
-LoaderExecutor& LoaderExecutor::GetInst() {
- static LoaderExecutor inst;
- return inst;
-}
-
-pid_t LoaderExecutor::Execute(const LoaderContext* loader_context,
- int priority) {
- loader_argv_ = CreateLoaderArgv(loader_context);
- if (process_pool_->IsPrepared()) {
- tizen_base::Bundle b;
- b.Add("LOADER_ARGS", loader_argv_);
- b.Add("LOADER_PRIORITY", std::to_string(priority));
- auto parcel = CreateParcelFromBundle(&b);
- pid_t pid = process_pool_->Execute(parcel);
- if (pid > 0)
- return pid;
- }
-
- return Executor::Execute(priority);
-}
-
-bool LoaderExecutor::HasCandidateProcess() const {
- return process_pool_->IsPrepared();
-}
-
-void LoaderExecutor::DisposeCandidateProcess() {
- process_pool_->Dispose();
- process_pool_->SetTimer();
-}
-
-void LoaderExecutor::HandleSigchld(pid_t pid) {
- process_pool_->HandleSigchld(pid);
-}
-
-void LoaderExecutor::OnExecution() {
- std::vector<char*> loader_argv(loader_argv_.size() + 1);
- int loader_argc = loader_argv_.size();
- for (int i = 0; i < loader_argc; ++i) {
- loader_argv[i] = const_cast<char*>(loader_argv_[i].c_str());
- if ((i + 1) != loader_argc)
- SECURE_LOGD("loader argument %d : %s##", i, loader_argv[i]);
- }
-
- SignalManager::GetInst().UnblockSigchld();
- Util::CloseAllFds();
- Stdio::Setup();
-
- SECURE_LOGE("Execute loader(%s)", loader_argv[LoaderArg::Path]);
- if (execv(loader_argv[LoaderArg::Path], loader_argv.data()) < 0) {
- char err_buf[1024];
- fprintf(stderr, "Failed to execute a file. path: %s, errno: %d:%s\n",
- loader_argv[LoaderArg::Path], errno,
- strerror_r(errno, err_buf, sizeof(err_buf)));
- exit(EXIT_FAILURE);
- }
-}
-
-void LoaderExecutor::OnRequestReceived(tizen_base::Parcel* parcel) {
- _W("Request received");
- 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();
-}
-
-std::vector<std::string> LoaderExecutor::CreateLoaderArgv(
- const LoaderContext* loader_context) {
- std::string dummy(kLoaderArgLength - 1, ' ');
- std::vector<std::string> argv(LoaderArg::Dummy + 1);
- argv[LoaderArg::Dummy] = std::move(dummy);
- argv[LoaderArg::Path] = loader_context->GetLoaderPath();
- argv[LoaderArg::Type] = std::to_string(loader_context->GetType());
- argv[LoaderArg::Id] = std::to_string(loader_context->GetLoaderId());
- argv[LoaderArg::Hydra] = loader_context->IsHydraMode() ? "1" : "0";
- argv[LoaderArg::Extra] = loader_context->GetLoaderExtra();
- return argv;
-}
-
-} // namespace launchpad
+++ /dev/null
-/*
- * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the License);
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an AS IS BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef LAUNCHPAD_PROCESS_POOL_LOADER_EXECUTOR_HH_
-#define LAUNCHPAD_PROCESS_POOL_LOADER_EXECUTOR_HH_
-
-#include <sys/types.h>
-
-#include <memory>
-#include <string>
-#include <vector>
-
-#include "launchpad-process-pool/executor.hh"
-#include "launchpad-process-pool/loader_context.hh"
-#include "launchpad-process-pool/process_pool.hh"
-
-namespace launchpad {
-
-class LoaderExecutor : public Executor::Delegator,
- public Executor,
- public ProcessPool::IEvent {
- public:
- LoaderExecutor(const LoaderExecutor&) = delete;
- LoaderExecutor& operator=(const LoaderExecutor&) = delete;
- LoaderExecutor(LoaderExecutor&&) = delete;
- LoaderExecutor& operator=(LoaderExecutor&&) = delete;
-
- static LoaderExecutor& GetInst();
-
- pid_t Execute(const LoaderContext* loader_context, int priority);
- bool HasCandidateProcess() const;
- void DisposeCandidateProcess();
- void HandleSigchld(pid_t pid);
-
- private:
- LoaderExecutor();
- ~LoaderExecutor() = default;
-
- void OnExecution() override;
- void OnRequestReceived(tizen_base::Parcel* parcel) override;
- std::vector<std::string> CreateLoaderArgv(
- const LoaderContext* loader_context);
-
- private:
- std::unique_ptr<ProcessPool> process_pool_;
- std::vector<std::string> loader_argv_;
-};
-
-} // namespace launchpad
-
-#endif // LAUNCHPAD_PROCESS_POOL_LOADER_EXECUTOR_HH_
#include <memory>
#include <vector>
+#include <loader_info.hh>
#include <types.hh>
#include "launchpad-process-pool/loader_context.hh"
-#include "launchpad-process-pool/loader_info.hh"
namespace launchpad {
+++ /dev/null
-/*
- * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the License);
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an AS IS BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "launchpad-process-pool/loader_info.hh"
-
-#include <dirent.h>
-#include <malloc.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <algorithm>
-#include <fstream>
-#include <sstream>
-#include <utility>
-
-#include "launchpad-process-pool/log_private.hh"
-#include "launchpad-process-pool/util.hh"
-
-namespace fs = std::filesystem;
-
-namespace launchpad {
-namespace {
-
-constexpr const char kTagLoader[] = "[LOADER]";
-constexpr const char kTagName[] = "NAME";
-constexpr const char kTagExe[] = "EXE";
-constexpr const char kTagAppType[] = "APP_TYPE";
-constexpr const char kTagDetectionMethod[] = "DETECTION_METHOD";
-constexpr const char kTagActivationMethod[] = "ACTIVATION_METHOD";
-constexpr const char kTagDeactivationMethod[] = "DEACTIVATION_METHOD";
-constexpr const char kTagTtl[] = "TTL";
-constexpr const char kTagTimeout[] = "TIMEOUT";
-constexpr const char kTagExtra[] = "EXTRA";
-constexpr const char kTagExtraArray[] = "EXTRA_ARRAY";
-constexpr const char kTagExtraArrayVal[] = "EXTRA_ARRAY_VAL";
-constexpr const char kTagAlternativeLoader[] = "ALTERNATIVE_LOADER";
-constexpr const char kTagHwAcc[] = "HW_ACC";
-constexpr const char kTagCpuThresholdMax[] = "CPU_THRESHOLD_MAX";
-constexpr const char kTagCpuThresholdMin[] = "CPU_THRESHOLD_MIN";
-constexpr const char kTagOnBoot[] = "ON_BOOT";
-constexpr const char kTagHydra[] = "HYDRA";
-constexpr const char kTagAppCheck[] = "APP_CHECK";
-constexpr const char kTagOnBootTimeout[] = "ON_BOOT_TIMEOUT";
-constexpr const char kTagSchedPriority[] = "SCHED_PRIORITY";
-constexpr const char kTagConditionPathExists[] = "CONDITION_PATH_EXISTS";
-
-constexpr const char kValOn[] = "ON";
-constexpr const char kValOff[] = "OFF";
-constexpr const char kValMethodTimeout[] = "TIMEOUT";
-constexpr const char kValMethodDemand[] = "DEMAND";
-constexpr const char kValMethodVisibility[] = "VISIBILITY";
-constexpr const char kValMethodRequest[] = "REQUEST";
-constexpr const char kValMethodAvailableMemory[] = "AVAILABLE_MEMORY";
-constexpr const char kValMethodTtl[] = "TTL";
-constexpr const char kValMethodOutOfMemory[] = "OUT_OF_MEMORY";
-
-LoaderType MakeLoaderType() {
- static uint32_t user_slot_offset;
- return static_cast<LoaderType>(
- static_cast<int>(LoaderType::User) + user_slot_offset++);
-}
-
-} // namespace
-
-LoaderInfo::Builder& LoaderInfo::Builder::SetType(LoaderType type) {
- type_ = type;
- return *this;
-}
-
-LoaderInfo::Builder& LoaderInfo::Builder::SetName(std::string name) {
- name_ = std::move(name);
- return *this;
-}
-
-LoaderInfo::Builder& LoaderInfo::Builder::SetExe(std::string exe) {
- exe_ = std::move(exe);
- return *this;
-}
-
-LoaderInfo::Builder& LoaderInfo::Builder::AddAppType(std::string app_type) {
- app_types_.push_back(std::move(app_type));
- return *this;
-}
-
-LoaderInfo::Builder& LoaderInfo::Builder::SetAppTypes(
- std::vector<std::string> app_types) {
- app_types_ = std::move(app_types);
- return *this;
-}
-
-LoaderInfo::Builder& LoaderInfo::Builder::SetDetectionMethod(
- LoaderMethod method) {
- detection_method_ = method;
- return *this;
-}
-
-LoaderInfo::Builder& LoaderInfo::Builder::SetActivationMethod(
- LoaderMethod method) {
- activation_method_ = method;
- return *this;
-}
-
-LoaderInfo::Builder& LoaderInfo::Builder::SetDeactivationMethod(
- LoaderMethod method) {
- deactivation_method_ = method;
- return *this;
-}
-
-LoaderInfo::Builder& LoaderInfo::Builder::SetTimeout(int timeout) {
- timeout_ = timeout;
- return *this;
-}
-
-LoaderInfo::Builder& LoaderInfo::Builder::SetHwAcc(std::string hw_acc) {
- hw_acc_ = std::move(hw_acc);
- return *this;
-}
-
-LoaderInfo::Builder& LoaderInfo::Builder::AddAlternativeLoader(
- std::string alternative_loader) {
- alternative_loaders_.push_back(std::move(alternative_loader));
- return *this;
-}
-
-LoaderInfo::Builder& LoaderInfo::Builder::SetAlternativeLoaders(
- std::vector<std::string> alternative_loaders) {
- alternative_loaders_ = std::move(alternative_loaders);
- return *this;
-}
-
-LoaderInfo::Builder& LoaderInfo::Builder::AddExtraData(std::string key,
- std::string value) {
- extra_.Add(std::move(key), std::move(value));
- return *this;
-}
-
-LoaderInfo::Builder& LoaderInfo::Builder::AddExtraArrayData(std::string key,
- std::vector<std::string> value) {
- extra_.Add(std::move(key), std::move(value));
- return *this;
-}
-
-LoaderInfo::Builder& LoaderInfo::Builder::SetExtra(tizen_base::Bundle extra) {
- extra_ = std::move(extra);
- return *this;
-}
-
-LoaderInfo::Builder& LoaderInfo::Builder::SetCPUThresholdMax(
- int cpu_threshold_max) {
- cpu_threshold_max_ = cpu_threshold_max;
- return *this;
-}
-
-LoaderInfo::Builder& LoaderInfo::Builder::SetCPUThresholdMin(
- int cpu_threshold_min) {
- cpu_threshold_min_ = cpu_threshold_min;
- return *this;
-}
-
-LoaderInfo::Builder& LoaderInfo::Builder::SetOnBoot(bool on_boot) {
- on_boot_ = on_boot;
- return *this;
-}
-
-LoaderInfo::Builder& LoaderInfo::Builder::SetTimeToLive(int time_to_live) {
- time_to_live_ = time_to_live;
- return *this;
-}
-
-LoaderInfo::Builder& LoaderInfo::Builder::SetHydraMode(bool hydra_mode) {
- hydra_mode_ = hydra_mode;
- return *this;
-}
-
-LoaderInfo::Builder& LoaderInfo::Builder::SetAppCheck(bool app_check) {
- app_check_ = app_check;
- return *this;
-}
-
-LoaderInfo::Builder& LoaderInfo::Builder::SetOnBootTimeout(
- int on_boot_timeout) {
- on_boot_timeout_ = on_boot_timeout;
- return *this;
-}
-
-LoaderInfo::Builder& LoaderInfo::Builder::SetSchedPriority(int sched_priority) {
- sched_priority_ = sched_priority;
- return *this;
-}
-
-LoaderInfo::Builder& LoaderInfo::Builder::AddConditionPathExists(
- std::string path) {
- condition_path_exists_.push_back(std::move(path));
- return *this;
-}
-
-LoaderInfo::Builder& LoaderInfo::Builder::SetConditionPathExists(
- std::vector<std::string> condition_path_exists) {
- condition_path_exists_ = std::move(condition_path_exists);
- return *this;
-}
-
-LoaderInfo::Builder& LoaderInfo::Builder::Reset() {
- type_ = LoaderType::None;
- name_.clear();
- exe_.clear();
- app_types_.clear();
- detection_method_ = LoaderMethod::Timeout | LoaderMethod::Visibility |
- LoaderMethod::Install;
- activation_method_ = LoaderMethod::None;
- deactivation_method_ = LoaderMethod::None;
- timeout_ = 5000;
- hw_acc_.clear();
- alternative_loaders_.clear();
- extra_ = tizen_base::Bundle();
- cpu_threshold_max_ = 90;
- cpu_threshold_min_ = 40;
- on_boot_ = true;
- time_to_live_ = 600;
- hydra_mode_ = false;
- app_check_ = true;
- on_boot_timeout_ = 0;
- sched_priority_ = 0;
- condition_path_exists_.clear();
- return *this;
-}
-
-LoaderInfo* LoaderInfo::Builder::Build() {
- return new LoaderInfo(type_, std::move(name_), std::move(exe_),
- std::move(app_types_), detection_method_, activation_method_,
- deactivation_method_, timeout_, std::move(hw_acc_),
- std::move(alternative_loaders_), std::move(extra_),
- cpu_threshold_max_, cpu_threshold_min_, on_boot_, time_to_live_,
- hydra_mode_, app_check_, on_boot_timeout_, sched_priority_,
- std::move(condition_path_exists_));
-}
-
-LoaderInfo::LoaderInfo(LoaderType type, std::string name, std::string exe,
- std::vector<std::string> app_types, LoaderMethod detection_method,
- LoaderMethod activation_method, LoaderMethod deactivation_method,
- int timeout, std::string hw_acc,
- std::vector<std::string> alternative_loaders,
- tizen_base::Bundle extra, int cpu_threshold_max,
- int cpu_threshold_min, bool on_boot, int time_to_live,
- bool hydra_mode, bool app_check, int on_boot_timeout,
- int sched_priority, std::vector<std::string> condition_path_exists)
- : type_(type),
- name_(std::move(name)),
- exe_(std::move(exe)),
- app_types_(std::move(app_types)),
- detection_method_(detection_method),
- activation_method_(activation_method),
- deactivation_method_(deactivation_method),
- timeout_(timeout),
- hw_acc_(std::move(hw_acc)),
- alternative_loaders_(std::move(alternative_loaders)),
- extra_(std::move(extra)),
- cpu_threshold_max_(cpu_threshold_max),
- cpu_threshold_min_(cpu_threshold_min),
- on_boot_(on_boot),
- time_to_live_(time_to_live),
- hydra_mode_(hydra_mode),
- app_check_(app_check),
- on_boot_timeout_(on_boot_timeout),
- sched_priority_(sched_priority),
- condition_path_exists_(std::move(condition_path_exists)) {
- extra_.Add("SCHED_PRIORITY", std::to_string(sched_priority_));
-}
-
-LoaderType LoaderInfo::GetType() const {
- return type_;
-}
-
-void LoaderInfo::SetType(LoaderType type) {
- type_ = type;
-}
-
-const std::string& LoaderInfo::GetName() const {
- return name_;
-}
-
-const std::string& LoaderInfo::GetExe() const {
- return exe_;
-}
-
-void LoaderInfo::SetExe(std::string exe) {
- exe_ = std::move(exe);
-}
-
-int LoaderInfo::GetCpuThresholdMax() const {
- return cpu_threshold_max_;
-}
-
-int LoaderInfo::GetCpuThresholdMin() const {
- return cpu_threshold_min_;
-}
-
-int LoaderInfo::GetTimeToLive() const {
- return time_to_live_;
-}
-
-const std::vector<std::string>& LoaderInfo::GetAppTypes() const {
- return app_types_;
-}
-
-LoaderMethod LoaderInfo::GetDetectionMethod() const {
- return detection_method_;
-}
-
-void LoaderInfo::SetDetectionMethod(LoaderMethod detection_method) {
- detection_method_ = detection_method;
-}
-
-LoaderMethod LoaderInfo::GetActivationMethod() const {
- return activation_method_;
-}
-
-void LoaderInfo::SetActivationMethod(LoaderMethod activation_method) {
- activation_method_ = activation_method;
-}
-
-LoaderMethod LoaderInfo::GetDeactivationMethod() const {
- return deactivation_method_;
-}
-
-void LoaderInfo::SetDeactivationMethod(LoaderMethod deactivation_method) {
- deactivation_method_ = deactivation_method;
-}
-
-const std::string& LoaderInfo::GetHwAcc() const {
- return hw_acc_;
-}
-
-int LoaderInfo::GetOnBootTimeout() const {
- return on_boot_timeout_;
-}
-
-int LoaderInfo::GetTimeout() const {
- return timeout_;
-}
-
-void LoaderInfo::SetTimeout(int timeout) {
- timeout_ = timeout;
-}
-
-int LoaderInfo::GetSchedPriority() const {
- return sched_priority_;
-}
-
-bool LoaderInfo::ShouldCheckAppInstallation() const {
- return app_check_;
-}
-
-bool LoaderInfo::IsOnBoot() const {
- return on_boot_;
-}
-
-bool LoaderInfo::IsHydraMode() const {
- return hydra_mode_;
-}
-
-tizen_base::Bundle& LoaderInfo::GetExtra() {
- return extra_;
-}
-
-void LoaderInfo::SetAppInstalled(bool app_installed) {
- app_installed_ = app_installed;
-}
-
-bool LoaderInfo::IsAppInstalled() const {
- return app_installed_;
-}
-
-const std::vector<std::string>& LoaderInfo::GetConditionPathExists() const {
- return condition_path_exists_;
-}
-
-LoaderInfoInflator::LoaderInfoInflator() {
- parsers_ = {
- { kTagName,
- std::bind(&LoaderInfoInflator::ParseName,
- this, std::placeholders::_1) },
- { kTagExe,
- std::bind(&LoaderInfoInflator::ParseExe,
- this, std::placeholders::_1) },
- { kTagAppType,
- std::bind(&LoaderInfoInflator::ParseAppType,
- this, std::placeholders::_1) },
- { kTagDetectionMethod,
- std::bind(&LoaderInfoInflator::ParseDetectionMethod,
- this, std::placeholders::_1) },
- { kTagActivationMethod,
- std::bind(&LoaderInfoInflator::ParseActivationMethod,
- this, std::placeholders::_1) },
- { kTagDeactivationMethod,
- std::bind(&LoaderInfoInflator::ParseDeativationMethod,
- this, std::placeholders::_1) },
- { kTagTtl,
- std::bind(&LoaderInfoInflator::ParseTimeToLive,
- this, std::placeholders::_1) },
- { kTagTimeout,
- std::bind(&LoaderInfoInflator::ParseTimeout,
- this, std::placeholders::_1) },
- { kTagExtra,
- std::bind(&LoaderInfoInflator::ParseExtra,
- this, std::placeholders::_1) },
- { kTagExtraArray,
- std::bind(&LoaderInfoInflator::ParseExtraArray,
- this, std::placeholders::_1) },
- { kTagExtraArrayVal,
- std::bind(&LoaderInfoInflator::ParseExtraArrayValue,
- this, std::placeholders::_1) },
- { kTagHwAcc,
- std::bind(&LoaderInfoInflator::ParseHwAcc,
- this, std::placeholders::_1) },
- { kTagAlternativeLoader,
- std::bind(&LoaderInfoInflator::ParseAlternativeLoader,
- this, std::placeholders::_1) },
- { kTagCpuThresholdMax,
- std::bind(&LoaderInfoInflator::ParseCPUThresholdMax,
- this, std::placeholders::_1) },
- { kTagCpuThresholdMin,
- std::bind(&LoaderInfoInflator::ParseCPUThresholdMin,
- this, std::placeholders::_1) },
- { kTagOnBoot,
- std::bind(&LoaderInfoInflator::ParseOnBoot,
- this, std::placeholders::_1) },
- { kTagHydra,
- std::bind(&LoaderInfoInflator::ParseHydra,
- this, std::placeholders::_1) },
- { kTagAppCheck,
- std::bind(&LoaderInfoInflator::ParseAppCheck,
- this, std::placeholders::_1) },
- { kTagOnBootTimeout,
- std::bind(&LoaderInfoInflator::ParseOnBootTimeout,
- this, std::placeholders::_1) },
- { kTagSchedPriority,
- std::bind(&LoaderInfoInflator::ParseSchedPriority,
- this, std::placeholders::_1) },
- { kTagConditionPathExists,
- std::bind(&LoaderInfoInflator::ParseConditionPathExists,
- this, std::placeholders::_1) },
- };
-}
-
-void LoaderInfoInflator::ParseName(std::string token) {
- builder_.SetName(std::move(token));
-}
-
-void LoaderInfoInflator::ParseExe(std::string token) {
- builder_.SetExe(std::move(token));
-}
-
-void LoaderInfoInflator::ParseAppType(std::string token) {
- std::string line = std::move(token);
- do {
- auto tokens = Split(line, " |\t\r\n");
- for (auto& app_type : tokens)
- builder_.AddAppType(app_type);
- } while (std::getline(string_stream_, line));
-}
-
-void LoaderInfoInflator::ParseDetectionMethod(std::string token) {
- LoaderMethod method = LoaderMethod::None;
- std::string line = std::move(token);
- do {
- auto tokens = Split(line, " |\t\r\n");
- for (auto& token : tokens) {
- if (token == kValMethodTimeout)
- method = method | LoaderMethod::Timeout;
- else if (token == kValMethodVisibility)
- method = method | LoaderMethod::Visibility;
- else if (token == kValMethodDemand)
- method = method | LoaderMethod::Demand;
- }
- } while (std::getline(string_stream_, line));
-
- method = method | LoaderMethod::Install;
- builder_.SetDetectionMethod(method);
- _D("Detection method: %d", static_cast<int>(method));
-}
-
-void LoaderInfoInflator::ParseActivationMethod(std::string token) {
- LoaderMethod method = LoaderMethod::None;
- std::string line = std::move(token);
- do {
- auto tokens = Split(line, " |\t\r\n");
- for (auto& token : tokens) {
- if (token == kValMethodRequest)
- method = method | LoaderMethod::Request;
- else if (token == kValMethodAvailableMemory)
- method = method | LoaderMethod::AvailableMemory;
- }
- } while (std::getline(string_stream_, line));
-
- builder_.SetActivationMethod(method);
- _D("Activation method: %d", static_cast<int>(method));
-}
-
-void LoaderInfoInflator::ParseDeativationMethod(std::string token) {
- LoaderMethod method = LoaderMethod::None;
- std::string line = std::move(token);
- do {
- auto tokens = Split(line, " |\t\r\n");
- for (auto& token : tokens) {
- if (token == kValMethodTtl)
- method = method | LoaderMethod::TimeToLive;
- else if (token == kValMethodOutOfMemory)
- method = method | LoaderMethod::OutOfMemory;
- }
- } while (std::getline(string_stream_, line));
-
- builder_.SetDeactivationMethod(method);
- _D("Deactivation method: %d", static_cast<int>(method));
-}
-
-void LoaderInfoInflator::ParseTimeToLive(std::string token) {
- builder_.SetTimeToLive(std::stoi(token));
-}
-
-void LoaderInfoInflator::ParseTimeout(std::string token) {
- builder_.SetTimeout(std::stoi(token));
-}
-
-void LoaderInfoInflator::ParseExtra(std::string token) {
- std::string value;
- if (string_stream_ >> value)
- builder_.AddExtraData(std::move(token), std::move(value));
-}
-
-void LoaderInfoInflator::ParseExtraArray(std::string token) {
- if (!extra_array_key_.empty() && !extra_array_value_.empty()) {
- builder_.AddExtraArrayData(std::move(extra_array_key_),
- std::move(extra_array_value_));
- extra_array_value_.clear();
- }
-
- extra_array_key_ = std::move(token);
-}
-
-void LoaderInfoInflator::ParseExtraArrayValue(std::string token) {
- extra_array_value_.push_back(std::move(token));
-}
-
-void LoaderInfoInflator::ParseHwAcc(std::string token) {
- builder_.SetHwAcc(std::move(token));
-}
-
-void LoaderInfoInflator::ParseAlternativeLoader(std::string token) {
- builder_.AddAlternativeLoader(std::move(token));
-}
-
-void LoaderInfoInflator::ParseCPUThresholdMax(std::string token) {
- builder_.SetCPUThresholdMax(std::stoi(token));
-}
-
-void LoaderInfoInflator::ParseCPUThresholdMin(std::string token) {
- builder_.SetCPUThresholdMin(std::stoi(token));
-}
-
-void LoaderInfoInflator::ParseOnBoot(std::string token) {
- if (token == kValOff)
- builder_.SetOnBoot(false);
-}
-
-void LoaderInfoInflator::ParseHydra(std::string token) {
- if (token == kValOn)
- builder_.SetHydraMode(true);
-}
-
-void LoaderInfoInflator::ParseAppCheck(std::string token) {
- if (token == kValOff)
- builder_.SetAppCheck(false);
-}
-
-void LoaderInfoInflator::ParseOnBootTimeout(std::string token) {
- builder_.SetOnBootTimeout(std::stoi(token));
-}
-
-void LoaderInfoInflator::ParseSchedPriority(std::string token) {
- builder_.SetSchedPriority(std::min(std::max(std::stoi(token), -20), 19));
-}
-
-void LoaderInfoInflator::ParseConditionPathExists(std::string token) {
- std::string line = std::move(token);
- do {
- auto tokens = Split(line, " |\t\r\n");
- for (auto& token : tokens)
- builder_.AddConditionPathExists(token);
- } while (std::getline(string_stream_, line));
-}
-
-void LoaderInfoInflator::Parse(const std::filesystem::path& path,
- LoaderType type) {
- std::ifstream loader_file;
- loader_file.open(path);
- if (loader_file.fail())
- return;
-
- bool parsing = false;
- std::string line;
- while (std::getline(loader_file, line)) {
- string_stream_ = std::istringstream(line);
- std::string token1;
- if (!(string_stream_ >> token1))
- continue;
-
- std::string key = ToUpper(std::move(token1));
- if (key == kTagLoader) {
- if (parsing)
- Insert(type);
-
- builder_.Reset();
- parsing = true;
- continue;
- }
-
- if (parsing == false)
- continue;
-
- std::string token2;
- if (!(string_stream_ >> token2))
- continue;
-
- auto found = parsers_.find(key);
- if (found == parsers_.end())
- continue;
-
- auto& parser = found->second;
- parser(std::move(token2));
- }
-
- if (parsing)
- Insert(type);
-
- loader_file.close();
-}
-
-void LoaderInfoInflator::Insert(LoaderType type) {
- if (!extra_array_key_.empty() && !extra_array_value_.empty()) {
- builder_.AddExtraArrayData(std::move(extra_array_key_),
- std::move(extra_array_value_));
- extra_array_value_.clear();
- }
-
- if (type != LoaderType::Dynamic)
- type = MakeLoaderType();
-
- builder_.SetType(type);
- loader_infos_.emplace_back(builder_.Build());
-}
-
-std::vector<LoaderInfoPtr> LoaderInfoInflator::Inflate(
- const std::string_view path) {
- fs::path input_path(path);
- if (fs::is_directory(input_path) == false)
- return {};
-
- try {
- for (auto& entry : fs::directory_iterator(input_path)) {
- fs::path file(entry.path());
- if (file.extension() == ".loader")
- Parse(file, LoaderType::User);
- }
- } catch (const fs::filesystem_error& e) {
- _E("Exception occurs. error(%s:%d)", e.what(), e.code().value());
- }
-
- return loader_infos_;
-}
-
-LoaderInfoManager::LoaderInfoManager(std::string path): path_(std::move(path)) {
-}
-
-void LoaderInfoManager::Load() {
- if (!loader_list_.empty())
- return;
-
- LoaderInfoInflator inflator;
- loader_list_ = inflator.Inflate(path_);
-}
-
-void LoaderInfoManager::LoadFile(const std::string_view file) {
- LoaderInfoInflator inflator;
- fs::path path(path_);
- inflator.Parse(path / file, LoaderType::Dynamic);
-}
-
-void LoaderInfoManager::Unload(const std::string_view loader_name) {
- loader_list_.erase(std::remove_if(loader_list_.begin(), loader_list_.end(),
- [&](const LoaderInfoPtr& info) -> bool {
- return info->GetName() == loader_name;
- }), loader_list_.end());
-}
-
-void LoaderInfoManager::Dispose() {
- loader_list_.clear();
-}
-
-std::string LoaderInfoManager::FindLoaderPath(
- const std::string_view loader_name) {
- for (auto& info : loader_list_) {
- if (info->GetName() == loader_name)
- return info->GetExe();
- }
-
- return "";
-}
-
-LoaderInfoPtr LoaderInfoManager::FindLoaderInfo(
- const std::string_view loader_name) {
- for (auto& info : loader_list_) {
- if (info->GetName() == loader_name)
- return info;
- }
-
- return nullptr;
-}
-
-LoaderType LoaderInfoManager::FindHwType(const std::string_view app_type) {
- for (auto& info : loader_list_) {
- if (info->GetHwAcc().empty() || info->GetHwAcc() == kValOn) {
- auto found = std::find_if(
- info->GetAppTypes().begin(), info->GetAppTypes().end(),
- [&](const std::string& type) -> bool { return type == app_type; });
- if (found != info->GetAppTypes().end())
- return info->GetType();
- }
- }
-
- return LoaderType::None;
-}
-
-LoaderType LoaderInfoManager::FindSwType(const std::string_view app_type) {
- for (auto& info : loader_list_) {
- if (info->GetHwAcc().empty() || info->GetHwAcc() == kValOff) {
- auto found = std::find_if(
- info->GetAppTypes().begin(), info->GetAppTypes().end(),
- [&](const std::string& type) -> bool { return type == app_type; });
- if (found != info->GetAppTypes().end())
- return info->GetType();
- }
- }
-
- return LoaderType::None;
-}
-
-std::vector<LoaderType> LoaderInfoManager::GetAlternativeTypes(
- LoaderType type) {
- std::vector<LoaderType> result;
- for (auto& info : loader_list_) {
- if (info->GetType() == type) {
- for (auto& alt_loader : info->alternative_loaders_) {
- auto found = std::find_if(loader_list_.begin(), loader_list_.end(),
- [&](const auto& li) -> bool {
- return li->GetName() == alt_loader;
- });
- if (found == loader_list_.end())
- continue;
-
- result.push_back((*found)->GetType());
- }
- }
- }
-
- return result;
-}
-
-const std::vector<LoaderInfoPtr>& LoaderInfoManager::GetLoaderInfoList() const {
- return loader_list_;
-}
-
-} // namespace launchpad
+++ /dev/null
-/*
- * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the License);
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an AS IS BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef LAUNCHPAD_PROCESS_POOL_LOADER_INFO_HH_
-#define LAUNCHPAD_PROCESS_POOL_LOADER_INFO_HH_
-
-#include <bundle_cpp.h>
-
-#include <filesystem>
-#include <functional>
-#include <memory>
-#include <string>
-#include <string_view>
-#include <unordered_map>
-#include <vector>
-
-#include <types.hh>
-
-#include "launchpad-process-pool/util.hh"
-
-namespace launchpad {
-
-enum class LoaderMethod : int {
- None = 0x0000,
- Timeout = 0x0001,
- Visibility = 0x0002,
- Demand = 0x0004,
- Request = 0x0010,
- AvailableMemory = 0x0020,
- TimeToLive = 0x0040,
- OutOfMemory = 0x0100,
- Install = 0x0200,
-};
-
-class LoaderInfo {
- public:
- class Builder {
- public:
- Builder& SetType(LoaderType type);
- Builder& SetName(std::string name);
- Builder& SetExe(std::string exe);
- Builder& AddAppType(std::string app_type);
- Builder& SetAppTypes(std::vector<std::string> app_types);
- Builder& SetDetectionMethod(launchpad::LoaderMethod method);
- Builder& SetActivationMethod(launchpad::LoaderMethod method);
- Builder& SetDeactivationMethod(launchpad::LoaderMethod method);
- Builder& SetTimeout(int timeout);
- Builder& SetHwAcc(std::string hw_acc);
- Builder& AddAlternativeLoader(std::string alternative_loader);
- Builder& SetAlternativeLoaders(
- std::vector<std::string> alternative_loaders);
- Builder& AddExtraData(std::string key, std::string value);
- Builder& AddExtraArrayData(std::string key, std::vector<std::string> value);
- Builder& SetExtra(tizen_base::Bundle extra);
- Builder& SetCPUThresholdMax(int cpu_threshold_max);
- Builder& SetCPUThresholdMin(int cpu_threshold_min);
- Builder& SetOnBoot(bool on_boot);
- Builder& SetTimeToLive(int time_to_live);
- Builder& SetHydraMode(bool hydra_mode);
- Builder& SetAppCheck(bool app_check);
- Builder& SetOnBootTimeout(int on_boot_timeout);
- Builder& SetSchedPriority(int sched_priority);
- Builder& AddConditionPathExists(std::string path);
- Builder& SetConditionPathExists(
- std::vector<std::string> condition_path_exists);
- Builder& Reset();
-
- LoaderInfo* Build();
-
- private:
- LoaderType type_ = LoaderType::None;
- std::string name_;
- std::string exe_;
- std::vector<std::string> app_types_;
- LoaderMethod detection_method_ =
- LoaderMethod::Timeout | LoaderMethod::Visibility | LoaderMethod::Install;
- LoaderMethod activation_method_ = LoaderMethod::None;
- LoaderMethod deactivation_method_ = LoaderMethod::None;
- int timeout_ = 5000;
- std::string hw_acc_;
- std::vector<std::string> alternative_loaders_;
- tizen_base::Bundle extra_;
- int cpu_threshold_max_ = 90;
- int cpu_threshold_min_ = 40;
- bool on_boot_ = true;
- int time_to_live_ = 600;
- bool hydra_mode_ = false;
- bool app_check_ = true;
- int on_boot_timeout_ = 0;
- int sched_priority_ = 0;
- std::vector<std::string> condition_path_exists_;
- };
-
- LoaderInfo(LoaderType type, std::string name, std::string exe,
- std::vector<std::string> app_types, LoaderMethod detection_method,
- LoaderMethod activation_method, LoaderMethod deactivation_method,
- int timeout, std::string hw_acc,
- std::vector<std::string> alternative_loaders,
- tizen_base::Bundle extra, int cpu_threshold_max,
- int cpu_threshold_min, bool on_boot, int time_to_live,
- bool hydra_mode, bool app_check, int on_boot_timeout,
- int sched_priority,
- std::vector<std::string> condition_path_exists);
-
- LoaderType GetType() const;
- void SetType(LoaderType type);
- const std::string& GetName() const;
- const std::string& GetExe() const;
- void SetExe(std::string exe);
- int GetCpuThresholdMax() const;
- int GetCpuThresholdMin() const;
- int GetTimeToLive() const;
- const std::vector<std::string>& GetAppTypes() const;
- LoaderMethod GetDetectionMethod() const;
- void SetDetectionMethod(LoaderMethod detection_method);
- LoaderMethod GetActivationMethod() const;
- void SetActivationMethod(LoaderMethod activation_method);
- LoaderMethod GetDeactivationMethod() const;
- void SetDeactivationMethod(LoaderMethod deactivation_method);
- const std::string& GetHwAcc() const;
- int GetOnBootTimeout() const;
- int GetTimeout() const;
- void SetTimeout(int timeout);
- int GetSchedPriority() const;
- bool ShouldCheckAppInstallation() const;
- bool IsOnBoot() const;
- bool IsHydraMode() const;
- tizen_base::Bundle& GetExtra();
- const std::vector<std::string>& GetConditionPathExists() const;
- void SetAppInstalled(bool app_installed);
- bool IsAppInstalled() const;
-
- private:
- friend class LoaderInfoManager;
- friend class LoaderInfoInflator;
-
- private:
- LoaderType type_;
- std::string name_;
- std::string exe_;
- std::vector<std::string> app_types_;
- LoaderMethod detection_method_;
- LoaderMethod activation_method_;
- LoaderMethod deactivation_method_;
- int timeout_;
- std::string hw_acc_;
- std::vector<std::string> alternative_loaders_;
- tizen_base::Bundle extra_;
- int cpu_threshold_max_;
- int cpu_threshold_min_;
- bool on_boot_;
- int time_to_live_;
- bool hydra_mode_;
- bool app_check_;
- int on_boot_timeout_;
- int sched_priority_;
- std::vector<std::string> condition_path_exists_;
- bool app_installed_ = false;
-};
-
-using LoaderInfoPtr = std::shared_ptr<LoaderInfo>;
-
-class LoaderInfoInflator {
- public:
- LoaderInfoInflator();
-
- std::vector<LoaderInfoPtr> Inflate(const std::string_view path);
-
- void Parse(const std::filesystem::path& path, LoaderType type);
-
- private:
- void ParseName(std::string token);
- void ParseExe(std::string token);
- void ParseAppType(std::string token);
- void ParseDetectionMethod(std::string token);
- void ParseActivationMethod(std::string token);
- void ParseDeativationMethod(std::string token);
- void ParseTimeToLive(std::string token);
- void ParseTimeout(std::string token);
- void ParseExtra(std::string token);
- void ParseExtraArray(std::string token);
- void ParseExtraArrayValue(std::string token);
- void ParseHwAcc(std::string token);
- void ParseAlternativeLoader(std::string token);
- void ParseCPUThresholdMax(std::string token);
- void ParseCPUThresholdMin(std::string token);
- void ParseOnBoot(std::string token);
- void ParseHydra(std::string token);
- void ParseAppCheck(std::string token);
- void ParseOnBootTimeout(std::string token);
- void ParseSchedPriority(std::string token);
- void ParseConditionPathExists(std::string token);
- void Insert(LoaderType type);
-
- private:
- std::unordered_map<std::string, std::function<void(std::string)>> parsers_;
- std::istringstream string_stream_;
- std::string extra_array_key_;
- std::vector<std::string> extra_array_value_;
- LoaderInfo::Builder builder_;
- std::vector<std::shared_ptr<LoaderInfo>> loader_infos_;
-};
-
-class LoaderInfoManager {
- public:
- explicit LoaderInfoManager(std::string path);
- LoaderInfoManager(const LoaderInfoManager&) = delete;
- LoaderInfoManager& operator=(const LoaderInfoManager&) = delete;
-
- void Load();
- void LoadFile(const std::string_view file);
- void Unload(const std::string_view loader_name);
- void Dispose();
- LoaderType FindHwType(const std::string_view app_type);
- LoaderType FindSwType(const std::string_view app_type);
- std::string FindLoaderPath(const std::string_view loader_name);
- LoaderInfoPtr FindLoaderInfo(const std::string_view loader_name);
- std::vector<LoaderType> GetAlternativeTypes(LoaderType type);
- const std::vector<LoaderInfoPtr>& GetLoaderInfoList() const;
-
- private:
- std::string path_;
- std::vector<LoaderInfoPtr> loader_list_;
-};
-
-} // namespace launchpad
-
-#endif // LAUNCHPAD_PROCESS_POOL_LOADER_INFO_HH_
#include <algorithm>
#include <utility>
+#include <loader_executor.hh>
#include <types.hh>
#include "launchpad-process-pool/config.hh"
-#include "launchpad-process-pool/loader_executor.hh"
#include "launchpad-process-pool/loader_factory.hh"
#include "launchpad-process-pool/log_private.hh"
#include <vector>
#include <app_info.hh>
+#include <loader_info.hh>
#include <hw_acceleration_config.hh>
#include "launchpad-process-pool/app_defined_loader_info_manager.hh"
#include "launchpad-process-pool/app_labels_monitor.hh"
#include "launchpad-process-pool/hydra_loader_context.hh"
#include "launchpad-process-pool/loader_context.hh"
-#include "launchpad-process-pool/loader_info.hh"
#include "launchpad-process-pool/loader_mount.hh"
#include "launchpad-process-pool/memory_monitor.hh"
#include "launchpad-process-pool/sequencer.hh"
#include <aul_keys.hh>
#include <exception.hh>
+#include <launchpad_args.hh>
#include <parcelable.hh>
#include <util.hh>
-#include "launchpad-process-pool/launchpad_args.hh"
#include "launchpad-process-pool/log_private.hh"
namespace fs = std::filesystem;
#include <vector>
#include <app_info.hh>
+#include <executor.hh>
#include <parcel.hh>
#include <socket.hh>
-#include "launchpad-process-pool/executor.hh"
-
namespace launchpad {
class LoaderMount : public Executor::Delegator, public Executor {
+++ /dev/null
-/*
- * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the License);
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an AS IS BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "launchpad-process-pool/process_pool.hh"
-
-#include <dlog-redirect-stdout.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <linux/limits.h>
-#include <string.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-#include <filesystem>
-#include <utility>
-#include <vector>
-
-#include <util.hh>
-
-#include "launchpad-process-pool/launchpad_args.hh"
-#include "launchpad-process-pool/log_private.hh"
-
-namespace fs = std::filesystem;
-
-namespace launchpad {
-namespace {
-
-constexpr const char kProcessPool[] = "process-pool";
-
-bool IsExceptable(const std::string& path) {
- static char buf[PATH_MAX];
- ssize_t len = readlink(path.c_str(), buf, sizeof(buf));
- if (len < 0) {
- _E("readlink() is failed. errno: %d", errno);
- return false;
- }
-
- buf[len] = '\0';
- if (strstr(buf, "log") != nullptr ||
- strstr(buf, "trace") != nullptr ||
- strstr(buf, "dev") != nullptr)
- return true;
-
- return false;
-}
-
-std::vector<int> GetExceptableFds() {
- std::vector<int> fds;
- try {
- fs::path proc_path("/proc/self/fd");
- for (const auto& entry : fs::directory_iterator(proc_path)) {
- if (!isdigit(entry.path().filename().string()[0]))
- continue;
-
- int fd = std::stoi(entry.path().filename().string());
- if (dlog_is_log_fd(fd) || IsExceptable(entry.path().string()))
- fds.push_back(fd);
- }
- } catch (const fs::filesystem_error& e) {
- _E("Exception occurs. error(%s)", e.what());
- }
-
- return fds;
-}
-
-} // namespace
-
-ProcessPool::ProcessPool(std::string name, int num_processes,
- IEvent* event_listener = nullptr)
- : Executor(this),
- name_(std::move(name)),
- num_processes_(num_processes),
- event_listener_(event_listener) {
- PrepareProcess();
-}
-
-ProcessPool::~ProcessPool() {
- Dispose();
-}
-
-bool ProcessPool::IsPrepared() const {
- return !queue_.empty();
-}
-
-pid_t ProcessPool::Execute(const tizen_base::Parcel& parcel) {
- SetTimer();
- if (!IsPrepared())
- return -1;
-
- auto process = std::move(queue_.front());
- queue_.erase(queue_.begin());
- if (process->Send(parcel) < 0)
- return -1;
-
- return process->GetPid();
-}
-
-void ProcessPool::Dispose() {
- for (auto& process : queue_) {
- process->Kill();
- _D("Kill process(%d)", process->GetPid());
- }
- queue_.clear();
- UnsetTimer();
-}
-
-void ProcessPool::HandleSigchld(pid_t pid) {
- auto iter = queue_.begin();
- while (iter != queue_.end()) {
- if ((*iter)->GetPid() == pid) {
- iter = queue_.erase(iter);
- break;
- }
-
- iter++;
- }
-
- int current_process_count = static_cast<int>(queue_.size());
- if (current_process_count != num_processes_)
- SetTimer();
-}
-
-ProcessPool::Process::Process(pid_t pid, int fd)
- : pid_(pid), socket_(new Socket(fd)) {
-}
-
-pid_t ProcessPool::Process::GetPid() const {
- return pid_;
-}
-
-int ProcessPool::Process::Send(const tizen_base::Parcel& parcel) {
- _W("Send execution request. process ID: %d", pid_);
- size_t data_size = parcel.GetDataSize();
- int ret = socket_->Write(static_cast<void*>(&data_size), sizeof(data_size));
- if (ret != 0) {
- _E("Write() is failed. error(%d)", ret);
- return ret;
- }
-
- return socket_->Write(parcel.GetData(), parcel.GetDataSize());
-}
-
-void ProcessPool::Process::Kill() {
- socket_->Close();
- if (kill(pid_, SIGKILL) == -1) {
- _E("Failed to send kill signal to the process. pid(%d), errno(%d)",
- pid_, errno);
- }
-}
-
-void ProcessPool::OnExecution() {
- _D("Candidate Process");
- char** args = LaunchpadArgs::GetInst().GetArgs();
- size_t length = strlen(args[0]);
- memset(args[0], '\0', length);
- snprintf(args[0], length, "/usr/bin/%s <%s>", kProcessPool, name_.c_str());
-
- close(pipe_fd_[1]);
- std::vector<int> except_fds = GetExceptableFds();
- except_fds.push_back(pipe_fd_[0]);
- Util::CloseAllFds(except_fds);
- int ret = WaitForRequest(std::make_unique<Socket>(pipe_fd_[0]));
- exit(ret);
-}
-
-void ProcessPool::PrepareProcess() {
- int current_process_count = static_cast<int>(queue_.size());
- for (int i = current_process_count; i < num_processes_; ++i) {
- pipe_fd_[0] = -1;
- pipe_fd_[1] = -1;
- if (pipe(pipe_fd_) == -1) {
- _E("Failed to create pipe. errno(%d)", errno);
- return;
- }
-
- if (fcntl(pipe_fd_[0], F_SETPIPE_SZ, Socket::kSocketMaxBufferSize) == -1)
- _E("Failed to set pipe size. errno(%d)", errno);
-
- if (fcntl(pipe_fd_[1], F_SETPIPE_SZ, Socket::kSocketMaxBufferSize) == -1)
- _E("Failed to set pipe size. errno(%d)", errno);
-
- pid_t pid = Executor::Execute();
- if (pid == -1) {
- _E("Failed to fork process. errno(%d)", errno);
- close(pipe_fd_[0]);
- close(pipe_fd_[1]);
- return;
- }
-
- close(pipe_fd_[0]);
- queue_.push_back(std::make_shared<Process>(pid, pipe_fd_[1]));
- }
-}
-
-int ProcessPool::WaitForRequest(std::unique_ptr<Socket> socket) {
- tizen_base::Parcel parcel;
- int ret = 0;
- do {
- size_t data_size = 0;
- ret = socket->Read(static_cast<void*>(&data_size), sizeof(data_size));
- if (ret != 0) {
- _E("Failed to read from socket. error(%d)", ret);
- return -1;
- }
-
- std::vector<uint8_t> data(data_size);
- ret = socket->Read(data.data(), data.size());
- if (ret != 0) {
- _E("Failed to read from socket. error(%d)", ret);
- return -1;
- }
-
- parcel.Write(data.data(), data.size());
- } while (ret != 0);
-
- if (event_listener_ != nullptr)
- event_listener_->OnRequestReceived(&parcel);
-
- return 0;
-}
-
-void ProcessPool::SetTimer() {
- if (timer_ != 0)
- return;
-
- timer_ = g_timeout_add(1000, OnTimeout, this);
-}
-
-void ProcessPool::UnsetTimer() {
- if (timer_ != 0) {
- g_source_remove(timer_);
- timer_ = 0;
- }
-}
-
-gboolean ProcessPool::OnTimeout(gpointer user_data) {
- auto* process_pool = static_cast<ProcessPool*>(user_data);
- process_pool->PrepareProcess();
- process_pool->timer_ = 0;
- return G_SOURCE_REMOVE;
-}
-
-} // namespace launchpad
-
+++ /dev/null
-/*
- * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the License);
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an AS IS BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef LAUNCHPAD_PROCESS_POOL_PROCESS_POOL_HH_
-#define LAUNCHPAD_PROCESS_POOL_PROCESS_POOL_HH_
-
-#include <glib.h>
-#include <sys/types.h>
-
-#include <memory>
-#include <string>
-#include <vector>
-
-#include <parcel.hh>
-#include <socket.hh>
-
-#include "launchpad-process-pool/executor.hh"
-
-namespace launchpad {
-
-class ProcessPool : public Executor::Delegator,
- public Executor {
- public:
- class IEvent {
- public:
- virtual ~IEvent() = default;
- virtual void OnRequestReceived(tizen_base::Parcel* parcel) = 0;
- };
-
- explicit ProcessPool(std::string name, int num_processes,
- IEvent* event_listener);
- virtual ~ProcessPool();
-
- bool IsPrepared() const;
- pid_t Execute(const tizen_base::Parcel& parcel);
- void Dispose();
- void HandleSigchld(pid_t pid);
- void SetTimer();
-
- private:
- class Process {
- public:
- Process(pid_t pid, int fd);
-
- pid_t GetPid() const;
- int Send(const tizen_base::Parcel& parcel);
- void Kill();
-
- private:
- pid_t pid_;
- std::unique_ptr<Socket> socket_;
- };
-
- void OnExecution() override;
- void UnsetTimer();
- void PrepareProcess();
- int WaitForRequest(std::unique_ptr<Socket> socket);
- static gboolean OnTimeout(gpointer user_data);
-
- private:
- std::string name_;
- int num_processes_;
- IEvent* event_listener_;
- int pipe_fd_[2] = { -1, -1 };
- std::vector<std::shared_ptr<Process>> queue_;
- guint timer_ = 0;
-};
-
-} // namespace launchpad
-
-#endif // LAUNCHPAD_PROCESS_POOL_PROCESS_POOL_HH_
+++ /dev/null
-/*
- * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the License);
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an AS IS BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef LAUNCHPAD_PROCESS_POOL_REC_MUTEX_HH_
-#define LAUNCHPAD_PROCESS_POOL_REC_MUTEX_HH_
-
-#include <mutex>
-
-namespace launchpad {
-
-class RecMutex {
- public:
- static RecMutex& GetInst() {
- static RecMutex inst;
- return inst;
- }
-
- std::recursive_mutex& GetMutex() const {
- return mutex_;
- }
-
- private:
- RecMutex() = default;
- ~RecMutex() = default;
-
- private:
- mutable std::recursive_mutex mutex_;
-};
-
-} // namespace launchpad
-
-#endif // LAUNCHPAD_PROCESS_POOL_REC_MUTEX_HH_
#include <string>
#include <vector>
+#include <sigchld_manager.hh>
+
#include "launchpad-process-pool/dbus.hh"
#include "launchpad-process-pool/log_private.hh"
return;
_W("BEGIN");
- if (BlockSigchld() != 0)
+ if (SigchldManager::BlockSigchld() != 0)
return;
- int sfd = GetSigchldFd();
+ int sfd = SigchldManager::GetSigchldFd();
if (sfd < 0)
return;
listener_ = listener;
}
-void SignalManager::UnblockSigchld() {
- if (sigprocmask(SIG_SETMASK, &old_mask_, nullptr) < 0)
- _E("sigprocmask(SIG_SETMASK) is failed. errno(%d)", errno);
-}
-
SignalManager::~SignalManager() {
Dispose();
}
-int SignalManager::BlockSigchld() {
- sigemptyset(&mask_);
- sigaddset(&mask_, SIGCHLD);
- if (sigprocmask(SIG_BLOCK, &mask_, &old_mask_) < 0) {
- int ret = -errno;
- _E("sigprocmask(SIG_BLOCK) is failed. errno(%d)", errno);
- return ret;
- }
-
- return 0;
-}
-
-int SignalManager::GetSigchldFd() {
- int sfd = signalfd(-1, &mask_, SFD_NONBLOCK | SFD_CLOEXEC);
- if (sfd < 0) {
- sfd = -errno;
- _E("signalfd() is failed. errno(%d)", errno);
- }
-
- return sfd;
-}
-
void SignalManager::HandleSigchld(pid_t pid, int status) {
if (listener_ != nullptr)
listener_->OnSigchldReceived(pid);
void Dispose();
void SetEventListener(IEvent* listener);
- void UnblockSigchld();
private:
class SignalAction {
void Init();
void HandleSigchld(pid_t pid, int status);
- int GetSigchldFd();
- int BlockSigchld();
void OnSigchld(pid_t pid, int status) override;
void OnHydraSigchld(pid_t pid, int status) override;
private:
bool disposed_ = true;
IEvent* listener_ = nullptr;
- sigset_t mask_;
- sigset_t old_mask_;
std::unique_ptr<SigchldEvent> sigchld_event_;
std::unique_ptr<HydraSigchldEvent> hydra_sigchld_event_;
std::unique_ptr<Worker> recycle_bin_;
+++ /dev/null
-/*
- * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the License);
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an AS IS BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "launchpad-process-pool/util.hh"
-
-#include <algorithm>
-#include <cctype>
-#include <regex>
-#include <utility>
-
-namespace launchpad {
-
-std::vector<std::string> Split(const std::string& str,
- const std::string& delim) {
- const std::regex deli("[^" + delim + "]+");
- std::vector<std::string> result;
- for (auto i = std::sregex_iterator(str.begin(), str.end(), deli);
- i != std::sregex_iterator(); ++i)
- result.push_back((*i).str());
-
- return result;
-}
-
-std::string ToUpper(std::string str) {
- std::string result = std::move(str);
- std::transform(result.begin(), result.end(), result.begin(), ::toupper);
- return result;
-}
-
-} // namespace launchpad
+++ /dev/null
-/*
- * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the License);
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an AS IS BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef LAUNCHPAD_PROCESS_POOL_UTIL_HH_
-#define LAUNCHPAD_PROCESS_POOL_UTIL_HH_
-
-#include <string>
-#include <vector>
-
-namespace launchpad {
-
-template <typename E>
-E operator|(E a, E b) {
- return static_cast<E>(static_cast<int>(a) | static_cast<int>(b));
-}
-
-template <typename E>
-bool operator==(E a, int x) {
- return static_cast<int>(a) == x;
-}
-
-template <typename E>
-int operator&(int a, E b) {
- return a & static_cast<int>(b);
-}
-
-std::vector<std::string> Split(const std::string& str,
- const std::string& delim);
-
-std::string ToUpper(std::string str);
-
-} // namespace launchpad
-
-#endif // LAUNCHPAD_PROCESS_POOL_UTIL_HH_
ADD_SUBDIRECTORY(launchpad)
ADD_SUBDIRECTORY(launchpad-common)
+ADD_SUBDIRECTORY(launchpad-core)
ADD_SUBDIRECTORY(launchpad-glib)
ADD_SUBDIRECTORY(launchpad-hydra)
--- /dev/null
+AUX_SOURCE_DIRECTORY(${CMAKE_CURRENT_SOURCE_DIR}/ LAUNCHPAD_CORE_SRCS)
+
+ADD_LIBRARY(${TARGET_LAUNCHPAD_CORE} SHARED ${LAUNCHPAD_CORE_SRCS})
+
+SET_TARGET_PROPERTIES(${TARGET_LAUNCHPAD_CORE} PROPERTIES
+ SOVERSION ${MAJORVER})
+SET_TARGET_PROPERTIES(${TARGET_LAUNCHPAD_CORE} PROPERTIES
+ VERSION ${VERSION})
+
+TARGET_INCLUDE_DIRECTORIES(${TARGET_LAUNCHPAD_CORE} PUBLIC
+ ${CMAKE_CURRENT_SOURCE_DIR}
+ ${CMAKE_CURRENT_SOURCE_DIR}/../
+)
+
+APPLY_PKG_CONFIG(${TARGET_LAUNCHPAD_CORE} PUBLIC
+ BUNDLE_DEPS
+ DBUS_DEPS
+ DLOG_DEPS
+ GIO_DEPS
+ LIBTZPLATFORM_CONFIG_DEPS
+ SECURITY_MANAGER_DEPS
+ TANCHOR_DEPS
+ VCONF_DEPS
+)
+
+TARGET_LINK_LIBRARIES(${TARGET_LAUNCHPAD_CORE} PUBLIC
+${TARGET_LAUNCHPAD_COMMON} ${TARGET_LAUNCHPAD_GLIB} "-ldl")
+
+INSTALL(TARGETS ${TARGET_LAUNCHPAD_CORE} DESTINATION ${LIB_INSTALL_DIR}
+ COMPONENT RuntimeLibraries)
+INSTALL(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/
+ DESTINATION include/launchpad-core
+ FILES_MATCHING
+ PATTERN "*_private.hh" EXCLUDE
+ PATTERN "*.hh"
+)
+
+CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/pkgconfig/liblaunchpad-core.pc.in
+ ${CMAKE_CURRENT_SOURCE_DIR}/pkgconfig/liblaunchpad-core.pc @ONLY)
+INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/pkgconfig/liblaunchpad-core.pc
+ DESTINATION ${LIB_INSTALL_DIR}/pkgconfig)
--- /dev/null
+/*
+ * Copyright (c) 2023 - 2024 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-core/app_executor.hh"
+
+#include <errno.h>
+#include <libgen.h>
+#include <malloc.h>
+#include <stdio.h>
+#include <sys/prctl.h>
+#include <trust-anchor.h>
+#include <tzplatform_config.h>
+#include <unistd.h>
+
+#include <filesystem>
+#include <utility>
+
+#include <aul_keys.hh>
+#include <plugin.hh>
+#include <stdio.hh>
+#include <types.hh>
+#include <user_tracer.hh>
+#include <util.hh>
+
+#include "launchpad-core/debug.hh"
+#include "launchpad-core/log_private.hh"
+
+namespace launchpad {
+namespace fs = std::filesystem;
+namespace {
+
+void ExecuteEcho(const std::string& app_path, const std::string& error) {
+ char *argv[] = {
+ const_cast<char*>("/usr/bin/echo"),
+ const_cast<char*>("Failed to execute a file. path:"),
+ const_cast<char*>(app_path.c_str()),
+ const_cast<char*>("error:"),
+ const_cast<char*>(error.c_str()),
+ nullptr,
+ };
+
+ execv(argv[0], argv);
+}
+
+} // namespace
+
+AppExecutor::AppExecutor() : Executor(this) {
+ LauncherInfoInflator inflator;
+ launcher_infos_ = inflator.Inflate("/usr/share/aul");
+
+ prepare_funcs_.push_back(
+ std::bind(&AppExecutor::StepPluginPrepareApp, this));
+ prepare_funcs_.push_back(
+ std::bind(&AppExecutor::StepEnableExternalPackage, this));
+ prepare_funcs_.push_back(
+ std::bind(&AppExecutor::StepEnableTrustAnchor, this));
+ prepare_funcs_.push_back(
+ std::bind(&AppExecutor::StepMountResDir, this));
+ prepare_funcs_.push_back(
+ std::bind(&AppExecutor::StepChangeMountNamespace, this));
+ prepare_funcs_.push_back(
+ std::bind(&AppExecutor::StepSecurityPrepareApp, this));
+ prepare_funcs_.push_back(
+ std::bind(&AppExecutor::StepSetupStdio, this));
+ prepare_funcs_.push_back(
+ std::bind(&AppExecutor::StepSetDumpable, this));
+ prepare_funcs_.push_back(
+ std::bind(&AppExecutor::StepSetProcessName, this));
+ prepare_funcs_.push_back(
+ std::bind(&AppExecutor::StepSetEnvironments, this));
+ prepare_funcs_.push_back(
+ std::bind(&AppExecutor::StepWaitTepMount, this));
+ prepare_funcs_.push_back(
+ std::bind(&AppExecutor::StepPrepareAppSocketAndIdFile, this));
+ prepare_funcs_.push_back(
+ std::bind(&AppExecutor::StepSendStartupSignal, this));
+
+ process_pool_ = std::unique_ptr<ProcessPool>(
+ new ProcessPool("app", ProcessPool::GetNumberOfProcesses(), this));
+}
+
+pid_t AppExecutor::Execute(const AppInfo* app_info) {
+ if (process_pool_->IsPrepared()) {
+ tizen_base::Parcel parcel;
+ parcel.WriteParcelable(*app_info);
+ pid_t pid = process_pool_->Execute(parcel);
+ if (pid > 0)
+ return pid;
+ }
+
+ app_info_ = app_info;
+ return Executor::Execute();
+}
+
+void AppExecutor::DisposeCandidateProcess() {
+ process_pool_->Dispose();
+ process_pool_->SetTimer();
+}
+
+void AppExecutor::HandleSigchld(pid_t pid) {
+ process_pool_->HandleSigchld(pid);
+}
+
+void AppExecutor::OnExecution() {
+ UserTracer::Print(std::to_string(getpid()) + "|after calling fork(). " +
+ app_info_->GetAppId());
+ CheckAndPrepareDebugging();
+ Util::DeleteSocketPath(getpid(), getuid());
+
+ int ret = Prepare();
+ if (ret < 0) {
+ _E("Failed to prepare executing application(%s)",
+ app_info_->GetAppId().c_str());
+ ExecuteEcho(app_info_->GetAppPath(), std::to_string(ret));
+ exit(ret);
+ }
+
+ std::vector<std::string> argv = CreateAppArgv(app_info_->GetAppPath(),
+ app_info_->GetBundle(), app_info_->GetAppType());
+ char** app_argv = static_cast<char**>(calloc(argv.size() + 1, sizeof(char*)));
+ if (app_argv == nullptr) {
+ _E("Out of memory");
+ ExecuteEcho(app_info_->GetAppPath(), std::to_string(-ENOMEM));
+ exit(-1);
+ }
+
+ int app_argc = argv.size();
+ for (int i = 0; i < app_argc; ++i) {
+ app_argv[i] = const_cast<char*>(argv[i].c_str());
+ SECURE_LOGD("input argument %d : %s##", i, app_argv[i]);
+ }
+
+ auto lib_dir = Util::GetLibDirectory(app_info_->GetAppPath());
+ if (!lib_dir.empty())
+ setenv("LD_LIBRARY_PATH", lib_dir.c_str(), 1);
+
+ Util::CloseAllFds();
+ SECURE_LOGE("Execute application(%s)", app_argv[LoaderArg::Path]);
+ if (execv(app_argv[LoaderArg::Path], app_argv) < 0) {
+ char err_buf[1024];
+ fprintf(stderr, "Failed to execute a file. path: %s, errno: %d(%s)\n",
+ app_info_->GetAppPath().c_str(), errno,
+ strerror_r(errno, err_buf, sizeof(err_buf)));
+ ExecuteEcho(app_info_->GetAppPath(), err_buf);
+ exit(EXIT_FAILURE);
+ }
+}
+
+void AppExecutor::OnRequestReceived(tizen_base::Parcel* parcel) {
+ _W("Request received");
+ AppInfo app_info;
+ parcel->ReadParcelable(&app_info);
+ app_info_ = &app_info;
+ OnExecution();
+}
+
+int AppExecutor::Prepare() {
+ for (auto& func : prepare_funcs_) {
+ if (func() != 0)
+ return -1;
+ }
+
+ return 0;
+}
+
+int AppExecutor::StepPluginPrepareApp() {
+ return Plugin::PrepareApp(app_info_->GetAppId(), app_info_->GetBundle());
+}
+
+int AppExecutor::StepEnableExternalPackage() {
+ return Util::EnableExternalPackage(app_info_);
+}
+
+int AppExecutor::StepEnableTrustAnchor() {
+ 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() returns %d", ret);
+ return -2;
+ }
+
+ return 0;
+}
+
+int AppExecutor::StepMountResDir() {
+ int ret = Util::MountGadgetDirectories(app_info_->GetBundle());
+ if (ret != 0) {
+ _E("Failed to mount gadget resources");
+ return ret;
+ }
+
+ Util::MountLibraryDirectories(app_info_->GetBundle());
+ return Util::MountResourceDirectories(app_info_);
+}
+
+int AppExecutor::StepChangeMountNamespace() {
+ if (app_info_->GetBundle().GetType(kAulSdk) != BUNDLE_TYPE_NONE)
+ Debug::ChangeMountNamespace();
+
+ return 0;
+}
+
+int AppExecutor::StepSecurityPrepareApp() {
+ auto enabled_light_user = app_info_->GetBundle().GetString(
+ 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.empty() ? nullptr : enabled_light_user.c_str());
+ _W("security_manager_prepare_app2 -- %s", app_info_->GetAppId().c_str());
+ if (ret != SECURITY_MANAGER_SUCCESS) {
+ _E("security_manager_prepare_app2() returns %d", ret);
+ return -2;
+ }
+
+ return 0;
+}
+
+int AppExecutor::StepSetupStdio() {
+ if (app_info_->GetBundle().GetType(kAulSdk) == BUNDLE_TYPE_NONE)
+ Stdio::Setup();
+
+ return 0;
+}
+
+int AppExecutor::StepSetDumpable() {
+ prctl(PR_SET_DUMPABLE, 1);
+ return 0;
+}
+
+int AppExecutor::StepSetProcessName() {
+ fs::path file_path(app_info_->GetAppPath());
+ fs::path file_name = file_path.filename();
+ prctl(PR_SET_NAME, file_name.c_str());
+ return 0;
+}
+
+int AppExecutor::StepSetEnvironments() {
+ Util::SetEnvironments(app_info_);
+ return 0;
+}
+
+int AppExecutor::StepWaitTepMount() {
+ return Util::WaitTepMount(app_info_);
+}
+
+int AppExecutor::StepPrepareAppSocketAndIdFile() {
+ if (app_info_->GetBundle().GetType(kAulSdk) != BUNDLE_TYPE_NONE)
+ return 0;
+
+ if (Util::PrepareAppSocket() < 0)
+ return -1;
+
+ return Util::PrepareAppIdFile(app_info_);
+}
+
+int AppExecutor::StepSendStartupSignal() {
+ Util::SendCmdToAmd(AmdCmd::AppStartupSignal);
+ return 0;
+}
+
+void AppExecutor::CheckAndPrepareDebugging() {
+ auto& debug = Debug::GetInst();
+ auto& b = app_info_->GetBundle();
+ if (b.GetType(kAulSdk) != BUNDLE_TYPE_NONE)
+ debug.PrepareDebugger(b);
+
+ debug.CheckAndSetAsanActivation(app_info_->GetAppId());
+ debug.CheckWebAppDebugging(b);
+}
+
+LauncherInfoPtr AppExecutor::FindLauncherInfo(const std::string& app_type) {
+ for (auto& info : launcher_infos_) {
+ for (auto& type : info->GetAppTypes()) {
+ if (type == app_type)
+ return info;
+ }
+ }
+
+ return nullptr;
+}
+
+std::vector<std::string> AppExecutor::GetLauncherArgv(
+ const std::string& app_type) {
+ std::vector<std::string> argv;
+ auto launcher_info = FindLauncherInfo(app_type);
+ if (launcher_info == nullptr) return argv;
+
+ argv.insert(argv.end(), launcher_info->GetExe());
+ argv.insert(argv.end(), launcher_info->GetExtraArgs().begin(),
+ launcher_info->GetExtraArgs().end());
+ return argv;
+}
+
+std::vector<std::string> AppExecutor::CreateAppArgv(const std::string& app_path,
+ const tizen_base::Bundle& b, const std::string& app_type) {
+ auto& inst = launchpad::Debug::GetInst();
+ std::vector<std::string> argv = inst.GetArgv();
+ if (inst.ShouldAttach())
+ return argv;
+
+ bool debug_mode = !argv.empty() ? true : false;
+ auto launcher_argv = GetLauncherArgv(app_type);
+ if (!launcher_argv.empty())
+ argv.insert(argv.end(), launcher_argv.begin(), launcher_argv.end());
+
+ auto exported_argv = b.Export();
+ exported_argv[LoaderArg::Path] = app_path;
+ if (debug_mode &&
+ exported_argv.size() > static_cast<size_t>(LoaderArg::Type))
+ exported_argv[LoaderArg::Type] = "'" + exported_argv[LoaderArg::Type] + "'";
+
+ if (!exported_argv.empty())
+ argv.insert(argv.end(), exported_argv.begin(), exported_argv.end());
+
+ auto extra_argv = inst.GetExtraArgv();
+ if (!extra_argv.empty())
+ argv.insert(argv.end(), extra_argv.begin(), extra_argv.end());
+
+ return argv;
+}
+
+} // namespace launchpad
--- /dev/null
+/*
+ * Copyright (c) 2023 - 2024 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_CORE_APP_EXECUTOR_HH_
+#define LIB_LAUNCHPAD_CORE_APP_EXECUTOR_HH_
+
+#include <bundle_cpp.h>
+
+#include <functional>
+#include <string>
+#include <vector>
+#include <memory>
+
+#include <app_info.hh>
+
+#include "launchpad-core/executor.hh"
+#include "launchpad-core/launcher_info.hh"
+#include "launchpad-core/process_pool.hh"
+
+#undef EXPORT_API
+#define EXPORT_API __attribute__((visibility("default")))
+
+namespace launchpad {
+
+class EXPORT_API AppExecutor : public Executor::Delegator,
+ public Executor,
+ public ProcessPool::IEvent {
+ public:
+ AppExecutor();
+
+ pid_t Execute(const AppInfo* app_info);
+ void DisposeCandidateProcess();
+ void HandleSigchld(pid_t pid);
+
+ private:
+ void OnExecution() override;
+ void OnRequestReceived(tizen_base::Parcel* parcel) override;
+
+ int Prepare();
+ int StepPluginPrepareApp();
+ int StepEnableExternalPackage();
+ int StepEnableTrustAnchor();
+ int StepMountResDir();
+ int StepChangeMountNamespace();
+ int StepSecurityPrepareApp();
+ int StepSetupStdio();
+ int StepSetDumpable();
+ int StepSetProcessName();
+ int StepSetEnvironments();
+ int StepWaitTepMount();
+ int StepPrepareAppSocketAndIdFile();
+ int StepSendStartupSignal();
+
+ void CheckAndPrepareDebugging();
+ std::vector<std::string> GetLauncherArgv(const std::string& app_type);
+ std::vector<std::string> CreateAppArgv(const std::string& app_path,
+ const tizen_base::Bundle& b, const std::string& app_type);
+ LauncherInfoPtr FindLauncherInfo(const std::string& app_type);
+
+ private:
+ using PrepareFunc = std::function<int()>;
+
+ std::vector<LauncherInfoPtr> launcher_infos_;
+ std::vector<PrepareFunc> prepare_funcs_;
+ std::unique_ptr<ProcessPool> process_pool_;
+ const AppInfo* app_info_ = nullptr;
+};
+
+} // namespace launchpad
+
+#endif // LIB_LAUNCHPAD_CORE_APP_EXECUTOR_HH_
--- /dev/null
+/*
+ * Copyright (c) 2023 - 2024 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-core/debug.hh"
+
+#include <fcntl.h>
+#include <stdio.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <fstream>
+#include <utility>
+
+#include <aul_keys.hh>
+#include <exception.hh>
+
+#include "launchpad-core/log_private.hh"
+
+namespace fs = std::filesystem;
+
+namespace launchpad {
+namespace {
+
+constexpr const char kOptUsrShareAulDebugPath[] = "/opt/usr/share/aul/debug";
+constexpr const char kAsanAppList[] = ".asan_app_list";
+constexpr const char kAsanAppListPath[] =
+ "/opt/usr/share/aul/debug/.asan_app_list";
+constexpr const char kDebuggerInfoPath[] = "/usr/share/aul";
+
+std::vector<std::string> GetStringArray(const tizen_base::Bundle& b,
+ const std::string& key) {
+ std::vector<std::string> values;
+ if (b.GetType(key) & BUNDLE_TYPE_ARRAY) {
+ values = b.GetStringArray(key);
+ } else {
+ std::string value = b.GetString(key);
+ if (!value.empty())
+ values.push_back(std::move(value));
+ }
+
+ return values;
+}
+
+} // namespace
+
+Debug& Debug::GetInst() {
+ static Debug inst;
+ inst.Init();
+ return inst;
+}
+
+void Debug::Dispose() {
+ if (disposed_)
+ return;
+
+ file_monitor_.reset();
+ disposed_ = true;
+}
+
+bool Debug::Load() {
+ if (!debugger_infos_.empty())
+ return false;
+
+ DebuggerInfoInflator inflator;
+ debugger_infos_ = inflator.Inflate(kDebuggerInfoPath);
+ return true;
+}
+
+void Debug::PrepareDebugger(const tizen_base::Bundle& b) {
+ auto debugger = b.GetString(kAulSdk);
+ if (debugger.empty())
+ return;
+
+ _D("[DEBUG] Debugger: %s", debugger.c_str());
+ auto found = debugger_infos_.find(debugger);
+ if (found == debugger_infos_.end()) {
+ _W("Failed to find debugger(%s)", debugger.c_str());
+ return;
+ }
+
+ debugger_info_ = found->second;
+ if (debugger == "ASAN")
+ setenv("TIZEN_ASAN_ACTIVATION", "1", 1);
+
+ ParseAndRedirectStandardFds(b);
+ RemoveFiles(debugger_info_->GetUnlinkList());
+
+ for (const auto& extra_env : debugger_info_->GetExtraEnvList())
+ ParseAndSetEnvironment(b, extra_env);
+
+ debug_argv_ = debugger_info_->GetDefaultOptList();
+ if (!debugger_info_->GetExe().empty())
+ debug_argv_.insert(debug_argv_.begin(), debugger_info_->GetExe());
+
+ for (const auto& extra_key : debugger_info_->GetExtraKeyList())
+ ParseAndAddArgv(b, extra_key);
+
+ for (const auto& last_extra_key : debugger_info_->GetLastExtraKeyList())
+ ParseAndAddExtraArgv(b, last_extra_key);
+}
+
+void Debug::ChangeMountNamespace() {
+ auto target_pid = std::getenv("TARGET_PID");
+ if (target_pid == nullptr)
+ return;
+
+ std::string mnt_path = "/proc/" + std::string(target_pid) + "/ns/mnt";
+ int fd = open(mnt_path.c_str(), O_RDONLY);
+ if (fd < 0) {
+ _E("open() is failed. path(%s), errno(%d)", mnt_path.c_str(), errno);
+ return;
+ }
+
+ int ret = ::setns(fd, CLONE_NEWNS);
+ close(fd);
+ if (ret != 0) {
+ _E("setns() is failed. errno(%d)", errno);
+ return;
+ }
+
+ _D("setns() is successful");
+}
+
+void Debug::CheckWebAppDebugging(const tizen_base::Bundle& b) {
+ if (b.GetType(kAulDebug) != BUNDLE_TYPE_NONE)
+ setenv("TIZEN_DEBUGGING_PORT", "1", 1);
+}
+
+bool Debug::CheckAsanApp(const std::string& appid) {
+ return asan_app_map_.find(appid) != asan_app_map_.end();
+}
+
+void Debug::CheckAndSetAsanActivation(const std::string& appid) {
+ if (CheckAsanApp(appid)) {
+ _W("Set TIZEN_ASAN_ACTIVATION. appid: %s", appid.c_str());
+ setenv("TIZEN_ASAN_ACTIVATION", "1", 1);
+ }
+}
+
+std::vector<std::string> Debug::GetExtraArgv() const {
+ return extra_argv_;
+}
+
+std::vector<std::string> Debug::GetArgv() const {
+ return debug_argv_;
+}
+
+bool Debug::ShouldAttach() const {
+ if (!debugger_info_)
+ return false;
+
+ return debugger_info_->GetAttachInfo() == "true";
+}
+
+Debug::~Debug() {
+ Dispose();
+}
+
+void Debug::Init() {
+ if (!disposed_)
+ return;
+
+ try {
+ file_monitor_ = std::make_unique<FileMonitor>(
+ kOptUsrShareAulDebugPath, this);
+ } catch (const Exception& e) {
+ _E("Exception occurs. error: %s", e.what());
+ return;
+ }
+
+ if (fs::exists(kAsanAppListPath))
+ LoadAsanAppList();
+
+ disposed_ = false;
+}
+
+void Debug::RemoveFiles(const std::vector<std::string>& files) {
+ for (const auto& file : files) {
+ if (fs::exists(file)) {
+ _D("[DEBUG] file: %s", file.c_str());
+ fs::remove(file);
+ }
+ }
+}
+
+void Debug::ParseAndSetEnvironment(const tizen_base::Bundle& b,
+ const std::string& key) {
+ _D("[DEBUG] key: %s", key.c_str());
+ std::vector<std::string> values = GetStringArray(b, key);
+ if (values.empty())
+ return;
+
+ std::string env;
+ for (const auto& value : values) {
+ if (!env.empty())
+ env += ",";
+
+ env += value;
+ }
+
+ const_cast<tizen_base::Bundle&>(b).Delete(key);
+ _D("[DEBUG] value: %s", env.c_str());
+ setenv(key.c_str(), env.c_str(), 1);
+}
+
+void Debug::ParseAndAddArgv(const tizen_base::Bundle& b,
+ const std::string& key) {
+ _D("[DEBUG] key: %s", key.c_str());
+ std::vector<std::string> values = GetStringArray(b, key);
+ if (values.empty())
+ return;
+
+ for (const auto& arg : values) {
+ debug_argv_.push_back(arg);
+ if (key == "__DLP_ATTACH_ARG__" && isdigit(arg[0])) {
+ _D("[DEBUG] TARGET_PID: %s", arg.c_str());
+ setenv("TARGET_PID", arg.c_str(), 1);
+ }
+ }
+
+ const_cast<tizen_base::Bundle&>(b).Delete(key);
+}
+
+void Debug::ParseAndAddExtraArgv(const tizen_base::Bundle& b,
+ const std::string& key) {
+ _D("[DEBUG] key: %s", key.c_str());
+ std::vector<std::string> values = GetStringArray(b, key);
+ if (values.empty()) return;
+
+ for (const auto& arg : values)
+ extra_argv_.push_back(arg);
+
+ const_cast<tizen_base::Bundle&>(b).Delete(key);
+}
+
+void Debug::ParseAndRedirectStandardFds(const tizen_base::Bundle& b) {
+ pid_t caller_pid = GetCallerPid(b);
+ if (caller_pid < 0)
+ return;
+
+ // stdin
+ std::string path = "/proc/" + std::to_string(caller_pid) + "/fd/";
+ int fd = open((path + std::to_string(STDIN_FILENO)).c_str(), O_RDONLY);
+ if (fd < 0) {
+ _E("Failed to open STDIN file descriptor. errno(%d)", errno);
+ return;
+ }
+
+ dup2(fd, STDIN_FILENO);
+ close(fd);
+
+ // stdout
+ fd = open((path + std::to_string(STDOUT_FILENO)).c_str(), O_WRONLY);
+ if (fd < 0) {
+ _E("Failed to open STDOUT file descriptor. errno(%d)", errno);
+ return;
+ }
+
+ dup2(fd, STDOUT_FILENO);
+ close(fd);
+
+ // stdout
+ fd = open((path + std::to_string(STDERR_FILENO)).c_str(), O_WRONLY);
+ if (fd < 0) {
+ _E("Failed to open STDERR file descriptor. errno(%d)", errno);
+ return;
+ }
+
+ dup2(fd, STDERR_FILENO);
+ close(fd);
+}
+
+pid_t Debug::GetCallerPid(const tizen_base::Bundle& b) {
+ auto pid_str = b.GetString(kAulOrgCallerPid);
+ if (pid_str.empty())
+ pid_str = b.GetString(kAulCallerPid);
+
+ if (pid_str.empty())
+ return -1;
+
+ return std::stoi(pid_str);
+}
+
+void Debug::LoadAsanAppList() {
+ asan_app_map_.clear();
+ std::ifstream if_stream;
+ if_stream.open(kAsanAppListPath);
+ if (!if_stream.is_open()) {
+ _E("Failed to open %s", kAsanAppListPath);
+ return;
+ }
+
+ std::string appid;
+ while (!if_stream.eof()) {
+ if_stream >> appid;
+ asan_app_map_.insert(std::move(appid));
+ }
+}
+
+void Debug::OnFileChanged(const std::string_view name,
+ FileMonitor::Event event) {
+ if (name != kAsanAppList)
+ return;
+
+ _W("%s was changed. event(%d)", kAsanAppList, static_cast<int>(event));
+ LoadAsanAppList();
+}
+
+} // namespace launchpad
--- /dev/null
+/*
+ * Copyright (c) 2023 - 2024 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_CORE_DEBUG_HH_
+#define LIB_LAUNCHPAD_CORE_DEBUG_HH_
+
+#include <bundle_cpp.h>
+
+#include <list>
+#include <memory>
+#include <string>
+#include <unordered_map>
+#include <unordered_set>
+#include <vector>
+
+#include <debugger_info.hh>
+#include <file_monitor.hh>
+
+#undef EXPORT_API
+#define EXPORT_API __attribute__((visibility("default")))
+
+namespace launchpad {
+
+class EXPORT_API Debug : public FileMonitor::IEvent {
+ public:
+ Debug(const Debug&) = delete;
+ Debug& operator = (const Debug&) = delete;
+ Debug(Debug&&) = delete;
+ Debug& operator = (Debug&&) = delete;
+
+ static Debug& GetInst();
+ void Init();
+ void Dispose();
+ bool Load();
+ void PrepareDebugger(const tizen_base::Bundle& b);
+ std::vector<std::string> GetExtraArgv() const;
+ std::vector<std::string> GetArgv() const;
+ bool ShouldAttach() const;
+ bool CheckAsanApp(const std::string& appid);
+ void CheckAndSetAsanActivation(const std::string& appid);
+
+ static void ChangeMountNamespace();
+ static void CheckWebAppDebugging(const tizen_base::Bundle& b);
+
+ private:
+ Debug() = default;
+ ~Debug();
+
+ void RemoveFiles(const std::vector<std::string>& files);
+ void ParseAndSetEnvironment(
+ const tizen_base::Bundle& b, const std::string& key);
+ void ParseAndAddArgv(const tizen_base::Bundle& b, const std::string& key);
+ void ParseAndAddExtraArgv(const tizen_base::Bundle& b,
+ const std::string& key);
+ void ParseAndRedirectStandardFds(const tizen_base::Bundle& b);
+ pid_t GetCallerPid(const tizen_base::Bundle& b);
+
+ void LoadAsanAppList();
+ void OnFileChanged(const std::string_view name,
+ FileMonitor::Event event) override;
+
+ private:
+ bool disposed_ = true;
+ DebuggerInfoPtr debugger_info_;
+ std::unordered_map<std::string, DebuggerInfoPtr> debugger_infos_;
+ std::vector<std::string> debug_argv_;
+ std::vector<std::string> extra_argv_;
+ std::unordered_set<std::string> asan_app_map_;
+ std::unique_ptr<launchpad::FileMonitor> file_monitor_;
+};
+
+} // namespace launchpad
+
+#endif // LIB_LAUNCHPAD_CORE_DEBUG_HH_
--- /dev/null
+/*
+ * Copyright (c) 2023 - 2024 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-core/debugger_info.hh"
+
+#include <dirent.h>
+#include <limits.h>
+#include <malloc.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <algorithm>
+#include <fstream>
+#include <sstream>
+#include <utility>
+
+#include <util.hh>
+
+#include "launchpad-core/log_private.hh"
+
+namespace launchpad {
+namespace {
+
+constexpr const char kTagDebugger[] = "[DEBUGGER]";
+constexpr const char kTagName[] = "NAME";
+constexpr const char kTagExe[] = "EXE";
+constexpr const char kTagAppType[] = "APP_TYPE";
+constexpr const char kTagExtraKey[] = "EXTRA_KEY";
+constexpr const char kTagExtraEnv[] = "EXTRA_ENV";
+constexpr const char kTagUnlink[] = "UNLINK";
+constexpr const char kTagAttach[] = "ATTACH";
+constexpr const char kTagLastExtraKey[] = "LAST_EXTRA_KEY";
+constexpr const char kTagDefaultOpt[] = "DEFAULT_OPT";
+
+} // namespace
+
+namespace fs = std::filesystem;
+
+DebuggerInfo::Builder& DebuggerInfo::Builder::SetName(std::string name) {
+ name_ = std::move(name);
+ return *this;
+}
+
+DebuggerInfo::Builder& DebuggerInfo::Builder::SetExe(std::string exe) {
+ exe_ = std::move(exe);
+ return *this;
+}
+
+DebuggerInfo::Builder& DebuggerInfo::Builder::AddAppType(std::string app_type) {
+ app_types_.push_back(std::move(app_type));
+ return *this;
+}
+
+DebuggerInfo::Builder& DebuggerInfo::Builder::AddExtraKey(
+ std::string extra_key) {
+ extra_keys_.push_back(std::move(extra_key));
+ return *this;
+}
+DebuggerInfo::Builder& DebuggerInfo::Builder::AddExtraEnv(
+ std::string extra_env) {
+ extra_envs_.push_back(std::move(extra_env));
+ return *this;
+}
+
+DebuggerInfo::Builder& DebuggerInfo::Builder::AddFileToDelete(
+ std::string file) {
+ delete_files_.push_back(std::move(file));
+ return *this;
+}
+
+DebuggerInfo::Builder& DebuggerInfo::Builder::SetAttach(std::string attach) {
+ attach_ = std::move(attach);
+ return *this;
+}
+
+DebuggerInfo::Builder& DebuggerInfo::Builder::AddLastExtraKey(
+ std::string last_extra_key) {
+ last_extra_keys_.push_back(std::move(last_extra_key));
+ return *this;
+}
+
+DebuggerInfo::Builder& DebuggerInfo::Builder::AddDefaultOpt(
+ std::string default_opt) {
+ default_opts_.push_back(std::move(default_opt));
+ return *this;
+}
+
+DebuggerInfo::Builder& DebuggerInfo::Builder::Reset() {
+ name_.clear();
+ exe_.clear();
+ app_types_.clear();
+ extra_keys_.clear();
+ extra_envs_.clear();
+ delete_files_.clear();
+ attach_.clear();
+ last_extra_keys_.clear();
+ default_opts_.clear();
+ return *this;
+}
+
+DebuggerInfo* DebuggerInfo::Builder::Build() {
+ return new DebuggerInfo(std::move(name_), std::move(exe_),
+ std::move(app_types_), std::move(extra_keys_), std::move(extra_envs_),
+ std::move(delete_files_), std::move(attach_),
+ std::move(last_extra_keys_), std::move(default_opts_));
+}
+
+DebuggerInfo::DebuggerInfo(std::string name, std::string exe,
+ std::vector<std::string> app_types,
+ std::vector<std::string> extra_keys,
+ std::vector<std::string> extra_envs,
+ std::vector<std::string> delete_files,
+ std::string attach,
+ std::vector<std::string> last_extra_keys,
+ std::vector<std::string> default_opts)
+ : name_(std::move(name)),
+ exe_(std::move(exe)),
+ app_types_(std::move(app_types)),
+ extra_keys_(std::move(extra_keys)),
+ extra_envs_(std::move(extra_envs)),
+ delete_files_(std::move(delete_files)),
+ attach_(std::move(attach)),
+ last_extra_keys_(std::move(last_extra_keys)),
+ default_opts_(std::move(default_opts)) {}
+
+const std::string& DebuggerInfo::GetName() const {
+ return name_;
+}
+
+const std::string& DebuggerInfo::GetExe() const {
+ return exe_;
+}
+
+const std::vector<std::string>& DebuggerInfo::GetAppTypes() const {
+ return app_types_;
+}
+
+const std::vector<std::string>& DebuggerInfo::GetExtraKeyList() const {
+ return extra_keys_;
+}
+
+const std::vector<std::string>& DebuggerInfo::GetExtraEnvList() const {
+ return extra_envs_;
+}
+
+const std::vector<std::string>& DebuggerInfo::GetUnlinkList() const {
+ return delete_files_;
+}
+
+const std::string& DebuggerInfo::GetAttachInfo() const {
+ return attach_;
+}
+
+const std::vector<std::string>& DebuggerInfo::GetLastExtraKeyList() const {
+ return last_extra_keys_;
+}
+
+const std::vector<std::string>& DebuggerInfo::GetDefaultOptList() const {
+ return default_opts_;
+}
+
+DebuggerInfoInflator::DebuggerInfoInflator() {
+ parsers_ = {
+ { kTagName,
+ std::bind(&DebuggerInfoInflator::ParseName,
+ this, std::placeholders::_1) },
+ { kTagExe,
+ std::bind(&DebuggerInfoInflator::ParseExe,
+ this, std::placeholders::_1) },
+ { kTagAppType,
+ std::bind(&DebuggerInfoInflator::ParseAppType,
+ this, std::placeholders::_1) },
+ { kTagExtraKey,
+ std::bind(&DebuggerInfoInflator::ParseExtraKey,
+ this, std::placeholders::_1) },
+ { kTagExtraEnv,
+ std::bind(&DebuggerInfoInflator::ParseExtraEnv,
+ this, std::placeholders::_1) },
+ { kTagUnlink,
+ std::bind(&DebuggerInfoInflator::ParseUnlink,
+ this, std::placeholders::_1) },
+ { kTagAttach,
+ std::bind(&DebuggerInfoInflator::ParseAttach,
+ this, std::placeholders::_1) },
+ { kTagLastExtraKey,
+ std::bind(&DebuggerInfoInflator::ParseLastExtraKey,
+ this, std::placeholders::_1) },
+ { kTagDefaultOpt,
+ std::bind(&DebuggerInfoInflator::ParseDefaultOpt,
+ this, std::placeholders::_1) },
+ };
+}
+
+std::unordered_map<std::string, DebuggerInfoPtr>
+DebuggerInfoInflator::Inflate(const std::string_view path) {
+ fs::path input_path(path);
+ if (fs::is_directory(input_path) == false)
+ return debugger_infos_;
+
+ try {
+ for (auto& entry : fs::directory_iterator(input_path)) {
+ fs::path file(entry.path());
+ if (file.extension() == ".debugger")
+ Parse(file);
+ }
+ } catch (const fs::filesystem_error& e) {
+ _E("Exception occurs. error(%s:%d)", e.what(), e.code().value());
+ }
+
+ return debugger_infos_;
+}
+
+void DebuggerInfoInflator::ParseName(std::string token) {
+ builder_.SetName(std::move(token));
+}
+
+void DebuggerInfoInflator::ParseExe(std::string token) {
+ builder_.SetExe(std::move(token));
+}
+
+void DebuggerInfoInflator::ParseAppType(std::string token) {
+ std::string line = std::move(token);
+ do {
+ auto tokens = Util::Split(line, " |\t\r\n");
+ for (auto& app_type : tokens) {
+ _D("app-type: %s", app_type.c_str());
+ builder_.AddAppType(app_type);
+ }
+ } while (std::getline(string_stream_, line));
+}
+
+void DebuggerInfoInflator::ParseExtraKey(std::string token) {
+ builder_.AddExtraKey(std::move(token));
+}
+
+void DebuggerInfoInflator::ParseExtraEnv(std::string token) {
+ builder_.AddExtraEnv(std::move(token));
+}
+
+void DebuggerInfoInflator::ParseUnlink(std::string token) {
+ builder_.AddFileToDelete(std::move(token));
+}
+
+void DebuggerInfoInflator::ParseAttach(std::string token) {
+ builder_.SetAttach(std::move(token));
+}
+
+void DebuggerInfoInflator::ParseLastExtraKey(std::string token) {
+ builder_.AddLastExtraKey(std::move(token));
+}
+
+void DebuggerInfoInflator::ParseDefaultOpt(std::string token) {
+ builder_.AddDefaultOpt(std::move(token));
+}
+
+void DebuggerInfoInflator::Parse(const fs::path& path) {
+ std::ifstream input_file(path);
+ if (!input_file.is_open())
+ return;
+
+ bool parsing = false;
+ std::string input;
+ while (std::getline(input_file, input)) {
+ string_stream_ = std::istringstream(input);
+ std::string token1;
+ if (!(string_stream_ >> token1))
+ continue;
+
+ std::string key = Util::ToUpper(std::move(token1));
+ if (key == kTagDebugger) {
+ if (parsing)
+ InsertDebuggerInfo(std::shared_ptr<DebuggerInfo>(builder_.Build()));
+
+ builder_.Reset();
+ parsing = true;
+ continue;
+ }
+
+ if (parsing == false)
+ continue;
+
+ std::string token2;
+ if (!(string_stream_ >> token2))
+ continue;
+
+ auto found = parsers_.find(key);
+ if (found == parsers_.end())
+ continue;
+
+ auto& parser = found->second;
+ parser(std::move(token2));
+ }
+
+ if (parsing)
+ InsertDebuggerInfo(std::shared_ptr<DebuggerInfo>(builder_.Build()));
+
+ input_file.close();
+}
+
+void DebuggerInfoInflator::InsertDebuggerInfo(DebuggerInfoPtr info) {
+ if (debugger_infos_.find(info->name_) != debugger_infos_.end())
+ return;
+
+ _D("name: %s, exe: %s", info->name_.c_str(), info->exe_.c_str());
+ std::string name = info->name_;
+ debugger_infos_[std::move(name)] = std::move(info);
+}
+
+} // namespace launchpad
--- /dev/null
+/*
+ * Copyright (c) 2023 - 2024 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_CORE_DEBUGGER_INFO_HH_
+#define LIB_LAUNCHPAD_CORE_DEBUGGER_INFO_HH_
+
+#include <filesystem>
+#include <functional>
+#include <memory>
+#include <string>
+#include <string_view>
+#include <unordered_map>
+#include <vector>
+
+namespace launchpad {
+
+class DebuggerInfo {
+ public:
+ class Builder {
+ public:
+ Builder& SetName(std::string name);
+ Builder& SetExe(std::string exe);
+ Builder& AddAppType(std::string app_type);
+ Builder& AddExtraKey(std::string extra_key);
+ Builder& AddExtraEnv(std::string extra_env);
+ Builder& AddFileToDelete(std::string file);
+ Builder& SetAttach(std::string attach);
+ Builder& AddLastExtraKey(std::string last_extra_key);
+ Builder& AddDefaultOpt(std::string default_opt);
+ Builder& Reset();
+
+ DebuggerInfo* Build();
+
+ private:
+ std::string name_;
+ std::string exe_;
+ std::vector<std::string> app_types_;
+ std::vector<std::string> extra_keys_;
+ std::vector<std::string> extra_envs_;
+ std::vector<std::string> delete_files_;
+ std::string attach_;
+ std::vector<std::string> last_extra_keys_;
+ std::vector<std::string> default_opts_;
+ };
+
+ DebuggerInfo(std::string name, std::string exe,
+ std::vector<std::string> app_types,
+ std::vector<std::string> extra_keys,
+ std::vector<std::string> extra_envs,
+ std::vector<std::string> delete_files,
+ std::string attach,
+ std::vector<std::string> last_extra_keys,
+ std::vector<std::string> default_opts);
+
+ const std::string& GetName() const;
+ const std::string& GetExe() const;
+ const std::vector<std::string>& GetAppTypes() const;
+ const std::vector<std::string>& GetExtraKeyList() const;
+ const std::vector<std::string>& GetExtraEnvList() const;
+ const std::vector<std::string>& GetUnlinkList() const;
+ const std::string& GetAttachInfo() const;
+ const std::vector<std::string>& GetLastExtraKeyList() const;
+ const std::vector<std::string>& GetDefaultOptList() const;
+
+ private:
+ std::string name_;
+ std::string exe_;
+ std::vector<std::string> app_types_;
+ std::vector<std::string> extra_keys_;
+ std::vector<std::string> extra_envs_;
+ std::vector<std::string> delete_files_;
+ std::string attach_;
+ std::vector<std::string> last_extra_keys_;
+ std::vector<std::string> default_opts_;
+
+ friend class DebuggerInfoInflator;
+};
+
+using DebuggerInfoPtr = std::shared_ptr<DebuggerInfo>;
+
+class DebuggerInfoInflator {
+ public:
+ DebuggerInfoInflator();
+
+ std::unordered_map<std::string, DebuggerInfoPtr> Inflate(
+ const std::string_view path);
+
+ private:
+ void ParseName(std::string token);
+ void ParseExe(std::string token);
+ void ParseAppType(std::string token);
+ void ParseExtraKey(std::string token);
+ void ParseExtraEnv(std::string token);
+ void ParseUnlink(std::string token);
+ void ParseAttach(std::string token);
+ void ParseLastExtraKey(std::string token);
+ void ParseDefaultOpt(std::string token);
+ void Parse(const std::filesystem::path& path);
+
+ void InsertDebuggerInfo(DebuggerInfoPtr info);
+
+ private:
+ std::unordered_map<std::string, std::function<void(std::string)>> parsers_;
+ std::unordered_map<std::string, DebuggerInfoPtr> debugger_infos_;
+ std::istringstream string_stream_;
+ DebuggerInfo::Builder builder_;
+};
+
+} // namespace launchpad
+
+#endif // LIB_LAUNCHPAD_CORE_DEBUGGER_INFO_HH_
--- /dev/null
+/*
+ * Copyright (c) 2023 - 2024 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-core/executor.hh"
+
+#include <stdlib.h>
+#include <unistd.h>
+
+#include <sched_priority.hh>
+
+#include "launchpad-core/log_private.hh"
+#include "launchpad-core/sigchld_manager.hh"
+
+namespace launchpad {
+
+Executor::Executor(Executor::Delegator* delegator) : delegator_(delegator) {}
+
+pid_t Executor::Execute(int priority) {
+ pid_t pid = fork();
+ if (pid == -1) {
+ _E("Failed to create child process. errno(%d)", errno);
+ return -1;
+ }
+
+ if (pid == 0) {
+ setsid();
+ if (priority != 0)
+ SchedPriority::Set(priority);
+
+ SigchldManager::UnblockSigchld();
+
+ _W("security_manager_prepare_app_candidate ++");
+ int ret = security_manager_prepare_app_candidate();
+ _W("security_manager_prepare_app_candidate --");
+ if (ret != SECURITY_MANAGER_SUCCESS) {
+ _E("Failed to prepare app candidate process. error(%d)", ret);
+ exit(1);
+ }
+
+ delegator_->OnExecution();
+ }
+
+ return pid;
+}
+
+} // namespace launchpad
--- /dev/null
+/*
+ * Copyright (c) 2023 - 2024 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_CORE_EXECUTOR_HH_
+#define LIB_LAUNCHPAD_CORE_EXECUTOR_HH_
+
+#include <security-manager.h>
+#include <sys/types.h>
+
+#undef EXPORT_API
+#define EXPORT_API __attribute__((visibility("default")))
+
+namespace launchpad {
+
+class EXPORT_API Executor {
+ public:
+ class EXPORT_API Delegator {
+ public:
+ virtual ~Delegator() = default;
+ virtual void OnExecution() = 0;
+ };
+
+ explicit Executor(Delegator* delegator);
+ virtual ~Executor() = default;
+
+ pid_t Execute(int priority = 0);
+
+ private:
+ Delegator* delegator_;
+};
+
+} // namespace launchpad
+
+#endif // LIB_LAUNCHPAD_CORE_EXECUTOR_HH_
--- /dev/null
+/*
+ * Copyright (c) 2023 - 2024 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-core/file_monitor.hh"
+
+#include <errno.h>
+
+#include <exception.hh>
+
+#include "launchpad-core/log_private.hh"
+
+namespace launchpad {
+
+namespace fs = std::filesystem;
+
+void FileMonitor::OnIOEventReceived(int fd, int condition) {
+ alignas(struct inotify_event) char buf[4096];
+ const struct inotify_event* event;
+ ssize_t len;
+ while ((len = read(fd, buf, sizeof(buf))) > 0) {
+ for (const char* ptr = buf; ptr < buf + len;
+ ptr += sizeof(struct inotify_event) + event->len) {
+ event = reinterpret_cast<const struct inotify_event*>(ptr);
+ const char* nptr = ptr + sizeof(struct inotify_event) + event->len;
+ if (nptr > buf + len)
+ break;
+
+ if (event->len) {
+ if (listener_) {
+ if (event->mask & IN_CREATE)
+ listener_->OnFileChanged(event->name, Event::Created);
+ else if (event->mask & IN_MODIFY)
+ listener_->OnFileChanged(event->name, Event::Modified);
+ else if (event->mask & IN_DELETE)
+ listener_->OnFileChanged(event->name, Event::Deleted);
+ }
+ }
+ }
+ }
+}
+
+FileMonitor::FileMonitor(const std::string_view path,
+ FileMonitor::IEvent* listener)
+ : path_(path), listener_(listener) {
+ if (!fs::exists(path_)) {
+ try {
+ if (!fs::create_directories(path_)) {
+ _E("Failed to create directory. %s", path_.c_str());
+ THROW(-EIO);
+ }
+ } catch (const std::exception& e) {
+ _E("Exception has been occurred: %s", e.what());
+ THROW(-EIO);
+ }
+ }
+
+ int fd = inotify_init1(IN_NONBLOCK | IN_CLOEXEC);
+ if (fd < 0) {
+ int error_code = -errno;
+ _E("inotify_init1() is failed. errno: %d", errno);
+ THROW(error_code);
+ }
+
+ int wd = inotify_add_watch(fd, path_.c_str(),
+ IN_CREATE | IN_MODIFY | IN_DELETE);
+ if (wd < 0) {
+ int error_code = -errno;
+ _E("inotify_add_watch() is failed. errno: %d", errno);
+ close(fd);
+ THROW(error_code);
+ }
+
+ channel_ = std::make_unique<IOChannel>(fd, G_IO_IN, this);
+ wd_ = wd;
+ fd_ = fd;
+}
+
+FileMonitor::~FileMonitor() {
+ channel_.reset();
+
+ if (wd_ > 0)
+ inotify_rm_watch(fd_, wd_);
+
+ if (fd_ > 0)
+ close(fd_);
+}
+
+} // namespace launchpad
--- /dev/null
+/*
+ * Copyright (c) 2023 - 2024 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_CORE_FILE_MONITOR_HH_
+#define LIB_LAUNCHPAD_CORE_FILE_MONITOR_HH_
+
+#include <sys/inotify.h>
+
+#include <filesystem>
+#include <memory>
+#include <string_view>
+
+#include <io_channel.hh>
+
+#undef EXPORT_API
+#define EXPORT_API __attribute__((visibility("default")))
+
+namespace launchpad {
+
+class EXPORT_API FileMonitor : public IOChannel::IEvent {
+ public:
+ enum class Event : int {
+ Created = IN_CREATE,
+ Modified = IN_MODIFY,
+ Deleted = IN_DELETE,
+ };
+
+ class IEvent {
+ public:
+ virtual ~IEvent() = default;
+ virtual void OnFileChanged(const std::string_view name, Event event) = 0;
+ };
+
+ FileMonitor(const std::string_view path, IEvent *listener);
+ virtual ~FileMonitor();
+
+ FileMonitor(const FileMonitor &) = delete;
+ FileMonitor &operator=(const FileMonitor &) = delete;
+
+ private:
+ void OnIOEventReceived(int fd, int condition) override;
+
+ private:
+ std::filesystem::path path_;
+ IEvent *listener_;
+ int fd_ = 0;
+ int wd_ = 0;
+ std::unique_ptr<IOChannel> channel_;
+};
+
+} // namespace launchpad
+
+#endif // LIB_LAUNCHPAD_CORE_FILE_MONITOR_HH_
--- /dev/null
+/*
+ * Copyright (c) 2023 - 2024 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-core/launcher_info.hh"
+
+#include <algorithm>
+#include <fstream>
+#include <sstream>
+#include <utility>
+
+#include <util.hh>
+
+#include "launchpad-core/log_private.hh"
+
+namespace launchpad {
+namespace {
+
+constexpr const char kTagLauncher[] = "[LAUNCHER]";
+constexpr const char kTagName[] = "NAME";
+constexpr const char kTagExe[] = "EXE";
+constexpr const char kTagAppType[] = "APP_TYPE";
+constexpr const char kTagExtraArg[] = "EXTRA_ARG";
+
+} // namespace
+
+namespace fs = std::filesystem;
+
+LauncherInfo::Builder& LauncherInfo::Builder::SetName(std::string name) {
+ name_ = std::move(name);
+ return *this;
+}
+
+LauncherInfo::Builder& LauncherInfo::Builder::SetExe(std::string exe) {
+ exe_ = std::move(exe);
+ return *this;
+}
+
+LauncherInfo::Builder& LauncherInfo::Builder::AddAppType(std::string app_type) {
+ app_types_.push_back(std::move(app_type));
+ return *this;
+}
+
+LauncherInfo::Builder& LauncherInfo::Builder::AddExtraArg(
+ std::string extra_arg) {
+ extra_args_.push_back(std::move(extra_arg));
+ return *this;
+}
+
+LauncherInfo::Builder& LauncherInfo::Builder::Reset() {
+ name_.clear();
+ exe_.clear();
+ app_types_.clear();
+ extra_args_.clear();
+ return *this;
+}
+
+LauncherInfo* LauncherInfo::Builder::Build() {
+ return new LauncherInfo(std::move(name_), std::move(exe_),
+ std::move(app_types_), std::move(extra_args_));
+}
+
+LauncherInfo::LauncherInfo(std::string name, std::string exe,
+ std::vector<std::string> app_types, std::vector<std::string> extra_args)
+ : name_(std::move(name)),
+ exe_(std::move(exe)),
+ app_types_(std::move(app_types)),
+ extra_args_(std::move(extra_args)) {
+}
+
+const std::string& LauncherInfo::GetName() const {
+ return name_;
+}
+
+const std::string& LauncherInfo::GetExe() const {
+ return exe_;
+}
+
+const std::vector<std::string>& LauncherInfo::GetAppTypes() const {
+ return app_types_;
+}
+
+const std::vector<std::string>& LauncherInfo::GetExtraArgs() const {
+ return extra_args_;
+}
+
+LauncherInfoInflator::LauncherInfoInflator() {
+ parsers_ = {
+ { kTagName,
+ std::bind(&LauncherInfoInflator::ParseName,
+ this, std::placeholders::_1) },
+ { kTagExe,
+ std::bind(&LauncherInfoInflator::ParseExe,
+ this, std::placeholders::_1) },
+ { kTagAppType,
+ std::bind(&LauncherInfoInflator::ParseAppType,
+ this, std::placeholders::_1) },
+ { kTagExtraArg,
+ std::bind(&LauncherInfoInflator::ParseExtraArg,
+ this, std::placeholders::_1) },
+ };
+}
+
+void LauncherInfoInflator::ParseName(std::string token) {
+ builder_.SetName(std::move(token));
+}
+
+void LauncherInfoInflator::ParseExe(std::string token) {
+ builder_.SetExe(std::move(token));
+}
+
+void LauncherInfoInflator::ParseAppType(std::string token) {
+ std::string line = std::move(token);
+ do {
+ auto tokens = Util::Split(line, " |\t\r\n");
+ for (auto& app_type : tokens)
+ builder_.AddAppType(app_type);
+ } while (std::getline(string_stream_, line));
+}
+
+void LauncherInfoInflator::ParseExtraArg(std::string token) {
+ builder_.AddExtraArg(std::move(token));
+}
+
+void LauncherInfoInflator::Parse(const fs::path& path) {
+ std::ifstream launcher_file;
+ launcher_file.open(path);
+ if (launcher_file.fail())
+ return;
+
+ bool parsing = false;
+ std::string line;
+ while (std::getline(launcher_file, line)) {
+ string_stream_ = std::istringstream(line);
+ std::string token1;
+ if (!(string_stream_ >> token1))
+ continue;
+
+ std::string key = Util::ToUpper(std::move(token1));
+ if (key == kTagLauncher) {
+ if (parsing)
+ Insert();
+
+ builder_.Reset();
+ parsing = true;
+ continue;
+ }
+
+ if (parsing == false)
+ continue;
+
+ std::string token2;
+ if (!(string_stream_ >> token2))
+ continue;
+
+ auto found = parsers_.find(key);
+ if (found == parsers_.end())
+ continue;
+
+ auto& parser = found->second;
+ parser(std::move(token2));
+ }
+
+ if (parsing)
+ Insert();
+
+ launcher_file.close();
+}
+
+void LauncherInfoInflator::Insert() {
+ launcher_infos_.emplace_back(builder_.Build());
+}
+
+std::vector<LauncherInfoPtr> LauncherInfoInflator::Inflate(
+ const std::string_view path) {
+ fs::path dir_path(path);
+ if (fs::is_directory(dir_path) == false)
+ return {};
+
+ try {
+ for (auto& entry : fs::directory_iterator(dir_path)) {
+ fs::path file(entry.path());
+ if (file.extension() == ".launcher") {
+ Parse(file);
+ }
+ }
+ } catch (const fs::filesystem_error& e) {
+ _E("Exception occurs. error(%s:%d)", e.what(), e.code().value());
+ }
+
+ return launcher_infos_;
+}
+
+} // namespace launchpad
--- /dev/null
+/*
+ * Copyright (c) 2023 - 2024 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_CORE_LAUNCHER_INFO_HH_
+#define LIB_LAUNCHPAD_CORE_LAUNCHER_INFO_HH_
+
+#include <filesystem>
+#include <functional>
+#include <memory>
+#include <string>
+#include <string_view>
+#include <unordered_map>
+#include <vector>
+
+namespace launchpad {
+
+class LauncherInfo {
+ public:
+ class Builder {
+ public:
+ Builder& SetName(std::string name);
+ Builder& SetExe(std::string exe);
+ Builder& AddAppType(std::string app_type);
+ Builder& AddExtraArg(std::string extra_arg);
+ Builder& Reset();
+
+ LauncherInfo* Build();
+
+ private:
+ std::string name_;
+ std::string exe_;
+ std::vector<std::string> app_types_;
+ std::vector<std::string> extra_args_;
+ };
+
+ LauncherInfo(std::string name, std::string exe,
+ std::vector<std::string> app_types, std::vector<std::string> extra_args);
+
+ const std::string& GetName() const;
+ const std::string& GetExe() const;
+ const std::vector<std::string>& GetAppTypes() const;
+ const std::vector<std::string>& GetExtraArgs() const;
+
+ private:
+ friend class LauncherInfoInflator;
+
+ std::string name_;
+ std::string exe_;
+ std::vector<std::string> app_types_;
+ std::vector<std::string> extra_args_;
+};
+
+using LauncherInfoPtr = std::shared_ptr<LauncherInfo>;
+
+class LauncherInfoInflator {
+ public:
+ LauncherInfoInflator();
+
+ std::vector<LauncherInfoPtr> Inflate(const std::string_view path);
+
+ private:
+ void Parse(const std::filesystem::path& path);
+
+ void ParseName(std::string token);
+ void ParseExe(std::string token);
+ void ParseAppType(std::string token);
+ void ParseExtraArg(std::string token);
+ void Insert();
+
+ private:
+ std::unordered_map<std::string, std::function<void(std::string)>> parsers_;
+ std::istringstream string_stream_;
+ LauncherInfo::Builder builder_;
+ std::vector<std::shared_ptr<LauncherInfo>> launcher_infos_;
+};
+
+} // namespace launchpad
+
+#endif // LIB_LAUNCHPAD_CORE_LAUNCHER_INFO_HH_
--- /dev/null
+/*
+ * Copyright (c) 2024 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-core/launchpad_args.hh"
+
+namespace launchpad {
+
+LaunchpadArgs& LaunchpadArgs::GetInst() {
+ static LaunchpadArgs inst;
+ return inst;
+}
+
+void LaunchpadArgs::Set(int argc, char** args) {
+ argc_ = argc;
+ args_ = args;
+}
+
+int LaunchpadArgs::GetArgc() const {
+ return argc_;
+}
+
+char** LaunchpadArgs::GetArgs() const {
+ return args_;
+}
+
+} // namespace launchpad
--- /dev/null
+/*
+ * Copyright (c) 2024 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_CORE_LAUNCHPAD_ARGS_HH_
+#define LIB_LAUNCHPAD_CORE_LAUNCHPAD_ARGS_HH_
+
+#undef EXPORT_API
+#define EXPORT_API __attribute__((visibility("default")))
+
+namespace launchpad {
+
+class EXPORT_API LaunchpadArgs {
+ public:
+ LaunchpadArgs(const LaunchpadArgs&) = delete;
+ LaunchpadArgs& operator=(const LaunchpadArgs&) = delete;
+
+ static LaunchpadArgs& GetInst();
+
+ void Set(int argc, char** args);
+
+ int GetArgc() const;
+ char** GetArgs() const;
+
+ private:
+ LaunchpadArgs() = default;
+ ~LaunchpadArgs() = default;
+
+ private:
+ int argc_ = 0;
+ char** args_ = nullptr;
+};
+
+} // namespace launchpad
+
+#endif // LIB_LAUNCHPAD_CORE_LAUNCHPAD_ARGS_HH_
--- /dev/null
+/*
+ * Copyright (c) 2023 - 2024 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-core/loader_executor.hh"
+
+#include <errno.h>
+#include <stdio.h>
+#include <unistd.h>
+
+#include <utility>
+
+#include <parcel.hh>
+#include <sched_priority.hh>
+#include <stdio.hh>
+#include <types.hh>
+#include <util.hh>
+
+#include "launchpad-core/log_private.hh"
+
+namespace launchpad {
+namespace {
+
+tizen_base::Parcel CreateParcelFromBundle(tizen_base::Bundle* b) {
+ auto b_raw = b->ToRaw();
+ std::string raw(reinterpret_cast<const char*>(b_raw.first.get()));
+ tizen_base::Parcel parcel;
+ parcel.WriteString(raw);
+ return parcel;
+}
+
+tizen_base::Bundle CreateBundleFromParcel(tizen_base::Parcel* parcel) {
+ std::string raw = parcel->ReadString();
+ return tizen_base::Bundle(raw);
+}
+
+} // namespace
+
+LoaderExecutor::LoaderExecutor() : Executor(this) {
+ process_pool_ = std::unique_ptr<ProcessPool>(new ProcessPool(
+ "loader", ProcessPool::GetNumberOfLoaderProcesses(), this));
+}
+
+LoaderExecutor& LoaderExecutor::GetInst() {
+ static LoaderExecutor inst;
+ return inst;
+}
+
+pid_t LoaderExecutor::Execute(const LoaderInfo* loader_info, int loader_id,
+ int priority) {
+ loader_argv_ = CreateLoaderArgv(loader_info, loader_id);
+ if (process_pool_->IsPrepared()) {
+ tizen_base::Bundle b;
+ b.Add("LOADER_ARGS", loader_argv_);
+ b.Add("LOADER_PRIORITY", std::to_string(priority));
+ auto parcel = CreateParcelFromBundle(&b);
+ pid_t pid = process_pool_->Execute(parcel);
+ if (pid > 0) return pid;
+ }
+
+ return Executor::Execute(priority);
+}
+
+bool LoaderExecutor::HasCandidateProcess() const {
+ return process_pool_->IsPrepared();
+}
+
+void LoaderExecutor::DisposeCandidateProcess() {
+ process_pool_->Dispose();
+ process_pool_->SetTimer();
+}
+
+void LoaderExecutor::HandleSigchld(pid_t pid) {
+ process_pool_->HandleSigchld(pid);
+}
+
+void LoaderExecutor::OnExecution() {
+ std::vector<char*> loader_argv(loader_argv_.size() + 1);
+ int loader_argc = loader_argv_.size();
+ for (int i = 0; i < loader_argc; ++i) {
+ loader_argv[i] = const_cast<char*>(loader_argv_[i].c_str());
+ if ((i + 1) != loader_argc)
+ SECURE_LOGD("loader argument %d : %s##", i, loader_argv[i]);
+ }
+
+ Util::CloseAllFds();
+ Stdio::Setup();
+
+ SECURE_LOGE("Execute loader(%s)", loader_argv[LoaderArg::Path]);
+ if (execv(loader_argv[LoaderArg::Path], loader_argv.data()) < 0) {
+ char err_buf[1024];
+ fprintf(stderr, "Failed to execute a file. path: %s, errno: %d:%s\n",
+ loader_argv[LoaderArg::Path], errno,
+ strerror_r(errno, err_buf, sizeof(err_buf)));
+ exit(EXIT_FAILURE);
+ }
+}
+
+void LoaderExecutor::OnRequestReceived(tizen_base::Parcel* parcel) {
+ _W("Request received");
+ 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();
+}
+
+std::vector<std::string> LoaderExecutor::CreateLoaderArgv(
+ const LoaderInfo* loader_info, int loader_id) {
+ std::string dummy(kLoaderArgLength - 1, ' ');
+ std::vector<std::string> argv(LoaderArg::Dummy + 1);
+ argv[LoaderArg::Dummy] = std::move(dummy);
+ argv[LoaderArg::Path] = loader_info->GetExe();
+ argv[LoaderArg::Type] = std::to_string(loader_info->GetType());
+ argv[LoaderArg::Id] = std::to_string(loader_id);
+ argv[LoaderArg::Hydra] = loader_info->IsHydraMode() ? "1" : "0";
+ argv[LoaderArg::Extra] = reinterpret_cast<const char*>(
+ const_cast<tizen_base::Bundle&>(loader_info->GetExtra())
+ .ToRaw()
+ .first.get());
+ return argv;
+}
+
+} // namespace launchpad
--- /dev/null
+/*
+ * Copyright (c) 2023 - 2024 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_CORE_LOADER_EXECUTOR_HH_
+#define LIB_LAUNCHPAD_CORE_LOADER_EXECUTOR_HH_
+
+#include <sys/types.h>
+
+#include <memory>
+#include <string>
+#include <vector>
+
+#include "launchpad-core/executor.hh"
+#include "launchpad-core/loader_info.hh"
+#include "launchpad-core/process_pool.hh"
+
+#undef EXPORT_API
+#define EXPORT_API __attribute__((visibility("default")))
+
+namespace launchpad {
+
+class EXPORT_API LoaderExecutor : public Executor::Delegator,
+ public Executor,
+ public ProcessPool::IEvent {
+ public:
+ LoaderExecutor(const LoaderExecutor&) = delete;
+ LoaderExecutor& operator=(const LoaderExecutor&) = delete;
+ LoaderExecutor(LoaderExecutor&&) = delete;
+ LoaderExecutor& operator=(LoaderExecutor&&) = delete;
+
+ static LoaderExecutor& GetInst();
+
+ pid_t Execute(const LoaderInfo* loader_info, int loader_id, int priority);
+ bool HasCandidateProcess() const;
+ void DisposeCandidateProcess();
+ void HandleSigchld(pid_t pid);
+
+ private:
+ LoaderExecutor();
+ ~LoaderExecutor() = default;
+
+ void OnExecution() override;
+ void OnRequestReceived(tizen_base::Parcel* parcel) override;
+ std::vector<std::string> CreateLoaderArgv(const LoaderInfo* loader_info,
+ int loader_id);
+
+ private:
+ std::unique_ptr<ProcessPool> process_pool_;
+ std::vector<std::string> loader_argv_;
+};
+
+} // namespace launchpad
+
+#endif // LIB_LAUNCHPAD_CORE_LOADER_EXECUTOR_HH_
--- /dev/null
+/*
+ * Copyright (c) 2023 - 2024 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-core/loader_info.hh"
+
+#include <dirent.h>
+#include <malloc.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <algorithm>
+#include <fstream>
+#include <sstream>
+#include <utility>
+
+#include <util.hh>
+
+#include "launchpad-core/log_private.hh"
+
+namespace fs = std::filesystem;
+
+namespace launchpad {
+namespace {
+
+constexpr const char kTagLoader[] = "[LOADER]";
+constexpr const char kTagName[] = "NAME";
+constexpr const char kTagExe[] = "EXE";
+constexpr const char kTagAppType[] = "APP_TYPE";
+constexpr const char kTagDetectionMethod[] = "DETECTION_METHOD";
+constexpr const char kTagActivationMethod[] = "ACTIVATION_METHOD";
+constexpr const char kTagDeactivationMethod[] = "DEACTIVATION_METHOD";
+constexpr const char kTagTtl[] = "TTL";
+constexpr const char kTagTimeout[] = "TIMEOUT";
+constexpr const char kTagExtra[] = "EXTRA";
+constexpr const char kTagExtraArray[] = "EXTRA_ARRAY";
+constexpr const char kTagExtraArrayVal[] = "EXTRA_ARRAY_VAL";
+constexpr const char kTagAlternativeLoader[] = "ALTERNATIVE_LOADER";
+constexpr const char kTagHwAcc[] = "HW_ACC";
+constexpr const char kTagCpuThresholdMax[] = "CPU_THRESHOLD_MAX";
+constexpr const char kTagCpuThresholdMin[] = "CPU_THRESHOLD_MIN";
+constexpr const char kTagOnBoot[] = "ON_BOOT";
+constexpr const char kTagHydra[] = "HYDRA";
+constexpr const char kTagAppCheck[] = "APP_CHECK";
+constexpr const char kTagOnBootTimeout[] = "ON_BOOT_TIMEOUT";
+constexpr const char kTagSchedPriority[] = "SCHED_PRIORITY";
+constexpr const char kTagConditionPathExists[] = "CONDITION_PATH_EXISTS";
+
+constexpr const char kValOn[] = "ON";
+constexpr const char kValOff[] = "OFF";
+constexpr const char kValMethodTimeout[] = "TIMEOUT";
+constexpr const char kValMethodDemand[] = "DEMAND";
+constexpr const char kValMethodVisibility[] = "VISIBILITY";
+constexpr const char kValMethodRequest[] = "REQUEST";
+constexpr const char kValMethodAvailableMemory[] = "AVAILABLE_MEMORY";
+constexpr const char kValMethodTtl[] = "TTL";
+constexpr const char kValMethodOutOfMemory[] = "OUT_OF_MEMORY";
+
+LoaderType MakeLoaderType() {
+ static uint32_t user_slot_offset;
+ return static_cast<LoaderType>(
+ static_cast<int>(LoaderType::User) + user_slot_offset++);
+}
+
+} // namespace
+
+LoaderInfo::Builder& LoaderInfo::Builder::SetType(LoaderType type) {
+ type_ = type;
+ return *this;
+}
+
+LoaderInfo::Builder& LoaderInfo::Builder::SetName(std::string name) {
+ name_ = std::move(name);
+ return *this;
+}
+
+LoaderInfo::Builder& LoaderInfo::Builder::SetExe(std::string exe) {
+ exe_ = std::move(exe);
+ return *this;
+}
+
+LoaderInfo::Builder& LoaderInfo::Builder::AddAppType(std::string app_type) {
+ app_types_.push_back(std::move(app_type));
+ return *this;
+}
+
+LoaderInfo::Builder& LoaderInfo::Builder::SetAppTypes(
+ std::vector<std::string> app_types) {
+ app_types_ = std::move(app_types);
+ return *this;
+}
+
+LoaderInfo::Builder& LoaderInfo::Builder::SetDetectionMethod(
+ LoaderMethod method) {
+ detection_method_ = method;
+ return *this;
+}
+
+LoaderInfo::Builder& LoaderInfo::Builder::SetActivationMethod(
+ LoaderMethod method) {
+ activation_method_ = method;
+ return *this;
+}
+
+LoaderInfo::Builder& LoaderInfo::Builder::SetDeactivationMethod(
+ LoaderMethod method) {
+ deactivation_method_ = method;
+ return *this;
+}
+
+LoaderInfo::Builder& LoaderInfo::Builder::SetTimeout(int timeout) {
+ timeout_ = timeout;
+ return *this;
+}
+
+LoaderInfo::Builder& LoaderInfo::Builder::SetHwAcc(std::string hw_acc) {
+ hw_acc_ = std::move(hw_acc);
+ return *this;
+}
+
+LoaderInfo::Builder& LoaderInfo::Builder::AddAlternativeLoader(
+ std::string alternative_loader) {
+ alternative_loaders_.push_back(std::move(alternative_loader));
+ return *this;
+}
+
+LoaderInfo::Builder& LoaderInfo::Builder::SetAlternativeLoaders(
+ std::vector<std::string> alternative_loaders) {
+ alternative_loaders_ = std::move(alternative_loaders);
+ return *this;
+}
+
+LoaderInfo::Builder& LoaderInfo::Builder::AddExtraData(std::string key,
+ std::string value) {
+ extra_.Add(std::move(key), std::move(value));
+ return *this;
+}
+
+LoaderInfo::Builder& LoaderInfo::Builder::AddExtraArrayData(std::string key,
+ std::vector<std::string> value) {
+ extra_.Add(std::move(key), std::move(value));
+ return *this;
+}
+
+LoaderInfo::Builder& LoaderInfo::Builder::SetExtra(tizen_base::Bundle extra) {
+ extra_ = std::move(extra);
+ return *this;
+}
+
+LoaderInfo::Builder& LoaderInfo::Builder::SetCPUThresholdMax(
+ int cpu_threshold_max) {
+ cpu_threshold_max_ = cpu_threshold_max;
+ return *this;
+}
+
+LoaderInfo::Builder& LoaderInfo::Builder::SetCPUThresholdMin(
+ int cpu_threshold_min) {
+ cpu_threshold_min_ = cpu_threshold_min;
+ return *this;
+}
+
+LoaderInfo::Builder& LoaderInfo::Builder::SetOnBoot(bool on_boot) {
+ on_boot_ = on_boot;
+ return *this;
+}
+
+LoaderInfo::Builder& LoaderInfo::Builder::SetTimeToLive(int time_to_live) {
+ time_to_live_ = time_to_live;
+ return *this;
+}
+
+LoaderInfo::Builder& LoaderInfo::Builder::SetHydraMode(bool hydra_mode) {
+ hydra_mode_ = hydra_mode;
+ return *this;
+}
+
+LoaderInfo::Builder& LoaderInfo::Builder::SetAppCheck(bool app_check) {
+ app_check_ = app_check;
+ return *this;
+}
+
+LoaderInfo::Builder& LoaderInfo::Builder::SetOnBootTimeout(
+ int on_boot_timeout) {
+ on_boot_timeout_ = on_boot_timeout;
+ return *this;
+}
+
+LoaderInfo::Builder& LoaderInfo::Builder::SetSchedPriority(int sched_priority) {
+ sched_priority_ = sched_priority;
+ return *this;
+}
+
+LoaderInfo::Builder& LoaderInfo::Builder::AddConditionPathExists(
+ std::string path) {
+ condition_path_exists_.push_back(std::move(path));
+ return *this;
+}
+
+LoaderInfo::Builder& LoaderInfo::Builder::SetConditionPathExists(
+ std::vector<std::string> condition_path_exists) {
+ condition_path_exists_ = std::move(condition_path_exists);
+ return *this;
+}
+
+LoaderInfo::Builder& LoaderInfo::Builder::Reset() {
+ type_ = LoaderType::None;
+ name_.clear();
+ exe_.clear();
+ app_types_.clear();
+ detection_method_ = LoaderMethod::Timeout | LoaderMethod::Visibility |
+ LoaderMethod::Install;
+ activation_method_ = LoaderMethod::None;
+ deactivation_method_ = LoaderMethod::None;
+ timeout_ = 5000;
+ hw_acc_.clear();
+ alternative_loaders_.clear();
+ extra_ = tizen_base::Bundle();
+ cpu_threshold_max_ = 90;
+ cpu_threshold_min_ = 40;
+ on_boot_ = true;
+ time_to_live_ = 600;
+ hydra_mode_ = false;
+ app_check_ = true;
+ on_boot_timeout_ = 0;
+ sched_priority_ = 0;
+ condition_path_exists_.clear();
+ return *this;
+}
+
+LoaderInfo* LoaderInfo::Builder::Build() {
+ return new LoaderInfo(type_, std::move(name_), std::move(exe_),
+ std::move(app_types_), detection_method_, activation_method_,
+ deactivation_method_, timeout_, std::move(hw_acc_),
+ std::move(alternative_loaders_), std::move(extra_),
+ cpu_threshold_max_, cpu_threshold_min_, on_boot_, time_to_live_,
+ hydra_mode_, app_check_, on_boot_timeout_, sched_priority_,
+ std::move(condition_path_exists_));
+}
+
+LoaderInfo::LoaderInfo(LoaderType type, std::string name, std::string exe,
+ std::vector<std::string> app_types, LoaderMethod detection_method,
+ LoaderMethod activation_method, LoaderMethod deactivation_method,
+ int timeout, std::string hw_acc,
+ std::vector<std::string> alternative_loaders,
+ tizen_base::Bundle extra, int cpu_threshold_max,
+ int cpu_threshold_min, bool on_boot, int time_to_live,
+ bool hydra_mode, bool app_check, int on_boot_timeout,
+ int sched_priority, std::vector<std::string> condition_path_exists)
+ : type_(type),
+ name_(std::move(name)),
+ exe_(std::move(exe)),
+ app_types_(std::move(app_types)),
+ detection_method_(detection_method),
+ activation_method_(activation_method),
+ deactivation_method_(deactivation_method),
+ timeout_(timeout),
+ hw_acc_(std::move(hw_acc)),
+ alternative_loaders_(std::move(alternative_loaders)),
+ extra_(std::move(extra)),
+ cpu_threshold_max_(cpu_threshold_max),
+ cpu_threshold_min_(cpu_threshold_min),
+ on_boot_(on_boot),
+ time_to_live_(time_to_live),
+ hydra_mode_(hydra_mode),
+ app_check_(app_check),
+ on_boot_timeout_(on_boot_timeout),
+ sched_priority_(sched_priority),
+ condition_path_exists_(std::move(condition_path_exists)) {
+ extra_.Add("SCHED_PRIORITY", std::to_string(sched_priority_));
+}
+
+LoaderType LoaderInfo::GetType() const {
+ return type_;
+}
+
+void LoaderInfo::SetType(LoaderType type) {
+ type_ = type;
+}
+
+const std::string& LoaderInfo::GetName() const {
+ return name_;
+}
+
+const std::string& LoaderInfo::GetExe() const {
+ return exe_;
+}
+
+void LoaderInfo::SetExe(std::string exe) {
+ exe_ = std::move(exe);
+}
+
+int LoaderInfo::GetCpuThresholdMax() const {
+ return cpu_threshold_max_;
+}
+
+int LoaderInfo::GetCpuThresholdMin() const {
+ return cpu_threshold_min_;
+}
+
+int LoaderInfo::GetTimeToLive() const {
+ return time_to_live_;
+}
+
+const std::vector<std::string>& LoaderInfo::GetAppTypes() const {
+ return app_types_;
+}
+
+LoaderMethod LoaderInfo::GetDetectionMethod() const {
+ return detection_method_;
+}
+
+void LoaderInfo::SetDetectionMethod(LoaderMethod detection_method) {
+ detection_method_ = detection_method;
+}
+
+LoaderMethod LoaderInfo::GetActivationMethod() const {
+ return activation_method_;
+}
+
+void LoaderInfo::SetActivationMethod(LoaderMethod activation_method) {
+ activation_method_ = activation_method;
+}
+
+LoaderMethod LoaderInfo::GetDeactivationMethod() const {
+ return deactivation_method_;
+}
+
+void LoaderInfo::SetDeactivationMethod(LoaderMethod deactivation_method) {
+ deactivation_method_ = deactivation_method;
+}
+
+const std::string& LoaderInfo::GetHwAcc() const {
+ return hw_acc_;
+}
+
+int LoaderInfo::GetOnBootTimeout() const {
+ return on_boot_timeout_;
+}
+
+int LoaderInfo::GetTimeout() const {
+ return timeout_;
+}
+
+void LoaderInfo::SetTimeout(int timeout) {
+ timeout_ = timeout;
+}
+
+int LoaderInfo::GetSchedPriority() const {
+ return sched_priority_;
+}
+
+bool LoaderInfo::ShouldCheckAppInstallation() const {
+ return app_check_;
+}
+
+bool LoaderInfo::IsOnBoot() const {
+ return on_boot_;
+}
+
+bool LoaderInfo::IsHydraMode() const {
+ return hydra_mode_;
+}
+
+const tizen_base::Bundle& LoaderInfo::GetExtra() const {
+ return extra_;
+}
+
+void LoaderInfo::SetAppInstalled(bool app_installed) {
+ app_installed_ = app_installed;
+}
+
+bool LoaderInfo::IsAppInstalled() const {
+ return app_installed_;
+}
+
+const std::vector<std::string>& LoaderInfo::GetConditionPathExists() const {
+ return condition_path_exists_;
+}
+
+LoaderInfoInflator::LoaderInfoInflator() {
+ parsers_ = {
+ { kTagName,
+ std::bind(&LoaderInfoInflator::ParseName,
+ this, std::placeholders::_1) },
+ { kTagExe,
+ std::bind(&LoaderInfoInflator::ParseExe,
+ this, std::placeholders::_1) },
+ { kTagAppType,
+ std::bind(&LoaderInfoInflator::ParseAppType,
+ this, std::placeholders::_1) },
+ { kTagDetectionMethod,
+ std::bind(&LoaderInfoInflator::ParseDetectionMethod,
+ this, std::placeholders::_1) },
+ { kTagActivationMethod,
+ std::bind(&LoaderInfoInflator::ParseActivationMethod,
+ this, std::placeholders::_1) },
+ { kTagDeactivationMethod,
+ std::bind(&LoaderInfoInflator::ParseDeativationMethod,
+ this, std::placeholders::_1) },
+ { kTagTtl,
+ std::bind(&LoaderInfoInflator::ParseTimeToLive,
+ this, std::placeholders::_1) },
+ { kTagTimeout,
+ std::bind(&LoaderInfoInflator::ParseTimeout,
+ this, std::placeholders::_1) },
+ { kTagExtra,
+ std::bind(&LoaderInfoInflator::ParseExtra,
+ this, std::placeholders::_1) },
+ { kTagExtraArray,
+ std::bind(&LoaderInfoInflator::ParseExtraArray,
+ this, std::placeholders::_1) },
+ { kTagExtraArrayVal,
+ std::bind(&LoaderInfoInflator::ParseExtraArrayValue,
+ this, std::placeholders::_1) },
+ { kTagHwAcc,
+ std::bind(&LoaderInfoInflator::ParseHwAcc,
+ this, std::placeholders::_1) },
+ { kTagAlternativeLoader,
+ std::bind(&LoaderInfoInflator::ParseAlternativeLoader,
+ this, std::placeholders::_1) },
+ { kTagCpuThresholdMax,
+ std::bind(&LoaderInfoInflator::ParseCPUThresholdMax,
+ this, std::placeholders::_1) },
+ { kTagCpuThresholdMin,
+ std::bind(&LoaderInfoInflator::ParseCPUThresholdMin,
+ this, std::placeholders::_1) },
+ { kTagOnBoot,
+ std::bind(&LoaderInfoInflator::ParseOnBoot,
+ this, std::placeholders::_1) },
+ { kTagHydra,
+ std::bind(&LoaderInfoInflator::ParseHydra,
+ this, std::placeholders::_1) },
+ { kTagAppCheck,
+ std::bind(&LoaderInfoInflator::ParseAppCheck,
+ this, std::placeholders::_1) },
+ { kTagOnBootTimeout,
+ std::bind(&LoaderInfoInflator::ParseOnBootTimeout,
+ this, std::placeholders::_1) },
+ { kTagSchedPriority,
+ std::bind(&LoaderInfoInflator::ParseSchedPriority,
+ this, std::placeholders::_1) },
+ { kTagConditionPathExists,
+ std::bind(&LoaderInfoInflator::ParseConditionPathExists,
+ this, std::placeholders::_1) },
+ };
+}
+
+void LoaderInfoInflator::ParseName(std::string token) {
+ builder_.SetName(std::move(token));
+}
+
+void LoaderInfoInflator::ParseExe(std::string token) {
+ builder_.SetExe(std::move(token));
+}
+
+void LoaderInfoInflator::ParseAppType(std::string token) {
+ std::string line = std::move(token);
+ do {
+ auto tokens = Util::Split(line, " |\t\r\n");
+ for (auto& app_type : tokens)
+ builder_.AddAppType(app_type);
+ } while (std::getline(string_stream_, line));
+}
+
+void LoaderInfoInflator::ParseDetectionMethod(std::string token) {
+ LoaderMethod method = LoaderMethod::None;
+ std::string line = std::move(token);
+ do {
+ auto tokens = Util::Split(line, " |\t\r\n");
+ for (auto& token : tokens) {
+ if (token == kValMethodTimeout)
+ method = method | LoaderMethod::Timeout;
+ else if (token == kValMethodVisibility)
+ method = method | LoaderMethod::Visibility;
+ else if (token == kValMethodDemand)
+ method = method | LoaderMethod::Demand;
+ }
+ } while (std::getline(string_stream_, line));
+
+ method = method | LoaderMethod::Install;
+ builder_.SetDetectionMethod(method);
+ _D("Detection method: %d", static_cast<int>(method));
+}
+
+void LoaderInfoInflator::ParseActivationMethod(std::string token) {
+ LoaderMethod method = LoaderMethod::None;
+ std::string line = std::move(token);
+ do {
+ auto tokens = Util::Split(line, " |\t\r\n");
+ for (auto& token : tokens) {
+ if (token == kValMethodRequest)
+ method = method | LoaderMethod::Request;
+ else if (token == kValMethodAvailableMemory)
+ method = method | LoaderMethod::AvailableMemory;
+ }
+ } while (std::getline(string_stream_, line));
+
+ builder_.SetActivationMethod(method);
+ _D("Activation method: %d", static_cast<int>(method));
+}
+
+void LoaderInfoInflator::ParseDeativationMethod(std::string token) {
+ LoaderMethod method = LoaderMethod::None;
+ std::string line = std::move(token);
+ do {
+ auto tokens = Util::Split(line, " |\t\r\n");
+ for (auto& token : tokens) {
+ if (token == kValMethodTtl)
+ method = method | LoaderMethod::TimeToLive;
+ else if (token == kValMethodOutOfMemory)
+ method = method | LoaderMethod::OutOfMemory;
+ }
+ } while (std::getline(string_stream_, line));
+
+ builder_.SetDeactivationMethod(method);
+ _D("Deactivation method: %d", static_cast<int>(method));
+}
+
+void LoaderInfoInflator::ParseTimeToLive(std::string token) {
+ builder_.SetTimeToLive(std::stoi(token));
+}
+
+void LoaderInfoInflator::ParseTimeout(std::string token) {
+ builder_.SetTimeout(std::stoi(token));
+}
+
+void LoaderInfoInflator::ParseExtra(std::string token) {
+ std::string value;
+ if (string_stream_ >> value)
+ builder_.AddExtraData(std::move(token), std::move(value));
+}
+
+void LoaderInfoInflator::ParseExtraArray(std::string token) {
+ if (!extra_array_key_.empty() && !extra_array_value_.empty()) {
+ builder_.AddExtraArrayData(std::move(extra_array_key_),
+ std::move(extra_array_value_));
+ extra_array_value_.clear();
+ }
+
+ extra_array_key_ = std::move(token);
+}
+
+void LoaderInfoInflator::ParseExtraArrayValue(std::string token) {
+ extra_array_value_.push_back(std::move(token));
+}
+
+void LoaderInfoInflator::ParseHwAcc(std::string token) {
+ builder_.SetHwAcc(std::move(token));
+}
+
+void LoaderInfoInflator::ParseAlternativeLoader(std::string token) {
+ builder_.AddAlternativeLoader(std::move(token));
+}
+
+void LoaderInfoInflator::ParseCPUThresholdMax(std::string token) {
+ builder_.SetCPUThresholdMax(std::stoi(token));
+}
+
+void LoaderInfoInflator::ParseCPUThresholdMin(std::string token) {
+ builder_.SetCPUThresholdMin(std::stoi(token));
+}
+
+void LoaderInfoInflator::ParseOnBoot(std::string token) {
+ if (token == kValOff)
+ builder_.SetOnBoot(false);
+}
+
+void LoaderInfoInflator::ParseHydra(std::string token) {
+ if (token == kValOn)
+ builder_.SetHydraMode(true);
+}
+
+void LoaderInfoInflator::ParseAppCheck(std::string token) {
+ if (token == kValOff)
+ builder_.SetAppCheck(false);
+}
+
+void LoaderInfoInflator::ParseOnBootTimeout(std::string token) {
+ builder_.SetOnBootTimeout(std::stoi(token));
+}
+
+void LoaderInfoInflator::ParseSchedPriority(std::string token) {
+ builder_.SetSchedPriority(std::min(std::max(std::stoi(token), -20), 19));
+}
+
+void LoaderInfoInflator::ParseConditionPathExists(std::string token) {
+ std::string line = std::move(token);
+ do {
+ auto tokens = Util::Split(line, " |\t\r\n");
+ for (auto& token : tokens)
+ builder_.AddConditionPathExists(token);
+ } while (std::getline(string_stream_, line));
+}
+
+void LoaderInfoInflator::Parse(const std::filesystem::path& path,
+ LoaderType type) {
+ std::ifstream loader_file;
+ loader_file.open(path);
+ if (loader_file.fail())
+ return;
+
+ bool parsing = false;
+ std::string line;
+ while (std::getline(loader_file, line)) {
+ string_stream_ = std::istringstream(line);
+ std::string token1;
+ if (!(string_stream_ >> token1))
+ continue;
+
+ std::string key = Util::ToUpper(std::move(token1));
+ if (key == kTagLoader) {
+ if (parsing)
+ Insert(type);
+
+ builder_.Reset();
+ parsing = true;
+ continue;
+ }
+
+ if (parsing == false)
+ continue;
+
+ std::string token2;
+ if (!(string_stream_ >> token2))
+ continue;
+
+ auto found = parsers_.find(key);
+ if (found == parsers_.end())
+ continue;
+
+ auto& parser = found->second;
+ parser(std::move(token2));
+ }
+
+ if (parsing)
+ Insert(type);
+
+ loader_file.close();
+}
+
+void LoaderInfoInflator::Insert(LoaderType type) {
+ if (!extra_array_key_.empty() && !extra_array_value_.empty()) {
+ builder_.AddExtraArrayData(std::move(extra_array_key_),
+ std::move(extra_array_value_));
+ extra_array_value_.clear();
+ }
+
+ if (type != LoaderType::Dynamic)
+ type = MakeLoaderType();
+
+ builder_.SetType(type);
+ loader_infos_.emplace_back(builder_.Build());
+}
+
+std::vector<LoaderInfoPtr> LoaderInfoInflator::Inflate(
+ const std::string_view path) {
+ fs::path input_path(path);
+ if (fs::is_directory(input_path) == false)
+ return {};
+
+ try {
+ for (auto& entry : fs::directory_iterator(input_path)) {
+ fs::path file(entry.path());
+ if (file.extension() == ".loader")
+ Parse(file, LoaderType::User);
+ }
+ } catch (const fs::filesystem_error& e) {
+ _E("Exception occurs. error(%s:%d)", e.what(), e.code().value());
+ }
+
+ return loader_infos_;
+}
+
+LoaderInfoManager::LoaderInfoManager(std::string path): path_(std::move(path)) {
+}
+
+void LoaderInfoManager::Load() {
+ if (!loader_list_.empty())
+ return;
+
+ LoaderInfoInflator inflator;
+ loader_list_ = inflator.Inflate(path_);
+}
+
+void LoaderInfoManager::LoadFile(const std::string_view file) {
+ LoaderInfoInflator inflator;
+ fs::path path(path_);
+ inflator.Parse(path / file, LoaderType::Dynamic);
+}
+
+void LoaderInfoManager::Unload(const std::string_view loader_name) {
+ loader_list_.erase(std::remove_if(loader_list_.begin(), loader_list_.end(),
+ [&](const LoaderInfoPtr& info) -> bool {
+ return info->GetName() == loader_name;
+ }), loader_list_.end());
+}
+
+void LoaderInfoManager::Dispose() {
+ loader_list_.clear();
+}
+
+std::string LoaderInfoManager::FindLoaderPath(
+ const std::string_view loader_name) {
+ for (auto& info : loader_list_) {
+ if (info->GetName() == loader_name)
+ return info->GetExe();
+ }
+
+ return "";
+}
+
+LoaderInfoPtr LoaderInfoManager::FindLoaderInfo(
+ const std::string_view loader_name) {
+ for (auto& info : loader_list_) {
+ if (info->GetName() == loader_name)
+ return info;
+ }
+
+ return nullptr;
+}
+
+LoaderType LoaderInfoManager::FindHwType(const std::string_view app_type) {
+ for (auto& info : loader_list_) {
+ if (info->GetHwAcc().empty() || info->GetHwAcc() == kValOn) {
+ auto found = std::find_if(
+ info->GetAppTypes().begin(), info->GetAppTypes().end(),
+ [&](const std::string& type) -> bool { return type == app_type; });
+ if (found != info->GetAppTypes().end())
+ return info->GetType();
+ }
+ }
+
+ return LoaderType::None;
+}
+
+LoaderType LoaderInfoManager::FindSwType(const std::string_view app_type) {
+ for (auto& info : loader_list_) {
+ if (info->GetHwAcc().empty() || info->GetHwAcc() == kValOff) {
+ auto found = std::find_if(
+ info->GetAppTypes().begin(), info->GetAppTypes().end(),
+ [&](const std::string& type) -> bool { return type == app_type; });
+ if (found != info->GetAppTypes().end())
+ return info->GetType();
+ }
+ }
+
+ return LoaderType::None;
+}
+
+std::vector<LoaderType> LoaderInfoManager::GetAlternativeTypes(
+ LoaderType type) {
+ std::vector<LoaderType> result;
+ for (auto& info : loader_list_) {
+ if (info->GetType() == type) {
+ for (auto& alt_loader : info->alternative_loaders_) {
+ auto found = std::find_if(loader_list_.begin(), loader_list_.end(),
+ [&](const auto& li) -> bool {
+ return li->GetName() == alt_loader;
+ });
+ if (found == loader_list_.end())
+ continue;
+
+ result.push_back((*found)->GetType());
+ }
+ }
+ }
+
+ return result;
+}
+
+const std::vector<LoaderInfoPtr>& LoaderInfoManager::GetLoaderInfoList() const {
+ return loader_list_;
+}
+
+} // namespace launchpad
--- /dev/null
+/*
+ * Copyright (c) 2023 - 2024 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_CORE_LOADER_INFO_HH_
+#define LIB_LAUNCHPAD_CORE_LOADER_INFO_HH_
+
+#include <bundle_cpp.h>
+
+#include <filesystem>
+#include <functional>
+#include <memory>
+#include <string>
+#include <string_view>
+#include <unordered_map>
+#include <vector>
+
+#include <types.hh>
+#include <util.hh>
+
+#undef EXPORT_API
+#define EXPORT_API __attribute__((visibility("default")))
+
+namespace launchpad {
+
+enum class EXPORT_API LoaderMethod : int {
+ None = 0x0000,
+ Timeout = 0x0001,
+ Visibility = 0x0002,
+ Demand = 0x0004,
+ Request = 0x0010,
+ AvailableMemory = 0x0020,
+ TimeToLive = 0x0040,
+ OutOfMemory = 0x0100,
+ Install = 0x0200,
+};
+
+class EXPORT_API LoaderInfo {
+ public:
+ class EXPORT_API Builder {
+ public:
+ Builder& SetType(LoaderType type);
+ Builder& SetName(std::string name);
+ Builder& SetExe(std::string exe);
+ Builder& AddAppType(std::string app_type);
+ Builder& SetAppTypes(std::vector<std::string> app_types);
+ Builder& SetDetectionMethod(launchpad::LoaderMethod method);
+ Builder& SetActivationMethod(launchpad::LoaderMethod method);
+ Builder& SetDeactivationMethod(launchpad::LoaderMethod method);
+ Builder& SetTimeout(int timeout);
+ Builder& SetHwAcc(std::string hw_acc);
+ Builder& AddAlternativeLoader(std::string alternative_loader);
+ Builder& SetAlternativeLoaders(
+ std::vector<std::string> alternative_loaders);
+ Builder& AddExtraData(std::string key, std::string value);
+ Builder& AddExtraArrayData(std::string key, std::vector<std::string> value);
+ Builder& SetExtra(tizen_base::Bundle extra);
+ Builder& SetCPUThresholdMax(int cpu_threshold_max);
+ Builder& SetCPUThresholdMin(int cpu_threshold_min);
+ Builder& SetOnBoot(bool on_boot);
+ Builder& SetTimeToLive(int time_to_live);
+ Builder& SetHydraMode(bool hydra_mode);
+ Builder& SetAppCheck(bool app_check);
+ Builder& SetOnBootTimeout(int on_boot_timeout);
+ Builder& SetSchedPriority(int sched_priority);
+ Builder& AddConditionPathExists(std::string path);
+ Builder& SetConditionPathExists(
+ std::vector<std::string> condition_path_exists);
+ Builder& Reset();
+
+ LoaderInfo* Build();
+
+ private:
+ LoaderType type_ = LoaderType::None;
+ std::string name_;
+ std::string exe_;
+ std::vector<std::string> app_types_;
+ LoaderMethod detection_method_ =
+ LoaderMethod::Timeout | LoaderMethod::Visibility | LoaderMethod::Install;
+ LoaderMethod activation_method_ = LoaderMethod::None;
+ LoaderMethod deactivation_method_ = LoaderMethod::None;
+ int timeout_ = 5000;
+ std::string hw_acc_;
+ std::vector<std::string> alternative_loaders_;
+ tizen_base::Bundle extra_;
+ int cpu_threshold_max_ = 90;
+ int cpu_threshold_min_ = 40;
+ bool on_boot_ = true;
+ int time_to_live_ = 600;
+ bool hydra_mode_ = false;
+ bool app_check_ = true;
+ int on_boot_timeout_ = 0;
+ int sched_priority_ = 0;
+ std::vector<std::string> condition_path_exists_;
+ };
+
+ LoaderInfo(LoaderType type, std::string name, std::string exe,
+ std::vector<std::string> app_types, LoaderMethod detection_method,
+ LoaderMethod activation_method, LoaderMethod deactivation_method,
+ int timeout, std::string hw_acc,
+ std::vector<std::string> alternative_loaders,
+ tizen_base::Bundle extra, int cpu_threshold_max,
+ int cpu_threshold_min, bool on_boot, int time_to_live,
+ bool hydra_mode, bool app_check, int on_boot_timeout,
+ int sched_priority,
+ std::vector<std::string> condition_path_exists);
+
+ LoaderType GetType() const;
+ void SetType(LoaderType type);
+ const std::string& GetName() const;
+ const std::string& GetExe() const;
+ void SetExe(std::string exe);
+ int GetCpuThresholdMax() const;
+ int GetCpuThresholdMin() const;
+ int GetTimeToLive() const;
+ const std::vector<std::string>& GetAppTypes() const;
+ LoaderMethod GetDetectionMethod() const;
+ void SetDetectionMethod(LoaderMethod detection_method);
+ LoaderMethod GetActivationMethod() const;
+ void SetActivationMethod(LoaderMethod activation_method);
+ LoaderMethod GetDeactivationMethod() const;
+ void SetDeactivationMethod(LoaderMethod deactivation_method);
+ const std::string& GetHwAcc() const;
+ int GetOnBootTimeout() const;
+ int GetTimeout() const;
+ void SetTimeout(int timeout);
+ int GetSchedPriority() const;
+ bool ShouldCheckAppInstallation() const;
+ bool IsOnBoot() const;
+ bool IsHydraMode() const;
+ const tizen_base::Bundle& GetExtra() const;
+ const std::vector<std::string>& GetConditionPathExists() const;
+ void SetAppInstalled(bool app_installed);
+ bool IsAppInstalled() const;
+
+ private:
+ friend class LoaderInfoManager;
+ friend class LoaderInfoInflator;
+
+ private:
+ LoaderType type_;
+ std::string name_;
+ std::string exe_;
+ std::vector<std::string> app_types_;
+ LoaderMethod detection_method_;
+ LoaderMethod activation_method_;
+ LoaderMethod deactivation_method_;
+ int timeout_;
+ std::string hw_acc_;
+ std::vector<std::string> alternative_loaders_;
+ tizen_base::Bundle extra_;
+ int cpu_threshold_max_;
+ int cpu_threshold_min_;
+ bool on_boot_;
+ int time_to_live_;
+ bool hydra_mode_;
+ bool app_check_;
+ int on_boot_timeout_;
+ int sched_priority_;
+ std::vector<std::string> condition_path_exists_;
+ bool app_installed_ = false;
+};
+
+using LoaderInfoPtr = std::shared_ptr<LoaderInfo>;
+
+class EXPORT_API LoaderInfoInflator {
+ public:
+ LoaderInfoInflator();
+
+ std::vector<LoaderInfoPtr> Inflate(const std::string_view path);
+
+ void Parse(const std::filesystem::path& path, LoaderType type);
+
+ private:
+ void ParseName(std::string token);
+ void ParseExe(std::string token);
+ void ParseAppType(std::string token);
+ void ParseDetectionMethod(std::string token);
+ void ParseActivationMethod(std::string token);
+ void ParseDeativationMethod(std::string token);
+ void ParseTimeToLive(std::string token);
+ void ParseTimeout(std::string token);
+ void ParseExtra(std::string token);
+ void ParseExtraArray(std::string token);
+ void ParseExtraArrayValue(std::string token);
+ void ParseHwAcc(std::string token);
+ void ParseAlternativeLoader(std::string token);
+ void ParseCPUThresholdMax(std::string token);
+ void ParseCPUThresholdMin(std::string token);
+ void ParseOnBoot(std::string token);
+ void ParseHydra(std::string token);
+ void ParseAppCheck(std::string token);
+ void ParseOnBootTimeout(std::string token);
+ void ParseSchedPriority(std::string token);
+ void ParseConditionPathExists(std::string token);
+ void Insert(LoaderType type);
+
+ private:
+ std::unordered_map<std::string, std::function<void(std::string)>> parsers_;
+ std::istringstream string_stream_;
+ std::string extra_array_key_;
+ std::vector<std::string> extra_array_value_;
+ LoaderInfo::Builder builder_;
+ std::vector<std::shared_ptr<LoaderInfo>> loader_infos_;
+};
+
+class EXPORT_API LoaderInfoManager {
+ public:
+ explicit LoaderInfoManager(std::string path);
+ LoaderInfoManager(const LoaderInfoManager&) = delete;
+ LoaderInfoManager& operator=(const LoaderInfoManager&) = delete;
+
+ void Load();
+ void LoadFile(const std::string_view file);
+ void Unload(const std::string_view loader_name);
+ void Dispose();
+ LoaderType FindHwType(const std::string_view app_type);
+ LoaderType FindSwType(const std::string_view app_type);
+ std::string FindLoaderPath(const std::string_view loader_name);
+ LoaderInfoPtr FindLoaderInfo(const std::string_view loader_name);
+ std::vector<LoaderType> GetAlternativeTypes(LoaderType type);
+ const std::vector<LoaderInfoPtr>& GetLoaderInfoList() const;
+
+ private:
+ std::string path_;
+ std::vector<LoaderInfoPtr> loader_list_;
+};
+
+} // namespace launchpad
+
+#endif // LIB_LAUNCHPAD_CORE_LOADER_INFO_HH_
--- /dev/null
+/*
+ * Copyright (c) 2024 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_CORE_LOG_PRIVATE_HH_
+#define LIB_LAUNCHPAD_CORE_LOG_PRIVATE_HH_
+
+#include <dlog.h>
+
+#undef LOG_TAG
+#define LOG_TAG "LAUNCHPAD"
+
+#undef _E
+#define _E(fmt, ...) LOGE("[CORE] " fmt, ##__VA_ARGS__)
+
+#undef _W
+#define _W(fmt, ...) LOGW("[CORE] " fmt, ##__VA_ARGS__)
+
+#undef _I
+#define _I(fmt, ...) LOGI("[CORE] " fmt, ##__VA_ARGS__)
+
+#undef _D
+#define _D(fmt, ...) LOGD("[CORE] " fmt, ##__VA_ARGS__)
+
+#endif // LIB_LAUNCHPAD_CORE_LOG_PRIVATE_HH_
--- /dev/null
+# Package Information for pkg-config
+
+prefix=/usr
+exec_prefix=@EXEC_PREFIX@
+libdir=@LIB_INSTALL_DIR@
+includedir=@INCLUDE_INSTALL_DIR@
+
+Name: liblaunchpad-core
+Description: launchpad core library
+Version: @VERSION@
+Requires: bundle dlog parcel launchpad-common launchpad-glib
+Libs: -L${libdir} -llaunchpad-core
+Cflags: -I${includedir} -I${includedir}/launchpad-core
--- /dev/null
+/*
+ * Copyright (c) 2023 - 2024 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-core/process_pool.hh"
+
+#include <dlog-redirect-stdout.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <linux/limits.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <filesystem>
+#include <utility>
+#include <vector>
+
+#include <ini_parser.hh>
+#include <util.hh>
+
+#include "launchpad-core/launchpad_args.hh"
+#include "launchpad-core/log_private.hh"
+
+namespace fs = std::filesystem;
+
+namespace launchpad {
+namespace {
+
+constexpr const char kProcessPool[] = "process-pool";
+constexpr const char kPathLaunchpadConf[] = "/usr/share/aul/launchpad.conf";
+constexpr const char kTagProcessPool[] = "ProcessPool";
+constexpr const char kKeyProcessPoolNumberOfProcesses[] = "NumberOfProcesses";
+constexpr const char kKeyProcessPoolNumberOfLoaderProcesses[] =
+ "NumberOfLoaderProcesses";
+
+class Config {
+ public:
+ Config() = default;
+
+ void Load() {
+ if (loaded_) return;
+
+ IniParser parser(kPathLaunchpadConf);
+ 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_);
+ loaded_ = true;
+ }
+
+ const int GetNumberOfProcesses() const { return number_of_processes_; }
+
+ const int GetNumberOfLoaderProcesses() const {
+ return number_of_loader_processes_;
+ }
+
+ private:
+ bool loaded_ = false;
+ int number_of_processes_ = 1;
+ int number_of_loader_processes_ = 1;
+};
+
+Config config_;
+
+bool IsExceptable(const std::string& path) {
+ static char buf[PATH_MAX];
+ ssize_t len = readlink(path.c_str(), buf, sizeof(buf));
+ if (len < 0) {
+ _E("readlink() is failed. errno: %d", errno);
+ return false;
+ }
+
+ buf[len] = '\0';
+ if (strstr(buf, "log") != nullptr ||
+ strstr(buf, "trace") != nullptr ||
+ strstr(buf, "dev") != nullptr)
+ return true;
+
+ return false;
+}
+
+std::vector<int> GetExceptableFds() {
+ std::vector<int> fds;
+ try {
+ fs::path proc_path("/proc/self/fd");
+ for (const auto& entry : fs::directory_iterator(proc_path)) {
+ if (!isdigit(entry.path().filename().string()[0]))
+ continue;
+
+ int fd = std::stoi(entry.path().filename().string());
+ if (dlog_is_log_fd(fd) || IsExceptable(entry.path().string()))
+ fds.push_back(fd);
+ }
+ } catch (const fs::filesystem_error& e) {
+ _E("Exception occurs. error(%s)", e.what());
+ }
+
+ return fds;
+}
+
+} // namespace
+
+ProcessPool::ProcessPool(std::string name, int num_processes,
+ IEvent* event_listener = nullptr)
+ : Executor(this),
+ name_(std::move(name)),
+ num_processes_(num_processes),
+ event_listener_(event_listener) {
+ PrepareProcess();
+}
+
+ProcessPool::~ProcessPool() {
+ Dispose();
+}
+
+bool ProcessPool::IsPrepared() const {
+ return !queue_.empty();
+}
+
+pid_t ProcessPool::Execute(const tizen_base::Parcel& parcel) {
+ SetTimer();
+ if (!IsPrepared())
+ return -1;
+
+ auto process = std::move(queue_.front());
+ queue_.erase(queue_.begin());
+ if (process->Send(parcel) < 0)
+ return -1;
+
+ return process->GetPid();
+}
+
+void ProcessPool::Dispose() {
+ for (auto& process : queue_) {
+ process->Kill();
+ _D("Kill process(%d)", process->GetPid());
+ }
+ queue_.clear();
+ UnsetTimer();
+}
+
+void ProcessPool::HandleSigchld(pid_t pid) {
+ auto iter = queue_.begin();
+ while (iter != queue_.end()) {
+ if ((*iter)->GetPid() == pid) {
+ iter = queue_.erase(iter);
+ break;
+ }
+
+ iter++;
+ }
+
+ int current_process_count = static_cast<int>(queue_.size());
+ if (current_process_count != num_processes_)
+ SetTimer();
+}
+
+ProcessPool::Process::Process(pid_t pid, int fd)
+ : pid_(pid), socket_(new Socket(fd)) {
+}
+
+pid_t ProcessPool::Process::GetPid() const {
+ return pid_;
+}
+
+int ProcessPool::Process::Send(const tizen_base::Parcel& parcel) {
+ _W("Send execution request. process ID: %d", pid_);
+ size_t data_size = parcel.GetDataSize();
+ int ret = socket_->Write(static_cast<void*>(&data_size), sizeof(data_size));
+ if (ret != 0) {
+ _E("Write() is failed. error(%d)", ret);
+ return ret;
+ }
+
+ return socket_->Write(parcel.GetData(), parcel.GetDataSize());
+}
+
+void ProcessPool::Process::Kill() {
+ socket_->Close();
+ if (kill(pid_, SIGKILL) == -1) {
+ _E("Failed to send kill signal to the process. pid(%d), errno(%d)",
+ pid_, errno);
+ }
+}
+
+void ProcessPool::OnExecution() {
+ _D("Candidate Process");
+ char** args = LaunchpadArgs::GetInst().GetArgs();
+ size_t length = strlen(args[0]);
+ memset(args[0], '\0', length);
+ snprintf(args[0], length, "/usr/bin/%s <%s>", kProcessPool, name_.c_str());
+
+ close(pipe_fd_[1]);
+ std::vector<int> except_fds = GetExceptableFds();
+ except_fds.push_back(pipe_fd_[0]);
+ Util::CloseAllFds(except_fds);
+ int ret = WaitForRequest(std::make_unique<Socket>(pipe_fd_[0]));
+ exit(ret);
+}
+
+void ProcessPool::PrepareProcess() {
+ int current_process_count = static_cast<int>(queue_.size());
+ for (int i = current_process_count; i < num_processes_; ++i) {
+ pipe_fd_[0] = -1;
+ pipe_fd_[1] = -1;
+ if (pipe(pipe_fd_) == -1) {
+ _E("Failed to create pipe. errno(%d)", errno);
+ return;
+ }
+
+ if (fcntl(pipe_fd_[0], F_SETPIPE_SZ, Socket::kSocketMaxBufferSize) == -1)
+ _E("Failed to set pipe size. errno(%d)", errno);
+
+ if (fcntl(pipe_fd_[1], F_SETPIPE_SZ, Socket::kSocketMaxBufferSize) == -1)
+ _E("Failed to set pipe size. errno(%d)", errno);
+
+ pid_t pid = Executor::Execute();
+ if (pid == -1) {
+ _E("Failed to fork process. errno(%d)", errno);
+ close(pipe_fd_[0]);
+ close(pipe_fd_[1]);
+ return;
+ }
+
+ close(pipe_fd_[0]);
+ queue_.push_back(std::make_shared<Process>(pid, pipe_fd_[1]));
+ }
+}
+
+int ProcessPool::WaitForRequest(std::unique_ptr<Socket> socket) {
+ tizen_base::Parcel parcel;
+ int ret = 0;
+ do {
+ size_t data_size = 0;
+ ret = socket->Read(static_cast<void*>(&data_size), sizeof(data_size));
+ if (ret != 0) {
+ _E("Failed to read from socket. error(%d)", ret);
+ return -1;
+ }
+
+ std::vector<uint8_t> data(data_size);
+ ret = socket->Read(data.data(), data.size());
+ if (ret != 0) {
+ _E("Failed to read from socket. error(%d)", ret);
+ return -1;
+ }
+
+ parcel.Write(data.data(), data.size());
+ } while (ret != 0);
+
+ if (event_listener_ != nullptr)
+ event_listener_->OnRequestReceived(&parcel);
+
+ return 0;
+}
+
+void ProcessPool::SetTimer() {
+ if (timer_ != 0)
+ return;
+
+ timer_ = g_timeout_add(1000, OnTimeout, this);
+}
+
+void ProcessPool::UnsetTimer() {
+ if (timer_ != 0) {
+ g_source_remove(timer_);
+ timer_ = 0;
+ }
+}
+
+gboolean ProcessPool::OnTimeout(gpointer user_data) {
+ auto* process_pool = static_cast<ProcessPool*>(user_data);
+ process_pool->PrepareProcess();
+ process_pool->timer_ = 0;
+ return G_SOURCE_REMOVE;
+}
+
+int ProcessPool::GetNumberOfProcesses() {
+ config_.Load();
+ return config_.GetNumberOfProcesses();
+}
+
+int ProcessPool::GetNumberOfLoaderProcesses() {
+ config_.Load();
+ return config_.GetNumberOfLoaderProcesses();
+}
+
+} // namespace launchpad
--- /dev/null
+/*
+ * Copyright (c) 2023 - 2024 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_CORE_PROCESS_POOL_HH_
+#define LIB_LAUNCHPAD_CORE_PROCESS_POOL_HH_
+
+#include <glib.h>
+#include <sys/types.h>
+
+#include <memory>
+#include <string>
+#include <vector>
+
+#include <executor.hh>
+#include <parcel.hh>
+#include <socket.hh>
+
+namespace launchpad {
+
+class ProcessPool : public Executor::Delegator,
+ public Executor {
+ public:
+ class IEvent {
+ public:
+ virtual ~IEvent() = default;
+ virtual void OnRequestReceived(tizen_base::Parcel* parcel) = 0;
+ };
+
+ explicit ProcessPool(std::string name, int num_processes,
+ IEvent* event_listener);
+ virtual ~ProcessPool();
+
+ bool IsPrepared() const;
+ pid_t Execute(const tizen_base::Parcel& parcel);
+ void Dispose();
+ void HandleSigchld(pid_t pid);
+ void SetTimer();
+
+ static int GetNumberOfProcesses();
+ static int GetNumberOfLoaderProcesses();
+
+ private:
+ class Process {
+ public:
+ Process(pid_t pid, int fd);
+
+ pid_t GetPid() const;
+ int Send(const tizen_base::Parcel& parcel);
+ void Kill();
+
+ private:
+ pid_t pid_;
+ std::unique_ptr<Socket> socket_;
+ };
+
+ void OnExecution() override;
+ void UnsetTimer();
+ void PrepareProcess();
+ int WaitForRequest(std::unique_ptr<Socket> socket);
+ static gboolean OnTimeout(gpointer user_data);
+
+ private:
+ std::string name_;
+ int num_processes_;
+ IEvent* event_listener_;
+ int pipe_fd_[2] = { -1, -1 };
+ std::vector<std::shared_ptr<Process>> queue_;
+ guint timer_ = 0;
+};
+
+} // namespace launchpad
+
+#endif // LIB_LAUNCHPAD_CORE_PROCESS_POOL_HH_
--- /dev/null
+/*
+ * Copyright (c) 2023 - 2024 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_CORE_REC_MUTEX_HH_
+#define LIB_LAUNCHPAD_CORE_REC_MUTEX_HH_
+
+#include <mutex>
+
+#undef EXPORT_API
+#define EXPORT_API __attribute__((visibility("default")))
+
+namespace launchpad {
+
+class EXPORT_API RecMutex {
+ public:
+ static RecMutex& GetInst() {
+ static RecMutex inst;
+ return inst;
+ }
+
+ std::recursive_mutex& GetMutex() const {
+ return mutex_;
+ }
+
+ private:
+ RecMutex() = default;
+ ~RecMutex() = default;
+
+ private:
+ mutable std::recursive_mutex mutex_;
+};
+
+} // namespace launchpad
+
+#endif // LIB_LAUNCHPAD_CORE_REC_MUTEX_HH_
--- /dev/null
+/*
+ * Copyright (c) 2024 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-core/sigchld_manager.hh"
+
+#include <signal.h>
+#include <sys/signalfd.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include "launchpad-core/log_private.hh"
+
+namespace {
+
+sigset_t mask_;
+sigset_t old_mask_;
+
+} // namespace
+
+namespace launchpad {
+
+int SigchldManager::BlockSigchld() {
+ sigemptyset(&mask_);
+ sigaddset(&mask_, SIGCHLD);
+ if (sigprocmask(SIG_BLOCK, &mask_, &old_mask_) < 0) {
+ int ret = -errno;
+ _E("sigprocmask(SIG_BLOCK) is failed. errno(%d)", errno);
+ return ret;
+ }
+
+ return 0;
+}
+
+void SigchldManager::UnblockSigchld() {
+ if (sigprocmask(SIG_SETMASK, &old_mask_, nullptr) < 0)
+ _E("sigprocmask(SIG_SETMASK) is failed. errno(%d)", errno);
+}
+
+int SigchldManager::GetSigchldFd() {
+ int sfd = signalfd(-1, &mask_, SFD_NONBLOCK | SFD_CLOEXEC);
+ if (sfd < 0) {
+ sfd = -errno;
+ _E("signalfd() is failed. errno(%d)", errno);
+ }
+
+ return sfd;
+}
+
+} // namespace launchpad
--- /dev/null
+/*
+ * Copyright (c) 2024 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_CORE_SIGCHLD_MANAGER_HH_
+#define LIB_LAUNCHPAD_CORE_SIGCHLD_MANAGER_HH_
+
+#undef EXPORT_API
+#define EXPORT_API __attribute__((visibility("default")))
+
+namespace launchpad {
+
+class EXPORT_API SigchldManager {
+ public:
+ static int BlockSigchld();
+ static void UnblockSigchld();
+ static int GetSigchldFd();
+};
+
+} // namespace launchpad
+
+#endif // LIB_LAUNCHPAD_CORE_SIGCHLD_MANAGER_HH_
\ No newline at end of file
#include <unistd.h>
#include <algorithm>
+#include <cctype>
#include <filesystem>
#include <fstream>
#include <memory>
+#include <regex>
#include <string>
#include <utility>
#include <vector>
return 0;
}
+std::vector<std::string> Util::Split(const std::string& str,
+ const std::string& delim) {
+ const std::regex deli("[^" + delim + "]+");
+ std::vector<std::string> result;
+ for (auto i = std::sregex_iterator(str.begin(), str.end(), deli);
+ i != std::sregex_iterator(); ++i)
+ result.push_back((*i).str());
+
+ return result;
+}
+
+std::string Util::ToUpper(std::string str) {
+ std::string result = std::move(str);
+ std::transform(result.begin(), result.end(), result.begin(), ::toupper);
+ return result;
+}
+
} // namespace launchpad
namespace launchpad {
+template <typename E>
+E operator|(E a, E b) {
+ return static_cast<E>(static_cast<int>(a) | static_cast<int>(b));
+}
+
+template <typename E>
+bool operator==(E a, int x) {
+ return static_cast<int>(a) == x;
+}
+
+template <typename E>
+int operator&(int a, E b) {
+ return a & static_cast<int>(b);
+}
+
class EXPORT_API Util {
public:
static void SetEnvironments(const AppInfo* app_info);
static int SendCmdToAmd(enum AmdCmd cmd);
static int SendCmdToAmd(enum AmdCmd cmd, bundle* request, int opt);
static int MountLibraryDirectories(const tizen_base::Bundle& b);
+ static std::vector<std::string> Split(const std::string& str,
+ const std::string& delim);
+ static std::string ToUpper(std::string str);
};
} // namespace launchpad
${CMAKE_CURRENT_SOURCE_DIR}/../../src/lib/common/inc
${CMAKE_CURRENT_SOURCE_DIR}/../../src/
${CMAKE_CURRENT_SOURCE_DIR}/../../src/lib/launchpad-common
+ ${CMAKE_CURRENT_SOURCE_DIR}/../../src/lib/launchpad-core
${CMAKE_CURRENT_SOURCE_DIR}/../../src/lib/launchpad-glib
)
SET_TARGET_PROPERTIES(${TARGET_LAUNCHPAD_PROCESS_POOL_UNITTEST}
PROPERTIES COMPILE_FLAGS "${EXTRA_CFLAGS}")
-TARGET_LINK_LIBRARIES(${TARGET_LAUNCHPAD_PROCESS_POOL_UNITTEST}
- PUBLIC ${TARGET_LAUNCHPAD_COMMON} ${TARGET_LAUNCHPAD_GLIB} "-ldl")
+TARGET_LINK_LIBRARIES(${TARGET_LAUNCHPAD_PROCESS_POOL_UNITTEST} PUBLIC
+ ${TARGET_LAUNCHPAD_COMMON} ${TARGET_LAUNCHPAD_CORE} ${TARGET_LAUNCHPAD_GLIB}
+ "-ldl")
INSTALL(TARGETS ${TARGET_LAUNCHPAD_PROCESS_POOL_UNITTEST} DESTINATION /usr/bin/)
#include <fstream>
#include <string>
-#include "launchpad-process-pool/debugger_info.hh"
-#include "launchpad-process-pool/launcher_info.hh"
-#include "launchpad-process-pool/loader_info.hh"
+#include "launchpad-core/debugger_info.hh"
+#include "launchpad-core/launcher_info.hh"
+#include "launchpad-core/loader_info.hh"
using ::testing::AtLeast;
using namespace launchpad;