- The lux is removed.
- The sub threads of the launchpad-process-pool are removed.
- Some features are moved to the amd.
Change-Id: Ic7ee8e73aa3a54aa09e330307f4a36f224b4b68b
Signed-off-by: Hwankyu Jhun <h.jhun@samsung.com>
SET(TARGET_LAUNCHPAD_PARSER "launchpad-parser")
SET(TARGET_LAUNCHPAD_PROCESS_POOL "launchpad-process-pool")
SET(TARGET_LAUNCHPAD_PROCESS_POOL_UNITTEST "launchpad-process-pool-unittest")
-SET(TARGET_LUX "lux")
SET(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH}
"${CMAKE_CURRENT_SOURCE_DIR}/cmake/Modules/")
BuildRequires: pkgconfig(ttrace)
BuildRequires: pkgconfig(vconf)
-BuildRequires: rust
-BuildRequires: rust-libc
-BuildRequires: rust-glib-sys
-BuildRequires: rust-tizen-bundle
-BuildRequires: rust-tizen-parcel
-
Requires(post): /sbin/ldconfig
Requires(post): /usr/bin/systemctl
Requires(postun): /sbin/ldconfig
Requires(posttrans): /usr/bin/echo
Requires(posttrans): /usr/bin/sed
-Requires: rust-std-shared
-Requires: rust-libc
-Requires: rust-glib-sys
-Requires: rust-tizen-bundle
-Requires: rust-tizen-parcel
-
Provides: app-launchpad
%define tizen_feature_priority_change 0
.
%__make %{?_smp_mflags}
-export LD_LIBRARY_PATH="./src/lib/launchpad-common/:./src/lib/launchpad-core"
-%{rustc_std_build} --crate-type=bin \
- --crate-name=%{real_crate_name} \
- -L native="./src/lib/launchpad-core" \
- -L native="./src/lib/launchpad-common" \
- -l "launchpad-core" \
- -l "launchpad-common" \
- %{?rustc_edition:--edition=%{rustc_edition}} \
- %rust_dylib_extern libc \
- ./src/lux/src/main.rs
-
%check
export LD_LIBRARY_PATH="../../src/lib/launchpad-common/:../../src/lib/launchpad-core"
ctest --verbose %{?_smp_mflags}
ln -sf ../launchpad-process-pool.socket %{buildroot}%{_userunitdir}/sockets.target.wants/launchpad-process-pool.socket
ln -sf ../launchpad-process-pool.service %{buildroot}%{_userunitdir}/basic.target.wants/launchpad-process-pool.service
-install -d -m 0755 %{buildroot}%{_bindir}
-install -m 0755 ./%{real_crate_name} %{buildroot}%{_bindir}/lux
-
%post
ln -sf /usr/bin/false /usr/bin/process-pool
%{_datadir}/parser-plugins/*
%attr(0644,root,root) %{_libdir}/liblaunchpad-common.so.*
%attr(0644,root,root) %{_libdir}/liblaunchpad-core.so.*
-%{_bindir}/lux
%files devel
%{_includedir}/launchpad/*.h
#include "launchpad-process-pool/config.hh"
#include "launchpad-process-pool/debug.hh"
#include "launchpad-process-pool/log_private.hh"
-#include "launchpad-process-pool/lux_manager.hh"
+#include "launchpad-process-pool/sigchld_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);
+}
+
void RemoveAulKeys(tizen_base::Bundle* b) {
b->Delete(kAulSdk);
b->Delete(kAulMountGlobalResDir);
} // namespace
-AppExecutor::AppExecutor() {
+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& config = Config::GetInst().GetProcessPool();
process_pool_ = std::unique_ptr<ProcessPool>(
- new ProcessPool("app", config.GetNumberOfProcesses()));
+ new ProcessPool("app", config.GetNumberOfProcesses(), this));
}
pid_t AppExecutor::Execute(const AppInfo* app_info) {
auto& b = const_cast<tizen_base::Bundle&>(app_info->GetBundle());
Debug::GetInst().PrepareDebugger(b);
-
- auto cloned_b = tizen_base::Bundle(b);
- RemoveAulKeys(&cloned_b);
- AddAulEnvKeys(&cloned_b);
- auto app_args =
- CreateAppArgv(app_info->GetAppPath(), cloned_b, app_info->GetAppType());
- b.Add(kAulAppArgs, app_args);
- b.Add(kAulLuxCmd, std::to_string(static_cast<int>(LuxCmd::ExecuteApp)));
-
- tizen_base::Parcel parcel = Util::CreateParcelFromBundle(&b);
if (process_pool_->IsPrepared()) {
+ tizen_base::Parcel parcel;
+ parcel.WriteParcelable(*app_info);
pid_t pid = process_pool_->Execute(parcel);
if (pid > 0) return pid;
}
- return LuxManager::GetInst().SendAndReceive(parcel);
+ app_info_ = app_info;
+ return Executor::Execute();
}
void AppExecutor::DisposeCandidateProcess() {
process_pool_->HandleSigchld(pid);
}
+
+void AppExecutor::OnExecution() {
+ UserTracer::Print(std::to_string(getpid()) + "|after calling fork(). " +
+ app_info_->GetAppId());
+ CheckAndPrepareDebugging();
+ SigchldManager::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);
+ }
+
+ auto cloned_b = tizen_base::Bundle(app_info_->GetBundle());
+ RemoveAulKeys(&cloned_b);
+ AddAulEnvKeys(&cloned_b);
+
+ std::vector<std::string> argv =
+ CreateAppArgv(app_info_->GetAppPath(), cloned_b, 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::GetInst().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& b = app_info_->GetBundle();
+ if (b.GetType(kAulSdk) != BUNDLE_TYPE_NONE)
+ Debug::GetInst().Prepare(b);
+
+ Debug::GetInst().CheckWebAppDebugging(b);
+}
+
LauncherInfoPtr AppExecutor::FindLauncherInfo(const std::string& app_type) {
for (auto& info : launcher_infos_) {
for (auto& type : info->GetAppTypes()) {
#include <bundle_cpp.h>
#include <functional>
-#include <memory>
#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"
-#undef EXPORT_API
-#define EXPORT_API __attribute__((visibility("default")))
-
namespace launchpad {
-class AppExecutor {
+class AppExecutor : public Executor::Delegator,
+ public Executor,
+ public ProcessPool::IEvent {
public:
AppExecutor();
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);
+ 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
+++ /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/dbus.hh"
-
-#include <gio/gio.h>
-#include <glib.h>
-
-#include <chrono>
-#include <memory>
-#include <shared-queue.hpp>
-#include <thread>
-#include <utility>
-
-#include "launchpad-process-pool/log_private.hh"
-
-namespace launchpad {
-namespace {
-
-constexpr const uint32_t ERROR_THRESHOLD = 10;
-constexpr const uint32_t ERROR_MODULO = 1000;
-constexpr const uint32_t PENDING_ITEM_INTERVAL = 1000;
-constexpr const char AUL_DBUS_PATH[] = "/aul/dbus_handler";
-constexpr const char AUL_DBUS_SIGNAL_INTERFACE[] = "org.tizen.aul.signal";
-constexpr const char AUL_DBUS_APPDEAD_SIGNAL[] = "app_dead";
-constexpr const char AUL_DBUS_APPLAUNCH_SIGNAL[] = "app_launch";
-
-class DBusMessage {
- public:
- DBusMessage(std::string path, std::string interface, std::string signal_name,
- GVariant* param, std::string log_message)
- : path_(std::move(path)),
- interface_(std::move(interface)),
- signal_name_(std::move(signal_name)),
- param_(param),
- log_message_(std::move(log_message)) {}
-
- explicit DBusMessage(bool done) : done_(done) {}
-
- ~DBusMessage() {
- if (param_ != nullptr) g_variant_unref(param_);
- }
-
- const std::string& GetPath() const { return path_; }
-
- const std::string& GetInterface() const { return interface_; }
-
- const std::string& GetSignalName() const { return signal_name_; }
-
- GVariant* RemoveParam() {
- GVariant* param = param_;
- param_ = nullptr;
- return param;
- }
-
- bool IsDone() const { return done_; }
-
- const std::string& GetLogMessage() const { return log_message_; }
-
- private:
- bool done_ = false;
- std::string path_;
- std::string interface_;
- std::string signal_name_;
- GVariant* param_ = nullptr;
- std::string log_message_;
-};
-
-class DBusManager {
- public:
- DBusManager(const DBusManager&) = delete;
- DBusManager& operator=(const DBusManager&) = delete;
- DBusManager(DBusManager&&) = delete;
- DBusManager& operator=(DBusManager&&) = delete;
-
- static DBusManager& GetInst() {
- static DBusManager inst;
- return inst;
- }
-
- void Dispose() {
- if (disposed_) return;
-
- if (getpid() == pid_) {
- queue_->Push(std::make_shared<DBusMessage>(true));
- thread_.join();
-
- if (conn_ != nullptr) {
- g_object_unref(conn_);
- conn_ = nullptr;
- }
-
- delete queue_;
- } else {
- thread_.detach();
- }
-
- disposed_ = true;
- }
-
- void Send(std::shared_ptr<DBusMessage> message) {
- queue_->Push(std::move(message));
- }
-
- void Init() {
- if (!disposed_) return;
-
- queue_ = new tizen_base::SharedQueue<std::shared_ptr<DBusMessage>>();
- thread_ = std::thread([&]() -> void { WorkerThread(); });
- disposed_ = false;
- }
-
- private:
- DBusManager() = default;
- ~DBusManager() { Dispose(); }
-
- GDBusConnection* GetConnection() {
- if (conn_) return conn_;
-
- GError* error = nullptr;
- conn_ = g_bus_get_sync(G_BUS_TYPE_SYSTEM, nullptr, &error);
- if (conn_ == nullptr) {
- error_count_++;
- if (error_count_ < ERROR_THRESHOLD || error_count_ % ERROR_MODULO == 0) {
- _E("g_bus_get_sync() is failed. error(%s)",
- error ? error->message : "Unknown");
- }
-
- g_clear_error(&error);
- return nullptr;
- }
-
- return conn_;
- }
-
- void EmitSignal(std::shared_ptr<DBusMessage> args) {
- GError* error = nullptr;
- if (!g_dbus_connection_emit_signal(conn_, nullptr, args->GetPath().c_str(),
- args->GetInterface().c_str(),
- args->GetSignalName().c_str(),
- args->RemoveParam(), &error)) {
- _E("g_dbus_connection_emit_signal() is failed. error(%s)",
- error ? error->message : "Unknown");
- g_clear_error(&error);
- return;
- }
-
- if (!g_dbus_connection_flush_sync(conn_, nullptr, &error)) {
- _E("g_dbus_connection_flush_sync() is failed. error(%s)",
- error ? error->message : "Unknown");
- g_clear_error(&error);
- return;
- }
-
- _E("[DBUS] %s", args->GetLogMessage().c_str());
- }
-
- void WorkerThread() {
- _W("BEGIN");
- while (true) {
- auto conn = GetConnection();
- if (conn == nullptr) {
- _W("Wait for dbus ready");
- std::this_thread::sleep_for(
- std::chrono::milliseconds(PENDING_ITEM_INTERVAL));
- continue;
- }
-
- auto message = queue_->WaitAndPop();
- if (message->IsDone()) break;
-
- EmitSignal(message);
- }
- _W("END");
- }
-
- private:
- bool disposed_ = true;
- pid_t pid_ = getpid();
- GDBusConnection* conn_ = nullptr;
- uint32_t error_count_ = 0;
- std::thread thread_;
- tizen_base::SharedQueue<std::shared_ptr<DBusMessage>>* queue_;
-};
-
-} // namespace
-
-void DBus::SendAppLaunchSignal(pid_t pid, const std::string_view appid) {
- DBusManager::GetInst().Send(std::make_shared<DBusMessage>(
- AUL_DBUS_PATH, AUL_DBUS_SIGNAL_INTERFACE, AUL_DBUS_APPLAUNCH_SIGNAL,
- g_variant_new("(us)", pid, appid.data()),
- "App Launch. " + std::to_string(pid) + ":" + std::string(appid)));
-}
-
-void DBus::SendAppDeadSignal(pid_t pid, int status) {
- DBusManager::GetInst().Send(std::make_shared<DBusMessage>(
- AUL_DBUS_PATH, AUL_DBUS_SIGNAL_INTERFACE, AUL_DBUS_APPDEAD_SIGNAL,
- g_variant_new("(ii)", pid, status),
- "App Dead. pid: " + std::to_string(pid) +
- ", status: " + std::to_string(status)));
-}
-
-void DBus::Init() { DBusManager::GetInst().Init(); }
-
-void DBus::Finish() { DBusManager::GetInst().Dispose(); }
-
-} // 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_DBUS_HH_
-#define LAUNCHPAD_PROCESS_POOL_DBUS_HH_
-
-#include <sys/types.h>
-#include <unistd.h>
-
-#include <string>
-
-namespace launchpad {
-
-class DBus {
- public:
- static void Init();
- static void Finish();
- static void SendAppLaunchSignal(pid_t pid, const std::string_view appid);
- static void SendAppDeadSignal(pid_t pid, int status);
-};
-
-} // namespace launchpad
-
-#endif // LAUNCHPAD_PROCESS_POOL_DBUS_HH_
#include <fstream>
#include <utility>
+#include <vector>
#include <aul_keys.hh>
#include <exception.hh>
constexpr const char kAsanAppListPath[] =
"/opt/usr/share/aul/debug/.asan_app_list";
constexpr const char kDebuggerInfoPath[] = "/usr/share/aul";
+constexpr const char kTizenAsanActivation[] = "TIZEN_ASAN_ACTIVATION";
+constexpr const char kDlpAttachArg[] = "__DLP_ATTACH_ARG__";
std::vector<std::string> GetStringArray(const tizen_base::Bundle& b,
const std::string& key) {
return values;
}
+pid_t GetCallerPid(const tizen_base::Bundle& b) {
+ auto pid_str = b.GetString(launchpad::kAulOrgCallerPid);
+ if (pid_str.empty()) pid_str = b.GetString(launchpad::kAulCallerPid);
+
+ if (pid_str.empty()) return -1;
+
+ return std::stoi(pid_str);
+}
+
+void 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);
+}
+
+void ParseAndSetEnvironment(const tizen_base::Bundle& b,
+ const std::string& key) {
+ _D("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("value: %s", env.c_str());
+ setenv(key.c_str(), env.c_str(), 1);
+}
+
+void ParseAndSetTargetPid(const tizen_base::Bundle& b) {
+ std::vector<std::string> values = GetStringArray(b, kDlpAttachArg);
+ if (values.empty()) return;
+
+ for (const auto& arg : values) {
+ if (isdigit(arg[0])) {
+ _D("TARGET_PID=%s", arg.c_str());
+ setenv("TARGET_PID", arg.c_str(), 1);
+ }
+ }
+}
+
} // namespace
Debug& Debug::GetInst() {
LoadAsanAppList();
}
+void Debug::Prepare(const tizen_base::Bundle& request) {
+ auto debugger = request.GetString(kAulSdk);
+ if (debugger.empty()) return;
+
+ if (debugger == "ASAN" ||
+ request.GetString(kAulTizenAsanActivation) == "true")
+ setenv(kTizenAsanActivation, "1", 1);
+
+ ParseAndRedirectStandardFds(request);
+
+ for (const auto& extra_env : request.GetStringArray(kAulDebugExtraEnvList))
+ ParseAndSetEnvironment(request, extra_env);
+
+ ParseAndSetTargetPid(request);
+}
+
+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& request) {
+ if (request.GetType(kAulDebug) != BUNDLE_TYPE_NONE)
+ setenv("TIZEN_DEBUGGING_PORT", "1", 1);
+}
+
} // namespace launchpad
std::vector<std::string> GetArgv() const;
bool ShouldAttach() const;
bool CheckAsanApp(const std::string& appid);
+ void Prepare(const tizen_base::Bundle& request);
+ void ChangeMountNamespace();
+ void CheckWebAppDebugging(const tizen_base::Bundle& request);
private:
Debug() = default;
#include <util.hh>
#include "launchpad-process-pool/config.hh"
-#include "launchpad-process-pool/dbus.hh"
#include "launchpad-process-pool/debug.hh"
#include "launchpad-process-pool/loader_manager.hh"
#include "launchpad-process-pool/log.hh"
#include "launchpad-process-pool/log_private.hh"
-#include "launchpad-process-pool/lux_manager.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/worker.hh"
namespace launchpad {
namespace {
const int kMaxPendingConnection = 128;
const uid_t kRegularUidMin = 5000;
-class CleanupInfo : public launchpad::Worker::Job {
- public:
- CleanupInfo(std::string appid, pid_t pid)
- : appid_(std::move(appid)), pid_(pid) {}
-
- void Do() override {
- _W("security_manager_cleanup_app() ++");
- security_manager_cleanup_app(appid_.c_str(), getuid(), pid_);
- _W("security_manager_cleanup_app() --");
- }
-
- private:
- std::string appid_;
- pid_t pid_;
-};
-
int GetLaunchpadFdFromSystemd() {
const std::string path = kRunAulDaemonsPath + std::to_string(getuid()) + "/" +
std::string(kLaunchpadProcessPoolSock);
this, std::placeholders::_1)},
{PadCmd::DisposeLoader, std::bind(&Launchpad::HandleDisposeLoaderRequest,
this, std::placeholders::_1)},
+ {PadCmd::ListenSigchld, std::bind(&Launchpad::HandleListenSigchldRequest,
+ this, std::placeholders::_1)},
};
CPUBoostController::Level level;
std::to_string(__LINE__) + ")");
launchpad::SignalManager::GetInst().SetEventListener(this);
LoaderManager::GetInst().SetEventListener(this);
- auto& lux_manager = launchpad::LuxManager::GetInst();
- lux_manager.Init();
- lux_manager.SetEventListener(this);
try {
app_executor_.reset(new AppExecutor());
return false;
}
- cleaner_.reset(new Worker("cleaner+"));
- DBus::Init();
-
LoaderManager::GetInst().AddDefaultLoaderContexts();
launchpad::Debug::GetInst().Init();
pid_map_.clear();
Util::SendCmdToAmd(AmdCmd::LaunchpadDeadSignal);
Debug::GetInst().Dispose();
- DBus::Finish();
- cleaner_.reset();
LoaderManager::GetInst().Dispose();
channel_.reset();
socket_.reset();
- launchpad::LuxManager::GetInst().Dispose();
SignalManager::GetInst().Dispose();
}
if (request->GetPid() > 0) {
auto* app_info = request->GetAppInfo();
- launchpad::DBus::SendAppLaunchSignal(request->GetPid(),
- app_info->GetAppId().c_str());
pid_map_[request->GetPid()] = app_info->GetAppId();
launchpad::Log::Print("[LAUNCH]", "pid(%7d) | appid(%s)", request->GetPid(),
app_info->GetAppId().c_str());
loader_context->GetLoaderName().c_str(), caller_pid);
}
+void Launchpad::HandleListenSigchldRequest(std::shared_ptr<Request> request) {
+ pid_t caller_pid = request->GetCallerPid();
+ uid_t caller_uid = request->GetCallerUid();
+ if (caller_uid >= kRegularUidMin) {
+ _E("Reject request. pid: %d, uid: %u", caller_pid, caller_uid);
+ request->SendResult(-1);
+ return;
+ }
+
+ auto* socket = request->GetClientSocket();
+ int fd = socket->RemoveFd();
+ sigchld_socket_.reset(new ClientSocket(fd));
+ _W("[PAD_CMD_LISTEN_SIGCHLD] pid: %d, uid: %u, fd: %d", caller_pid,
+ caller_uid, fd);
+}
+
void Launchpad::OnIOEventReceived(int fd, int condition) {
auto client_socket = socket_->Accept();
if (!client_socket) {
}
}
-void Launchpad::HandleSigchld(pid_t pid) {
+bool Launchpad::SendSigchldEvent(pid_t pid, int status) {
+ if (!sigchld_socket_) return false;
+
+ tizen_base::Parcel parcel;
+ parcel.WriteInt32(pid);
+ parcel.WriteInt32(status);
+ size_t data_size = parcel.GetDataSize();
+ int ret =
+ sigchld_socket_->Send(static_cast<void*>(&data_size), sizeof(data_size));
+ if (ret != 0) {
+ _E("Send() is failed. error=%d", ret);
+ sigchld_socket_.reset();
+ return false;
+ }
+
+ ret = sigchld_socket_->Send(parcel.GetData(), data_size);
+ if (ret != 0) {
+ _E("Send() is failed. error=%d", ret);
+ sigchld_socket_.reset();
+ return false;
+ }
+
+ return true;
+}
+
+void Launchpad::OnSigchldReceived(pid_t pid, int status) {
fast_launches_.erase(pid);
auto found = pid_map_.find(pid);
if (found != pid_map_.end()) {
auto appid = found->second;
- cleaner_->Add(std::make_shared<CleanupInfo>(std::move(appid), pid));
+ _E("pid=%d, appid=%s", pid, appid.c_str());
pid_map_.erase(found);
}
auto context = request->GetAvailableLoaderContext();
if (context != nullptr && request->GetPid() == pid) {
context->Unref();
- auto* app_info = request->GetAppInfo();
- launchpad::DBus::SendAppLaunchSignal(request->GetPid(),
- app_info->GetAppId().c_str());
pending_requests_.erase(iter);
break;
}
iter++;
}
- launchpad::Log::Print("[SIGCHLD]", "pid(%7d)", pid);
- LoaderManager::GetInst().HandleSigchld(pid);
- app_executor_->HandleSigchld(pid);
-}
+ auto it = pending_siginfos_.begin();
+ while (it != pending_siginfos_.end()) {
+ if (!SendSigchldEvent(it->first, it->second)) break;
-void Launchpad::OnSigchldReceived(pid_t pid) {
- HandleSigchld(pid);
- LuxManager::GetInst().HandleSigchld(pid);
-}
+ it = pending_siginfos_.erase(it);
+ }
-void Launchpad::OnLuxSigchld(pid_t pid, int status) {
- HandleSigchld(pid);
- SignalManager::GetInst().HandleSigchld(pid, status);
-}
+ if (!SendSigchldEvent(pid, status))
+ pending_siginfos_.emplace_back(pid, status);
-void Launchpad::OnLuxAppLabelsChanged() {
- LoaderManager::GetInst().HandleAppLabelsChanged();
+ launchpad::Log::Print("[SIGCHLD]", "pid(%7d)", pid);
+ LoaderManager::GetInst().HandleSigchld(pid);
+ app_executor_->HandleSigchld(pid);
}
void Launchpad::OnLoaderPrepared(LoaderContext* loader_context) {
#include <memory>
#include <string>
#include <unordered_map>
+#include <utility>
#include <vector>
#include <language_config.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/lux_manager.hh"
#include "launchpad-process-pool/request.hh"
#include "launchpad-process-pool/signal_manager.hh"
class Launchpad : public IOChannel::IEvent,
public SignalManager::IEvent,
- public LoaderManager::IEvent,
- public LuxManager::IEvent {
+ public LoaderManager::IEvent {
public:
enum class LaunchResult : int {
Fail = -1,
void HandleKillLoaderRequest(std::shared_ptr<Request> request);
void HandleRestartLoaderRequest(std::shared_ptr<Request> request);
void HandleDisposeLoaderRequest(std::shared_ptr<Request> request);
+ void HandleListenSigchldRequest(std::shared_ptr<Request> request);
bool CanUseLoaderContext(const std::shared_ptr<LoaderContext>& context);
LaunchResult ForkProcessing(std::shared_ptr<Request> request);
LaunchResult LaunchRequestDo(std::shared_ptr<Request> request);
LaunchResult LaunchRequestPend(std::shared_ptr<Request> request);
void LaunchRequestComplete(std::shared_ptr<Request> request);
- void HandleSigchld(pid_t pid);
+ bool SendSigchldEvent(pid_t pid, int status);
void OnIOEventReceived(int fd, int condition) override;
- void OnSigchldReceived(pid_t pid) override;
+ void OnSigchldReceived(pid_t pid, int status) override;
void OnLoaderPrepared(LoaderContext* loader_context) override;
void OnLoaderLaunched(LoaderContext* loader_context) override;
- void OnLuxSigchld(pid_t pid, int status) override;
- void OnLuxAppLabelsChanged() override;
private:
int argc_;
std::unordered_map<pid_t, std::string> pid_map_;
std::unique_ptr<LanguageConfig> lang_config_;
std::unique_ptr<RegionFormatConfig> region_format_config_;
- std::unique_ptr<Worker> cleaner_;
std::vector<std::shared_ptr<Request>> pending_requests_;
Config::LaunchMode::Mode mode_;
bool ping_received_ = false;
std::unordered_map<pid_t, std::string> fast_launches_;
+ std::unique_ptr<ClientSocket> sigchld_socket_;
+ std::vector<std::pair<pid_t, int>> pending_siginfos_;
};
} // namespace launchpad
#include "launchpad-process-pool/config.hh"
#include "launchpad-process-pool/log_private.hh"
-#include "launchpad-process-pool/lux_manager.hh"
+#include "launchpad-process-pool/sigchld_manager.hh"
namespace launchpad {
-LoaderExecutor::LoaderExecutor() {
+LoaderExecutor::LoaderExecutor() : Executor(this) {
auto& config = Config::GetInst().GetProcessPool();
process_pool_ = std::unique_ptr<ProcessPool>(
- new ProcessPool("loader", config.GetNumberOfLoaderProcesses()));
+ new ProcessPool("loader", config.GetNumberOfLoaderProcesses(), this));
}
LoaderExecutor& LoaderExecutor::GetInst() {
pid_t LoaderExecutor::Execute(const LoaderInfo* loader_info, int loader_id,
int priority) {
- auto loader_args = CreateLoaderArgv(loader_info, loader_id);
- tizen_base::Bundle b;
- b.Add(kAulLuxCmd, std::to_string(static_cast<int>(LuxCmd::ExecuteLoader)));
- b.Add("LOADER_ARGS", loader_args);
- b.Add("LOADER_PRIORITY", std::to_string(priority));
- auto parcel = Util::CreateParcelFromBundle(&b);
-
+ 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 = Util::CreateParcelFromBundle(&b);
pid_t pid = process_pool_->Execute(parcel);
if (pid > 0) return pid;
}
- return LuxManager::GetInst().SendAndReceive(parcel);
+ return Executor::Execute(priority);
}
bool LoaderExecutor::HasCandidateProcess() const {
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]);
+ }
+
+ SigchldManager::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 = Util::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::vector<std::string> argv(LoaderArg::Dummy + 1);
#include <vector>
#include "launchpad-process-pool/loader_info.hh"
+#include "launchpad-process-pool/executor.hh"
#include "launchpad-process-pool/process_pool.hh"
-#undef EXPORT_API
-#define EXPORT_API __attribute__((visibility("default")))
-
namespace launchpad {
-class EXPORT_API LoaderExecutor {
+class LoaderExecutor : public Executor::Delegator,
+ public Executor,
+ public ProcessPool::IEvent {
public:
LoaderExecutor(const LoaderExecutor&) = delete;
LoaderExecutor& operator=(const LoaderExecutor&) = delete;
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
RemoveLoaderContextsByCallerPid(pid);
LoaderExecutor::GetInst().HandleSigchld(pid);
- if (loader_mount_) loader_mount_->HandleSigchld(pid);
}
void LoaderManager::AddDefaultLoaderContexts() {
_W("END");
}
-void LoaderManager::OnAppLabelsChanged() {}
+void LoaderManager::OnAppLabelsChanged() { HandleAppLabelsChanged(); }
void LoaderManager::OnMemoryStatusChanged(bool low_memory,
bool should_check_pss) {
namespace fs = std::filesystem;
namespace {
-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;
-}
-
int ChangeMountNamespace(pid_t pid) {
std::string mnt_path = "/proc/" + std::to_string(pid) + "/ns/mnt";
int fd = open(mnt_path.c_str(), O_RDONLY);
return 0;
}
-class Request : public tizen_base::Parcelable {
- public:
- explicit Request(tizen_base::Parcel* parcel) { ReadFromParcel(parcel); }
-
- Request(pid_t pid, tizen_base::Bundle b) : pid_(pid), b_(std::move(b)) {}
-
- pid_t GetPid() const { return pid_; }
-
- const tizen_base::Bundle& GetBundle() const { return b_; }
-
- void WriteToParcel(tizen_base::Parcel* parcel) const override {
- parcel->WriteInt32(pid_);
- bundle_raw* raw = nullptr;
- int len = 0;
- bundle_encode(b_.GetHandle(), &raw, &len);
- parcel->WriteInt32(len);
- parcel->Write(reinterpret_cast<unsigned char*>(raw), len);
- bundle_free_encoded_rawdata(&raw);
- }
-
- void ReadFromParcel(tizen_base::Parcel* parcel) override {
- parcel->ReadInt32(&pid_);
- int len = 0;
- parcel->ReadInt32(&len);
- if (len > 0) {
- std::vector<uint8_t> data(len);
- parcel->Read(data.data(), data.size());
- b_ = tizen_base::Bundle(
- bundle_decode(reinterpret_cast<bundle_raw*>(data.data()), len), false,
- true);
- }
- }
-
- private:
- pid_t pid_;
- tizen_base::Bundle b_;
-};
-
-class Reply : public tizen_base::Parcelable {
- public:
- explicit Reply(tizen_base::Parcel* parcel) { ReadFromParcel(parcel); }
-
- explicit Reply(int result) : result_(result) {}
-
- int GetResult() const { return result_; }
-
- void WriteToParcel(tizen_base::Parcel* parcel) const override {
- parcel->WriteInt32(result_);
- }
-
- void ReadFromParcel(tizen_base::Parcel* parcel) override {
- parcel->ReadInt32(&result_);
- }
-
- private:
- int result_ = -1;
-};
-
} // namespace
namespace launchpad {
-LoaderMount::LoaderMount() : Executor(this), launchpad_ppid_(getppid()) {
- Prepare();
-}
-
-LoaderMount::~LoaderMount() { Dispose(); }
-
-void LoaderMount::Prepare() {
- if (pid_ > 0) return;
-
- int pipe_fd[2];
- if (CreatePipe(&pipe_fd) != 0) return;
+LoaderMount::LoaderMount() : launchpad_ppid_(getppid()) {}
- read_socket_.reset(new Socket(pipe_fd[0]));
- int write_fd = pipe_fd[1];
-
- if (CreatePipe(&pipe_fd) != 0) return;
-
- int read_fd = pipe_fd[0];
- write_socket_.reset(new Socket(pipe_fd[1]));
-
- _W("read_socket=%d, write_socket=%d", read_socket_->GetFd(),
- write_socket_->GetFd());
- pid_ = Executor::Execute();
- if (pid_ == -1) {
- _E("Failed to fork process. errno(%d)", errno);
- close(read_fd);
- close(write_fd);
- return;
- }
-
- read_socket_.reset(new Socket(read_fd));
- write_socket_.reset(new Socket(write_fd));
-}
-
-void LoaderMount::Dispose() {
- read_socket_.reset();
- write_socket_.reset();
- if (pid_ > 0) {
- if (kill(pid_, SIGKILL) == -1)
- _E("Failed to send kill signal. pid(%d), errno(%d)", pid_, errno);
-
- pid_ = -1;
- }
-}
-
-void LoaderMount::HandleSigchld(pid_t pid) {
- if (pid_ != pid) return;
-
- pid_ = -1;
- Dispose();
- Prepare();
-}
+LoaderMount::~LoaderMount() {}
int LoaderMount::Mount(pid_t pid, const AppInfo* app_info) {
auto& b = app_info->GetBundle();
b.GetType(kAulMountLibDir) == BUNDLE_TYPE_NONE)
return 0;
- tizen_base::Parcel parcel;
- Request request(pid, b);
- request.WriteToParcel(&parcel);
-
- _W("Send mount request");
- int ret = Write(parcel);
- if (ret != 0) return ret;
-
- parcel.Clear();
- ret = Read(&parcel);
- if (ret != 0) return ret;
-
- _W("receive result");
- Reply reply(&parcel);
- return reply.GetResult();
-}
-
-void LoaderMount::OnExecution() {
- _D("Mount Manager");
- char** args = LaunchpadArgs::GetInst().GetArgs();
- size_t length = strlen(args[0]);
- memset(args[0], '\0', length);
- snprintf(args[0], length, "/usr/bin/loader-mount");
-
- std::vector<int> except_fds = GetExceptableFds();
- except_fds.push_back(read_socket_->GetFd());
- except_fds.push_back(write_socket_->GetFd());
- Util::CloseAllFds(except_fds);
- int ret = ProcessRequests();
- exit(ret);
-}
-
-int LoaderMount::CreatePipe(int (*pipe_fd)[2]) {
- (*pipe_fd)[0] = -1;
- (*pipe_fd)[1] = -1;
-
- if (pipe(*pipe_fd) == -1) {
- _E("pipe() is failed. errno(%d)", errno);
- return -1;
- }
-
- if (fcntl((*pipe_fd)[0], F_SETPIPE_SZ, Socket::kSocketMaxBufferSize) == -1)
- _E("Failed to set pipe size. pipe_fd(%d), errno(%d)", (*pipe_fd)[0], errno);
-
- if (fcntl((*pipe_fd)[1], F_SETPIPE_SZ, Socket::kSocketMaxBufferSize) == -1)
- _E("Failed to set pipe size. pipe_fd(%d), errno(%d)", (*pipe_fd)[1], errno);
-
- return 0;
-}
-
-int LoaderMount::Write(const tizen_base::Parcel& parcel) {
- size_t data_size = parcel.GetDataSize();
- int ret =
- write_socket_->Write(static_cast<void*>(&data_size), sizeof(data_size));
- if (ret != 0) {
- _E("Write() is failed. error(%d)", ret);
- return -1;
- }
-
- return write_socket_->Write(parcel.GetData(), parcel.GetDataSize());
-}
-
-int LoaderMount::Read(tizen_base::Parcel* parcel) {
- size_t data_size = 0;
- int ret =
- read_socket_->Read(static_cast<void*>(&data_size), sizeof(data_size));
- if (ret != 0) {
- _E("Read() is failed. error(%d)", ret);
- return -1;
- }
-
- std::vector<uint8_t> data(data_size);
- ret = read_socket_->Read(data.data(), data.size());
- if (ret != 0) {
- _E("Read() is failed. error(%d)", ret);
- return -1;
- }
-
- parcel->Write(data.data(), data.size());
- return 0;
-}
-
-int LoaderMount::ProcessRequests() {
- tizen_base::Parcel parcel;
- while (true) {
- parcel.Clear();
- int ret = Read(&parcel);
- if (ret != 0) continue;
-
- _W("Request received");
- Request request(&parcel);
- ret = ChangeMountNamespace(request.GetPid());
- if (ret == 0) {
- auto& b = request.GetBundle();
- if (b.GetType(kAulMountGadgetPaths) != BUNDLE_TYPE_NONE)
- ret |= Util::MountGadgetDirectories(b);
- if (b.GetType(kAulMountLibDir) != BUNDLE_TYPE_NONE)
- ret |= Util::MountLibraryDirectories(b);
+ int ret = ChangeMountNamespace(pid);
+ if (ret == 0) {
+ if (b.GetType(kAulMountGadgetPaths) != BUNDLE_TYPE_NONE)
+ ret |= Util::MountGadgetDirectories(b);
+ if (b.GetType(kAulMountLibDir) != BUNDLE_TYPE_NONE)
+ ret |= Util::MountLibraryDirectories(b);
- ChangeMountNamespace(launchpad_ppid_);
- }
-
- Reply reply(ret);
- parcel.Clear();
- reply.WriteToParcel(&parcel);
- Write(parcel);
+ ChangeMountNamespace(launchpad_ppid_);
}
- return 0;
+ return ret;
}
} // namespace launchpad
#include <parcel.hh>
#include <socket.hh>
-#include "launchpad-process-pool/executor.hh"
-
namespace launchpad {
-class LoaderMount : public Executor::Delegator, public Executor {
+class LoaderMount {
public:
LoaderMount();
virtual ~LoaderMount();
- void Prepare();
- void Dispose();
- void HandleSigchld(pid_t pid);
-
int Mount(pid_t pid, const AppInfo* app_info);
- private:
- void OnExecution() override;
- int CreatePipe(int (*pipe_fd)[2]);
- int Write(const tizen_base::Parcel& parcel);
- int Read(tizen_base::Parcel* parcel);
- int ProcessRequests();
-
private:
pid_t launchpad_ppid_ = -1;
- pid_t pid_ = -1;
- std::unique_ptr<Socket> read_socket_;
- std::unique_ptr<Socket> write_socket_;
};
} // 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.
- */
-
-#include "launchpad-process-pool/lux_manager.hh"
-
-#include <fcntl.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-#include <cpu_boost_controller.hh>
-#include <exception.hh>
-#include <socket.hh>
-#include <peer_credentials.hh>
-#include <util.hh>
-#include <types.hh>
-
-#include "launchpad-process-pool/log_private.hh"
-
-namespace {
-
-constexpr const char kPathLux[] = "/usr/bin/lux";
-
-} // namespace
-
-namespace launchpad {
-
-LuxManager& LuxManager::GetInst() {
- static LuxManager inst;
- return inst;
-}
-
-void LuxManager::Init() {
- if (!disposed_) return;
-
- if (!Prepare()) return;
-
- disposed_ = false;
-}
-
-void LuxManager::Dispose() {
- if (disposed_) return;
-
- Kill();
- IgnoreEvents();
- ClosePipeFds();
- disposed_ = true;
-}
-
-bool LuxManager::PreparePipeFds() {
- read_fd_ = -1;
- write_fd_ = -1;
- sigchld_fd_ = -1;
- label_monitor_fd_ = -1;
-
- int pipe_fd[2];
- if (CreatePipe(&pipe_fd) != 0) return false;
-
- read_socket_.reset(new Socket(pipe_fd[0]));
- write_fd_ = pipe_fd[1];
-
- if (CreatePipe(&pipe_fd) != 0) {
- ClosePipeFds();
- return false;
- }
-
- read_fd_ = pipe_fd[0];
- write_socket_.reset(new Socket(pipe_fd[1]));
-
- if (CreatePipe(&pipe_fd) != 0) {
- ClosePipeFds();
- return false;
- }
-
- sigchld_fd_ = pipe_fd[0];
- sigchld_socket_.reset(new Socket(pipe_fd[1]));
-
- if (CreatePipe(&pipe_fd) != 0) {
- ClosePipeFds();
- return false;
- }
-
- label_monitor_fd_ = pipe_fd[0];
- label_monitor_socket_.reset(new Socket(pipe_fd[1]));
- return true;
-}
-
-void LuxManager::ClosePipeFds() {
- if (label_monitor_fd_ > -1) {
- close(label_monitor_fd_);
- label_monitor_fd_ = -1;
- }
-
- if (sigchld_fd_ > -1) {
- close(sigchld_fd_);
- sigchld_fd_ = -1;
- }
-
- if (read_fd_ > -1) {
- close(read_fd_);
- read_fd_ = -1;
- }
-
- if (write_fd_ > -1) {
- close(write_fd_);
- write_fd_ = -1;
- }
-
- label_monitor_socket_.reset();
- sigchld_socket_.reset();
- read_socket_.reset();
- write_socket_.reset();
-}
-
-bool LuxManager::ListenEvents() {
- try {
- sigchld_channel_.reset(new IOChannel(sigchld_socket_->GetFd(),
- IOChannel::IOCondition::IO_IN, this));
- label_monitor_channel_.reset(new IOChannel(
- label_monitor_socket_->GetFd(), IOChannel::IOCondition::IO_IN, this));
- } catch (const Exception& e) {
- _E("Exception occurs. error=%s", e.what());
- return false;
- }
-
- return true;
-}
-
-void LuxManager::IgnoreEvents() {
- sigchld_channel_.reset();
- label_monitor_channel_.reset();
-}
-
-bool LuxManager::Prepare() {
- if (pid_ > 0) return false;
-
- if (!PreparePipeFds()) return false;
-
- _W("read_socket=%d, write_socket=%d, sigchld_socket=%d, "
- "label_monitor_socket=%d",
- read_socket_->GetFd(), write_socket_->GetFd(), sigchld_socket_->GetFd(),
- label_monitor_socket_->GetFd());
- pid_ = Executor::Execute();
- if (pid_ < 0) {
- _E("Failed to execute lux. errno(%d)", errno);
- ClosePipeFds();
- return false;
- }
-
- _W("Lux process=%d", pid_);
- label_monitor_socket_.reset(new Socket(label_monitor_fd_));
- label_monitor_fd_ = -1;
- sigchld_socket_.reset(new Socket(sigchld_fd_));
- sigchld_fd_ = -1;
- read_socket_.reset(new Socket(read_fd_));
- read_fd_ = -1;
- write_socket_.reset(new Socket(write_fd_));
- write_fd_ = -1;
- return ListenEvents();
-}
-
-bool LuxManager::IsPrepared() const {
- return (pid_ > 0);
-}
-
-pid_t LuxManager::SendAndReceive(const tizen_base::Parcel& parcel) {
- _W("Send a request");
- size_t data_size = parcel.GetDataSize();
- int ret =
- write_socket_->Write(static_cast<void*>(&data_size), sizeof(data_size));
- if (ret != 0) {
- _E("Failed to write the data size. error=%d", ret);
- return ret;
- }
-
- ret = write_socket_->Write(parcel.GetData(), data_size);
- if (ret != 0) {
- _E("Failed to write the data. error=%d", ret);
- return ret;
- }
-
- pid_t pid = -1;
- ret = read_socket_->Read(static_cast<void*>(&pid), sizeof(pid));
- if (ret != 0) {
- _E("Failed to read the result. error=%d", ret);
- return ret;
- }
-
- return pid;
-}
-
-void LuxManager::HandleSigchld(pid_t pid) {
- if (pid_ != pid) return;
-
- IgnoreEvents();
- ClosePipeFds();
- pid_ = -1;
- Prepare();
-}
-
-void LuxManager::SetEventListener(IEvent* listener) { listener_ = listener; }
-
-LuxManager::LuxManager() : Executor(this) {}
-
-LuxManager::~LuxManager() { Dispose(); }
-
-int LuxManager::CreatePipe(int (*pipe_fd)[2]) {
- (*pipe_fd)[0] = -1;
- (*pipe_fd)[1] = -1;
-
- if (pipe(*pipe_fd) == -1) {
- _E("pipe() is failed. errno(%d)", errno);
- return -1;
- }
-
- if (fcntl((*pipe_fd)[0], F_SETPIPE_SZ, Socket::kSocketMaxBufferSize) == -1)
- _E("Failed to set pipe size. pipe_fd(%d), errno(%d)", (*pipe_fd)[0], errno);
-
- if (fcntl((*pipe_fd)[1], F_SETPIPE_SZ, Socket::kSocketMaxBufferSize) == -1)
- _E("Failed to set pipe size. pipe_fd(%d), errno(%d)", (*pipe_fd)[1], errno);
-
- return 0;
-}
-
-void LuxManager::Kill() {
- if (pid_ < 0) return;
-
- _W("Kill process=%d", pid_);
- if (kill(pid_, SIGKILL) != 0)
- _E("kill() is failed. pid=%d, errno=%d", pid_, errno);
-
- pid_ = -1;
-}
-
-void LuxManager::HandleSigChldEvent() {
- size_t data_size = 0;
- int ret =
- sigchld_socket_->Read(static_cast<void*>(&data_size), sizeof(data_size));
- if (ret != 0) {
- _E("Failed to receive the data. error=%d", ret);
- return;
- }
-
- std::vector<uint8_t> data(data_size);
- ret = sigchld_socket_->Read(data.data(), data_size);
- if (ret != 0) {
- _E("Failed to receive the data. error=%d", ret);
- return;
- }
-
- tizen_base::Parcel parcel(data.data(), data.size());
- pid_t pid = -1;
- parcel.ReadInt32(&pid);
- int status = 0;
- parcel.ReadInt32(&status);
- _W("[SIGCHLD] pid=%d, status=%d", pid, status);
- if (listener_) listener_->OnLuxSigchld(pid, status);
-}
-
-void LuxManager::HandleAppLabelsChangedEvent() {
- size_t data_size = 0;
- int ret = label_monitor_socket_->Read(static_cast<void*>(&data_size),
- sizeof(data_size));
- if (ret != 0) {
- _E("Failed to receive the data. error=%d", ret);
- return;
- }
-
- std::vector<uint8_t> data(data_size);
- ret = label_monitor_socket_->Read(data.data(), data_size);
- if (ret != 0) {
- _E("Failed to receive the data. error=%d", ret);
- return;
- }
-
- tizen_base::Parcel parcel(data.data(), data.size());
- parcel.ReadInt32(&ret);
- _W("[AppLabelsChanged] ret=%d", ret);
- if (listener_) listener_->OnLuxAppLabelsChanged();
-}
-
-void LuxManager::OnIOEventReceived(int fd, int condition) {
- _D("fd=%d, condition=%d", fd, condition);
- if (fd == sigchld_socket_->GetFd()) HandleSigChldEvent();
- else if (fd == label_monitor_socket_->GetFd()) HandleAppLabelsChangedEvent();
-}
-
-void LuxManager::OnExecution() {
- CPUBoostController::DoBoost(getpid(), CPUBoostController::Level::Strong, -1,
- true);
- std::vector<int> except_fds{read_socket_->GetFd(), write_socket_->GetFd(),
- sigchld_socket_->GetFd(),
- label_monitor_socket_->GetFd()};
- Util::CloseAllFds(except_fds);
-
- std::string rfd = std::to_string(read_socket_->RemoveFd());
- std::string wfd = std::to_string(write_socket_->RemoveFd());
- std::string sfd = std::to_string(sigchld_socket_->RemoveFd());
- std::string lfd = std::to_string(label_monitor_socket_->RemoveFd());
- setenv("LUX_READ_FD", rfd.c_str(), 1);
- setenv("LUX_WRITE_FD", wfd.c_str(), 1);
- setenv("LUX_SIGCHLD_FD", sfd.c_str(), 1);
- setenv("LUX_LABEL_MONITOR_FD", lfd.c_str(), 1);
-
- std::vector<char*> args;
- args.push_back(const_cast<char*>(kPathLux));
- args.push_back(nullptr);
-
- SECURE_LOGW("Execute Lux(%s)", kPathLux);
- int ret = execv(args[LoaderArg::Path], args.data());
- if (ret < 0) {
- char err_buf[1024];
- fprintf(stderr, "Failed to execute a file. path: %s, errno: %d(%s)\n",
- kPathLux, errno, strerror_r(errno, err_buf, sizeof(err_buf)));
- }
- exit(ret);
-}
-
-} // 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 LAUNCHPAD_PROCESS_POOL_LUX_MANAGER_HH_
-#define LAUNCHPAD_PROCESS_POOL_LUX_MANAGER_HH_
-
-#include <sys/types.h>
-#include <unistd.h>
-
-#include <memory>
-
-#include <socket.hh>
-#include <io_channel.hh>
-#include <parcel.hh>
-
-#include "launchpad-process-pool/executor.hh"
-
-namespace launchpad {
-
-class LuxManager : public IOChannel::IEvent,
- public Executor::Delegator,
- public Executor {
- public:
- class IEvent {
- public:
- virtual ~IEvent() = default;
- virtual void OnLuxSigchld(pid_t pid, int status) = 0;
- virtual void OnLuxAppLabelsChanged() = 0;
- };
-
- LuxManager(const LuxManager&) = delete;
- LuxManager& operator=(const LuxManager&) = delete;
- LuxManager(LuxManager&&) = delete;
- LuxManager& operator=(LuxManager&&) = delete;
-
- static LuxManager& GetInst();
-
- void Init();
- void Dispose();
- bool Prepare();
- bool IsPrepared() const;
- pid_t SendAndReceive(const tizen_base::Parcel& parcel);
- void HandleSigchld(pid_t pid);
- void SetEventListener(IEvent* listener);
-
- private:
- LuxManager();
- ~LuxManager();
-
- bool PreparePipeFds();
- void ClosePipeFds();
- bool ListenEvents();
- void IgnoreEvents();
- int CreatePipe(int (*pipe_fd)[2]);
- void Kill();
- void HandleServerEvent();
- void HandleClientEvent(int condition);
- void HandleSigChldEvent();
- void HandleAppLabelsChangedEvent();
- void OnIOEventReceived(int fd, int condition) override;
- void OnExecution() override;
-
- private:
- bool disposed_ = true;
- pid_t pid_ = -1;
- IEvent* listener_ = nullptr;
- std::unique_ptr<Socket> read_socket_;
- std::unique_ptr<Socket> write_socket_;
- std::unique_ptr<Socket> sigchld_socket_;
- std::unique_ptr<IOChannel> sigchld_channel_;
- std::unique_ptr<Socket> label_monitor_socket_;
- std::unique_ptr<IOChannel> label_monitor_channel_;
- int read_fd_ = -1;
- int write_fd_ = -1;
- int sigchld_fd_ = -1;
- int label_monitor_fd_ = -1;
-};
-
-} // namespace launchpad
-
-#endif // LAUNCHPAD_PROCESS_POOL_LUX_MANAGER_HH_
#include <utility>
#include <vector>
-#include <aul_keys.hh>
-#include <ini_parser.hh>
-#include <peer_credentials.hh>
-#include <socket.hh>
-#include <types.hh>
#include <util.hh>
+#include "launchpad-process-pool/launchpad_args.hh"
#include "launchpad-process-pool/log_private.hh"
-#include "launchpad-process-pool/lux_manager.hh"
namespace fs = std::filesystem;
+namespace launchpad {
namespace {
-constexpr const char kProcessPoolSock[] = ".process-pool-sock";
+constexpr const char kProcessPool[] = "process-pool";
-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;
+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;
}
-} // namespace
+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());
+ }
-namespace launchpad {
+ return fds;
+}
+
+} // namespace
-ProcessPool::ProcessPool(std::string name, int num_processes)
- : name_(std::move(name)), num_processes_(num_processes) {
- Listen();
+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(); }
+ProcessPool::~ProcessPool() {
+ Dispose();
+}
bool ProcessPool::IsPrepared() const {
- if (queue_.empty()) return false;
-
- auto process = queue_.front();
- return process->GetFd() > -1;
+ return !queue_.empty();
}
pid_t ProcessPool::Execute(const tizen_base::Parcel& parcel) {
SetTimer();
- if (!IsPrepared()) return -1;
+ if (!IsPrepared())
+ return -1;
auto process = std::move(queue_.front());
queue_.erase(queue_.begin());
- if (process->Send(parcel) < 0) return -1;
+ if (process->Send(parcel) < 0)
+ return -1;
return process->GetPid();
}
}
int current_process_count = static_cast<int>(queue_.size());
- if (current_process_count != num_processes_) SetTimer();
+ if (current_process_count != num_processes_)
+ SetTimer();
}
-ProcessPool::Process::Process(pid_t pid) : pid_(pid) {}
+ProcessPool::Process::Process(pid_t pid, int fd)
+ : pid_(pid), socket_(new Socket(fd)) {
+}
-pid_t ProcessPool::Process::GetPid() const { return pid_; }
+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 =
- client_socket_->Send(static_cast<void*>(&data_size), sizeof(data_size));
+ 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 client_socket_->Send(parcel.GetData(), parcel.GetDataSize());
+ return socket_->Write(parcel.GetData(), parcel.GetDataSize());
}
void ProcessPool::Process::Kill() {
- client_channel_.reset();
- client_socket_.reset();
+ socket_->Close();
if (kill(pid_, SIGKILL) == -1) {
- _E("Failed to send kill signal to the process. pid(%d), errno(%d)", pid_,
- errno);
+ _E("Failed to send kill signal to the process. pid(%d), errno(%d)",
+ pid_, errno);
}
}
-void ProcessPool::Process::SetClientSocket(
- std::unique_ptr<ClientSocket> client_socket) {
- client_socket_ = std::move(client_socket);
-}
-
-int ProcessPool::Process::GetFd() const {
- if (!client_socket_) return -1;
-
- return client_socket_->GetFd();
-}
-
-void ProcessPool::Process::Listen(IOChannel::IEvent* listener) {
- if (!client_socket_ || client_socket_->GetFd() < 0) return;
-
- client_channel_.reset(new IOChannel(client_socket_->GetFd(),
- IOChannel::IOCondition::IO_ERR |
- IOChannel::IOCondition::IO_HUP |
- IOChannel::IOCondition::IO_NVAL,
- listener));
+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() {
- tizen_base::Bundle envelope;
- envelope.Add(kAulLuxCmd,
- std::to_string(static_cast<int>(LuxCmd::ExecuteProcessPool)));
- envelope.Add(kAulProcessPoolName, name_);
- tizen_base::Parcel parcel = CreateParcelFromBundle(&envelope);
-
int current_process_count = static_cast<int>(queue_.size());
for (int i = current_process_count; i < num_processes_; ++i) {
- pid_t pid = LuxManager::GetInst().SendAndReceive(parcel);
- if (pid == -1) {
- _E("Failed to create process pool. error(%d)", pid);
+ pipe_fd_[0] = -1;
+ pipe_fd_[1] = -1;
+ if (pipe(pipe_fd_) == -1) {
+ _E("Failed to create pipe. errno(%d)", errno);
return;
}
- queue_.push_back(std::make_shared<Process>(pid));
- }
-}
-
-void ProcessPool::SetTimer() {
- if (timer_ != 0) return;
+ if (fcntl(pipe_fd_[0], F_SETPIPE_SZ, Socket::kSocketMaxBufferSize) == -1)
+ _E("Failed to set pipe size. errno(%d)", errno);
- timer_ = g_timeout_add(1000, OnTimeout, this);
-}
-
-void ProcessPool::UnsetTimer() {
- if (timer_ != 0) {
- g_source_remove(timer_);
- timer_ = 0;
- }
-}
+ if (fcntl(pipe_fd_[1], F_SETPIPE_SZ, Socket::kSocketMaxBufferSize) == -1)
+ _E("Failed to set pipe size. errno(%d)", errno);
-void ProcessPool::Listen() {
- try {
- std::string endpoint = "/run/aul/daemons/" + std::to_string(getuid()) +
- "/" + std::string(kProcessPoolSock) + "-" + name_;
- if (access(endpoint.c_str(), F_OK) == 0) unlink(endpoint.c_str());
-
- server_socket_.reset(new ServerSocket());
- server_socket_->Bind(endpoint);
- server_socket_->Listen(128);
-
- server_channel_.reset(new IOChannel(server_socket_->GetFd(),
- IOChannel::IOCondition::IO_IN, this));
- } catch (const Exception& e) {
- _E("Exception occurs. error=%s", e.what());
- THROW(e.GetErrorCode());
- }
-}
+ 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;
+ }
-std::shared_ptr<ProcessPool::Process> ProcessPool::Find(pid_t pid) {
- for (auto& process : queue_) {
- if (process->GetPid() == pid) return process;
+ close(pipe_fd_[0]);
+ queue_.push_back(std::make_shared<Process>(pid, pipe_fd_[1]));
}
-
- return nullptr;
}
-void ProcessPool::HandleClientEvent(int fd, int condition) {
- for (auto& process : queue_) {
- if (process->GetFd() == fd) {
- _E("socket was disconnected. pid=%d, fd=%d", process->GetPid(), fd);
+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;
}
- }
-}
-
-void ProcessPool::HandleServerEvent() {
- try {
- auto client_socket = server_socket_->Accept();
- client_socket->SetReceiveBufferSize(Socket::kSocketMaxBufferSize);
- pid_t pid = -1;
- int ret = client_socket->Receive(static_cast<void*>(&pid), sizeof(pid));
+ std::vector<uint8_t> data(data_size);
+ ret = socket->Read(data.data(), data.size());
if (ret != 0) {
- _E("Receive() is failed. error=%d", ret);
- return;
+ _E("Failed to read from socket. error(%d)", ret);
+ return -1;
}
- auto peer_cred = PeerCredentials::Get(client_socket->GetFd());
- if (peer_cred->GetPid() != pid) {
- _E("The peer information does not match. %d : %d", peer_cred->GetPid(),
- pid);
- return;
- }
+ parcel.Write(data.data(), data.size());
+ } while (ret != 0);
- auto process = Find(pid);
- if (process == nullptr) return;
+ if (event_listener_ != nullptr)
+ event_listener_->OnRequestReceived(&parcel);
+
+ return 0;
+}
- process->SetClientSocket(std::move(client_socket));
- process->Listen(this);
- } catch (const Exception& e) {
- _E("Exception occurs. error=%s", e.what());
+void ProcessPool::SetTimer() {
+ if (timer_ != 0)
return;
- }
+
+ timer_ = g_timeout_add(1000, OnTimeout, this);
}
-void ProcessPool::OnIOEventReceived(int fd, int condition) {
- if (server_socket_->GetFd() == fd) {
- HandleServerEvent();
- } else {
- HandleClientEvent(fd, condition);
+void ProcessPool::UnsetTimer() {
+ if (timer_ != 0) {
+ g_source_remove(timer_);
+ timer_ = 0;
}
}
#include <string>
#include <vector>
-#include <client_socket.hh>
-#include <io_channel.hh>
#include <parcel.hh>
-#include <server_socket.hh>
+#include <socket.hh>
+
+#include "launchpad-process-pool/executor.hh"
namespace launchpad {
-class ProcessPool : public IOChannel::IEvent {
+class ProcessPool : public Executor::Delegator,
+ public Executor {
public:
- explicit ProcessPool(std::string name, int num_processes);
+ 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;
private:
class Process {
public:
- explicit Process(pid_t pid);
+ Process(pid_t pid, int fd);
pid_t GetPid() const;
int Send(const tizen_base::Parcel& parcel);
void Kill();
- void SetClientSocket(std::unique_ptr<ClientSocket> client_socket);
- int GetFd() const;
- void Listen(IOChannel::IEvent* listener);
private:
pid_t pid_;
- std::unique_ptr<ClientSocket> client_socket_;
- std::unique_ptr<IOChannel> client_channel_;
+ std::unique_ptr<Socket> socket_;
};
- void Listen();
- std::shared_ptr<Process> Find(pid_t pid);
+ void OnExecution() override;
void UnsetTimer();
void PrepareProcess();
- void HandleClientEvent(int fd, int condition);
- void HandleServerEvent();
- void OnIOEventReceived(int fd, int condition) override;
-
+ int WaitForRequest(std::unique_ptr<Socket> socket);
static gboolean OnTimeout(gpointer user_data);
private:
std::string name_;
int num_processes_;
- guint timer_ = 0;
+ IEvent* event_listener_;
+ int pipe_fd_[2] = { -1, -1 };
std::vector<std::shared_ptr<Process>> queue_;
- std::unique_ptr<ServerSocket> server_socket_;
- std::unique_ptr<IOChannel> server_channel_;
+ guint timer_ = 0;
};
} // namespace launchpad
#endif // LAUNCHPAD_PROCESS_POOL_PROCESS_POOL_HH_
+
#include <string>
#include <vector>
-#include "launchpad-process-pool/dbus.hh"
#include "launchpad-process-pool/log_private.hh"
#include "launchpad-process-pool/sigchld_manager.hh"
namespace fs = std::filesystem;
-class GarbageCollector : public launchpad::Worker::Job {
+class GarbageCollector {
public:
explicit GarbageCollector(pid_t pid) : pid_(pid) {}
- void Do() override {
- _D("pid: %d", pid_);
- try {
- std::string path = "/run/aul/apps/" + std::to_string(getuid()) + "/" +
- std::to_string(pid_);
- DeleteSocketPath(fs::path(path));
-
- DeleteUnusedFiles();
- SocketGarbadgeCollector();
- } catch (const std::filesystem::filesystem_error& e) {
- _E("Exception occurs. error(%s:%d)", e.what(), e.code().value());
- }
- }
-
void DoAtFork() {
_W("pid: %d", pid_);
try {
for (int signo = 0; signo < _NSIG; ++signo) signal(signo, SIG_DFL);
#endif // PRELOAD_ACTIVATE
- recycle_bin_.reset();
hydra_sigchld_event_.reset();
sigchld_event_.reset();
pthread_atfork(nullptr, nullptr, nullptr);
sigchld_event_.reset(new SigchldEvent(sfd, this));
hydra_sigchld_event_.reset(new HydraSigchldEvent(this));
- recycle_bin_.reset(new Worker("RecycleBin+"));
for (int signo = 0; signo < _NSIG; ++signo) {
if (signo == SIGQUIT || signo == SIGILL || signo == SIGABRT ||
SignalManager::~SignalManager() { Dispose(); }
void SignalManager::HandleSigchld(pid_t pid, int status) {
- if (listener_ != nullptr) listener_->OnSigchldReceived(pid);
-
- DBus::SendAppDeadSignal(pid, status);
- recycle_bin_->Add(std::make_shared<GarbageCollector>(pid));
+ if (listener_ != nullptr) listener_->OnSigchldReceived(pid, status);
}
void SignalManager::OnSigchld(pid_t pid, int status) {
#include "launchpad-process-pool/hydra_sigchld_event.hh"
#include "launchpad-process-pool/sigchld_event.hh"
-#include "launchpad-process-pool/worker.hh"
namespace launchpad {
class IEvent {
public:
virtual ~IEvent() = default;
- virtual void OnSigchldReceived(pid_t pid) = 0;
+ virtual void OnSigchldReceived(pid_t pid, int status) = 0;
};
SignalManager(const SignalManager&) = delete;
void Dispose();
void SetEventListener(IEvent* listener);
- void HandleSigchld(pid_t pid, int status);
+ void UnblockSigchld();
private:
class SignalAction {
~SignalManager();
void Init();
+ void HandleSigchld(pid_t pid, int status);
void OnSigchld(pid_t pid, int status) override;
void OnHydraSigchld(pid_t pid, int status) override;
IEvent* listener_ = nullptr;
std::unique_ptr<SigchldEvent> sigchld_event_;
std::unique_ptr<HydraSigchldEvent> hydra_sigchld_event_;
- std::unique_ptr<Worker> recycle_bin_;
std::unordered_map<int, std::unique_ptr<SignalAction>> sigaction_map_;
};
+++ /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/worker.hh"
-
-#include <unistd.h>
-#include <sys/types.h>
-
-#include <fstream>
-
-#include <exception.hh>
-#include <procfs.hh>
-
-#include "launchpad-process-pool/log_private.hh"
-
-namespace launchpad {
-namespace {
-
-const pid_t current_pid = getpid();
-
-class Ender : public Worker::Job {
- public:
- bool IsDone() override { return true; }
-};
-
-} // namespace
-
-Worker::Worker(std::string name) : name_(std::move(name)) {
- queue_ = new tizen_base::SharedQueue<std::shared_ptr<Job>>();
- thread_ = std::thread([&]() -> void { RunThread(); });
-}
-
-Worker::~Worker() {
- if (getpid() == current_pid) {
- Add(std::make_shared<Ender>());
- thread_.join();
- delete queue_;
- } else {
- thread_.detach();
- }
-}
-
-void Worker::Add(std::shared_ptr<Worker::Job> job) {
- queue_->Push(std::move(job));
-}
-
-void Worker::RunThread() {
- _W("BEGIN");
- Procfs::SetComm(gettid(), name_);
- while (true) {
- auto job = queue_->WaitAndPop();
- job->Do();
- if (job->IsDone()) break;
- }
- _W("END");
-}
-
-} // 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_WORKER_HH_
-#define LAUNCHPAD_PROCESS_POOL_WORKER_HH_
-
-#include <memory>
-#include <string>
-#include <thread>
-#include <utility>
-
-#include <shared-queue.hpp>
-
-namespace launchpad {
-
-class Worker {
- public:
- class Job {
- public:
- virtual ~Job() = default;
- virtual void Do() {}
- virtual bool IsDone() { return false; }
- };
-
- explicit Worker(std::string name);
- virtual ~Worker();
-
- void Add(std::shared_ptr<Worker::Job> job);
-
- private:
- void RunThread();
-
- private:
- std::string name_;
- std::thread thread_;
- tizen_base::SharedQueue<std::shared_ptr<Job>>* queue_;
-};
-
-} // namespace launchpad
-
-#endif // LAUNCHPAD_PROCESS_POOL_WORKER_HH_
KillLoader = 19,
RestartLoader = 20,
DisposeLoader = 21,
+ ListenSigchld = 22,
};
enum PadLoaderId {
PATTERN "*.hh"
)
-INSTALL(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/include
- DESTINATION include/launchpad-core
- FILES_MATCHING
- PATTERN "*.h"
-)
-
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
+++ /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/app_executor_internal.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 <security-manager.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_internal.hh"
-#include "launchpad-core/log_private.hh"
-
-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
-
-namespace launchpad {
-namespace internal {
-namespace fs = std::filesystem;
-
-AppExecutor::AppExecutor() {
- 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));
-}
-
-void AppExecutor::Execute(tizen_base::Bundle request) {
- app_info_ = std::unique_ptr<AppInfo>(AppInfo::Create(std::move(request)));
- 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);
- }
-
- auto& b = app_info_->GetBundle();
- std::vector<std::string> argv = b.GetStringArray(kAulAppArgs);
- std::vector<char*> app_argv(argv.size());
- 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]);
- }
- app_argv.push_back(nullptr);
-
- 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.data()) < 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);
- }
-}
-
-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_.get());
-}
-
-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_.get());
-}
-
-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_.get());
- return 0;
-}
-
-int AppExecutor::StepWaitTepMount() {
- return Util::WaitTepMount(app_info_.get());
-}
-
-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_.get());
-}
-
-int AppExecutor::StepSendStartupSignal() {
- Util::SendCmdToAmd(AmdCmd::AppStartupSignal);
- return 0;
-}
-
-void AppExecutor::CheckAndPrepareDebugging() {
- auto& b = app_info_->GetBundle();
- if (b.GetType(kAulSdk) != BUNDLE_TYPE_NONE)
- Debug::Prepare(b);
-
- Debug::CheckWebAppDebugging(b);
-}
-
-} // namespace internal
-} // 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_APP_EXECUTOR_INTERNAL_HH_
-#define LIB_LAUNCHPAD_CORE_APP_EXECUTOR_INTERNAL_HH_
-
-#include <functional>
-#include <memory>
-#include <vector>
-
-#include <app_info.hh>
-#include <bundle_cpp.h>
-
-namespace launchpad {
-namespace internal {
-
-class AppExecutor {
- public:
- AppExecutor();
-
- void Execute(tizen_base::Bundle request);
-
- private:
- 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();
-
- private:
- using PrepareFunc = std::function<int()>;
-
- std::vector<PrepareFunc> prepare_funcs_;
- std::unique_ptr<AppInfo> app_info_;
-};
-
-} // namespace internal
-} // namespace launchpad
-
-#endif // LIB_LAUNCHPAD_CORE_APP_EXECUTOR_INTERNAL_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/debug_internal.hh"
-
-#include <fcntl.h>
-#include <stdio.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-#include <string>
-#include <vector>
-
-#include <aul_keys.hh>
-
-#include "launchpad-core/log_private.hh"
-
-namespace {
-
-constexpr const char kTizenAsanActivation[] = "TIZEN_ASAN_ACTIVATION";
-constexpr const char kDlpAttachArg[] = "__DLP_ATTACH_ARG__";
-
-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;
-}
-
-pid_t GetCallerPid(const tizen_base::Bundle& b) {
- auto pid_str = b.GetString(launchpad::kAulOrgCallerPid);
- if (pid_str.empty()) pid_str = b.GetString(launchpad::kAulCallerPid);
-
- if (pid_str.empty()) return -1;
-
- return std::stoi(pid_str);
-}
-
-void 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);
-}
-
-void ParseAndSetEnvironment(const tizen_base::Bundle& b,
- const std::string& key) {
- _D("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("value: %s", env.c_str());
- setenv(key.c_str(), env.c_str(), 1);
-}
-
-void ParseAndSetTargetPid(const tizen_base::Bundle& b) {
- std::vector<std::string> values = GetStringArray(b, kDlpAttachArg);
- if (values.empty()) return;
-
- for (const auto& arg : values) {
- if (isdigit(arg[0])) {
- _D("TARGET_PID=%s", arg.c_str());
- setenv("TARGET_PID", arg.c_str(), 1);
- }
- }
-}
-
-} // namespace
-
-namespace launchpad {
-namespace internal {
-
-void Debug::Prepare(const tizen_base::Bundle& request) {
- auto debugger = request.GetString(kAulSdk);
- if (debugger.empty()) return;
-
- if (debugger == "ASAN" ||
- request.GetString(kAulTizenAsanActivation) == "true")
- setenv(kTizenAsanActivation, "1", 1);
-
- ParseAndRedirectStandardFds(request);
-
- for (const auto& extra_env : request.GetStringArray(kAulDebugExtraEnvList))
- ParseAndSetEnvironment(request, extra_env);
-
- ParseAndSetTargetPid(request);
-}
-
-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& request) {
- if (request.GetType(kAulDebug) != BUNDLE_TYPE_NONE)
- setenv("TIZEN_DEBUGGING_PORT", "1", 1);
-}
-
-} // namespace internal
-} // 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_DEBUG_INTERNAL_HH_
-#define LIB_LAUNCHPAD_CORE_DEBUG_INTERNAL_HH_
-
-#include <bundle_cpp.h>
-
-namespace launchpad {
-namespace internal {
-
-class Debug {
- public:
- static void Prepare(const tizen_base::Bundle& request);
- static void ChangeMountNamespace();
- static void CheckWebAppDebugging(const tizen_base::Bundle& request);
-};
-
-} // namespace internal
-} // namespace launchpad
-
-#endif // LIB_LAUNCHPAD_CORE_DEBUG_INTERNAL_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 __LAUNCHPAD_CORE_H__
-#define __LAUNCHPAD_CORE_H__
-
-#include <bundle.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-void launchpad_core_execute_app(bundle *request);
-
-void launchpad_core_execute_process_pool(bundle *request);
-
-void launchpad_core_execute_loader(bundle *request);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* __LAUNCHPAD_CORE_H__ */
+++ /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/include/launchpad_core.h"
-
-#include <bundle.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-#include "launchpad-core/app_executor_internal.hh"
-#include "launchpad-core/loader_executor_internal.hh"
-#include "launchpad-core/log_private.hh"
-#include "launchpad-core/process_pool_internal.hh"
-
-#undef EXPORT
-#define EXPORT __attribute__((visibility("default")))
-
-#undef API
-#define API extern "C" EXPORT
-
-API void launchpad_core_execute_app(bundle* request) {
- tizen_base::Bundle b(request, false, false);
- launchpad::internal::AppExecutor executor;
- executor.Execute(std::move(b));
-}
-
-API void launchpad_core_execute_process_pool(bundle* request) {
- tizen_base::Bundle b(request, false, false);
- launchpad::internal::ProcessPool process_pool;
- process_pool.Execute(std::move(b));
-}
-
-API void launchpad_core_execute_loader(bundle* request) {
- tizen_base::Bundle b(request, false, false);
- launchpad::internal::LoaderExecutor executor;
- executor.Execute(std::move(b));
-}
+++ /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/loader_executor_internal.hh"
-
-#include <errno.h>
-#include <stdio.h>
-#include <unistd.h>
-
-#include <sched_priority.hh>
-#include <stdio.hh>
-#include <types.hh>
-#include <util.hh>
-
-#include "launchpad-core/log_private.hh"
-
-namespace launchpad {
-namespace internal {
-
-LoaderExecutor::LoaderExecutor() = default;
-
-void LoaderExecutor::Execute(tizen_base::Bundle request) {
- int priority = std::stoi(request.GetString("LOADER_PRIORITY"));
- if (priority != 0)
- SchedPriority::Set(priority);
-
- auto loader_args = request.GetStringArray("LOADER_ARGS");
- std::vector<char*> loader_argv(loader_args.size());
- int loader_argc = loader_argv.size();
- for (int i = 0; i < loader_argc; ++i) {
- loader_argv[i] = const_cast<char*>(loader_args[i].c_str());
- if ((i + 1) != loader_argc)
- SECURE_LOGD("loader argument %d : %s##", i, loader_argv[i]);
- }
- loader_argv.push_back(nullptr);
-
- 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);
- }
-}
-
-} // namespace internal
-} // 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 LAUNCHPAD_PROCESS_POOL_LOADER_EXECUTOR_INTERNAL_HH_
-#define LAUNCHPAD_PROCESS_POOL_LOADER_EXECUTOR_INTERNAL_HH_
-
-#include <sys/types.h>
-
-#include <bundle_cpp.h>
-
-namespace launchpad {
-namespace internal {
-
-class LoaderExecutor {
- public:
- LoaderExecutor();
-
- void Execute(tizen_base::Bundle request);
-};
-
-} // namespace internal
-} // namespace launchpad
-
-#endif // LAUNCHPAD_PROCESS_POOL_LOADER_EXECUTOR_INTERNAL_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/process_pool_internal.hh"
-
-#include <stdbool.h>
-#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 <pthread.h>
-
-#include <filesystem>
-#include <utility>
-#include <vector>
-
-#include <aul_keys.hh>
-#include <bundle_cpp.h>
-#include <socket.hh>
-#include <types.hh>
-#include <util.hh>
-
-#include "launchpad-core/app_executor_internal.hh"
-#include "launchpad-core/loader_executor_internal.hh"
-#include "launchpad-core/log_private.hh"
-
-namespace fs = std::filesystem;
-
-namespace {
-
-constexpr const char kProcessPoolSock[] = ".process-pool-sock";
-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;
-}
-
-void GetAndSetEnvironments(const tizen_base::Bundle& request) {
- auto lang = request.GetString(launchpad::kAulEnvLang);
- if (!lang.empty())
- setenv("LANG", lang.c_str(), 1);
-
- auto region_format = request.GetString(launchpad::kAulEnvRegionFormat);
- if (!region_format.empty())
- setenv("LC_CTYPE", region_format.c_str(), 1);
-}
-
-} // namespace
-
-namespace launchpad {
-namespace internal {
-
-ProcessPool::ProcessPool() {}
-
-void ProcessPool::Execute(tizen_base::Bundle request) {
- name_ = request.GetString(kAulProcessPoolName);
- _D("Candidate Process. name=%s", name_.c_str());
- std::string comm = std::string(kProcessPool) + "-" + name_;
- pthread_setname_np(pthread_self(), comm.c_str());
- std::vector<int> except_fds = GetExceptableFds();
- Util::CloseAllFds(except_fds);
- int ret = ConnectToServer();
- if (ret != 0) exit(ret);
-
- ret = WaitForRequest();
- exit(ret);
-}
-
-int ProcessPool::ConnectToServer() {
- try {
- std::string endpoint = "/run/aul/daemons/" + std::to_string(getuid()) +
- "/" + std::string(kProcessPoolSock) + "-" + name_;
- client_socket_.reset(new ClientSocket());
- client_socket_->Connect(endpoint);
- client_socket_->SetReceiveBufferSize(Socket::kSocketMaxBufferSize);
-
- pid_t pid = getpid();
- int ret = client_socket_->Send(static_cast<void*>(&pid), sizeof(pid));
- if (ret != 0) {
- _E("Send() is failed. error=%d", ret);
- return ret;
- }
- } catch (const Exception& e) {
- _E("Exception occurs. error=%s", e.what());
- return e.GetErrorCode();
- }
-
- return 0;
-}
-
-int ProcessPool::WaitForRequest() {
- tizen_base::Parcel parcel;
- size_t data_size = 0;
- int ret = client_socket_->Receive(static_cast<void*>(&data_size),
- sizeof(data_size));
- if (ret != 0) {
- _E("Receive() is failed. error=%d", ret);
- return -1;
- }
-
- std::vector<uint8_t> data(data_size);
- ret = client_socket_->Receive(data.data(), data.size());
- if (ret != 0) {
- _E("Receive() is failed. erorr=%d", ret);
- return -1;
- }
-
- parcel.Write(data.data(), data.size());
- tizen_base::Bundle request = Util::CreateBundleFromParcel(&parcel);
- auto cmd_str = request.GetString(kAulLuxCmd);
- _W("[%d] cmd=%s", getpid(), cmd_str.c_str());
- int cmd = std::stoi(cmd_str);
- switch (cmd) {
- case static_cast<int>(LuxCmd::ExecuteApp): {
- GetAndSetEnvironments(request);
- AppExecutor app_executor;
- app_executor.Execute(std::move(request));
- break;
- }
- case static_cast<int>(LuxCmd::ExecuteLoader): {
- LoaderExecutor loader_executor;
- loader_executor.Execute(std::move(request));
- break;
- }
- default: {
- _W("Unknown command=%s", cmd_str.c_str());
- exit(EXIT_FAILURE);
- }
- }
-
- return 0;
-}
-
-} // namespace internal
-} // 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_PROCESS_POOL_INTERNAL_HH_
-#define LIB_LAUNCHPAD_CORE_PROCESS_POOL_INTERNAL_HH_
-
-#include <glib.h>
-#include <sys/types.h>
-
-#include <memory>
-#include <string>
-
-#include <bundle_cpp.h>
-#include <client_socket.hh>
-
-namespace launchpad {
-namespace internal {
-
-class ProcessPool {
- public:
- ProcessPool();
-
- void Execute(tizen_base::Bundle request);
-
- private:
- int ConnectToServer();
- int WaitForRequest();
-
- private:
- std::string name_;
- std::unique_ptr<ClientSocket> client_socket_;
-};
-
-} // namespace internal
-} // namespace launchpad
-
-#endif // LIB_LAUNCHPAD_CORE_PROCESS_POOL_INTERNAL_HH_
+++ /dev/null
-[package]
-name = "lux"
-version = "0.1.0"
-edition = "2021"
-
-[dependencies]
-glib-sys = "0.20.2"
-libc = "0.2.158"
+++ /dev/null
-macro_rules! DLOG_DEBUG {
- () => {
- 3
- };
-}
-macro_rules! DLOG_INFO {
- () => {
- 4
- };
-}
-macro_rules! DLOG_WARN {
- () => {
- 5
- };
-}
-macro_rules! DLOG_ERROR {
- () => {
- 6
- };
-}
-
-macro_rules! DLOG {
- ($prio:expr, $($arg:tt)*) => {{
- use std::ffi::c_int;
-
- #[link(name = "dlog")]
- extern "C" {
- pub fn __dlog_print(
- log_id: c_int,
- ...
- ) -> c_int;
- }
-
- fn f() {}
- fn type_name_of<T>(_: T) -> &'static str {
- std::any::type_name::<T>()
- }
- let prio = $prio;
- let full_func_name = type_name_of(f).strip_suffix("::f").unwrap();
- let func_name = &full_func_name[full_func_name.rfind("::").unwrap()+2..];
- let file_path = std::path::PathBuf::from(file!());
- let file_name = file_path.file_name().unwrap().to_str().unwrap();
- let total_log = format!("{}: {}({}): {}\0", file_name, func_name, line!(), format_args!($($arg)*).to_string());
- unsafe { __dlog_print(0, prio, "Lux\0".as_ptr(), total_log.as_ptr()); }
- }}
-}
-
-macro_rules! debug { ($($arg:tt)*) => {{ DLOG!(DLOG_DEBUG!(), $($arg)*); }} }
-
-macro_rules! info { ($($arg:tt)*) => {{ DLOG!(DLOG_INFO!(), $($arg)*); }} }
-
-macro_rules! warn { ($($arg:tt)*) => {{ DLOG!(DLOG_WARN!(), $($arg)*); }} }
-
-macro_rules! error { ($($arg:tt)*) => {{ DLOG!(DLOG_ERROR!(), $($arg)*); }} }
+++ /dev/null
-extern crate glib_sys;
-extern crate libc;
-extern crate tizen_parcel;
-
-use glib_sys::*;
-use libc::*;
-use std::mem;
-use tizen_parcel::*;
-use std::ptr;
-
-const SECURITY_MANAGER_SUCCESS: i32 = 0;
-
-#[link(name="security-manager-client")]
-extern "C" {
- fn security_manager_app_labels_monitor_init(handle: *mut *mut c_void) -> c_int;
- fn security_manager_app_labels_monitor_process(handle: *mut c_void) -> c_int;
- fn security_manager_app_labels_monitor_get_fd(handle: *mut c_void, fd: *mut c_int) -> c_int;
- fn security_manager_app_labels_monitor_finish(handle: *mut c_void) -> c_int;
-}
-
-pub struct AppLabelsMonitor {
- handle: *mut c_void,
- source_id: c_uint,
- write_fd: i32,
- disposed: bool,
-}
-
-impl Drop for AppLabelsMonitor {
- fn drop(&mut self) {
- self.dispose();
- }
-}
-
-extern "C" fn app_labels_monitor_callback(
- fd: c_int,
- cond: c_uint,
- data: *mut c_void,
-) -> glib_sys::gboolean {
- unsafe {
- debug!("BEGIN");
- let handle: &mut AppLabelsMonitor = &mut *(data as *mut AppLabelsMonitor);
- handle.process();
- debug!("END");
- G_SOURCE_CONTINUE
- }
-}
-
-impl AppLabelsMonitor {
- pub fn new() -> Self {
- AppLabelsMonitor { handle: ptr::null_mut(), source_id: 0, write_fd: -1, disposed: true }
- }
-
- pub fn init(&mut self, write_fd: i32) -> Result<(), ()> {
- if !self.disposed {
- return Ok(());
- }
-
- self.write_fd = write_fd;
- let mut fd: i32 = -1;
- let ret = unsafe { security_manager_app_labels_monitor_init(&mut self.handle) };
- if ret != SECURITY_MANAGER_SUCCESS {
- error!("Failed to initialize app labels monitor. error={}", ret);
- return Err(());
- }
-
- let ret = unsafe { security_manager_app_labels_monitor_process(self.handle) };
- if ret != SECURITY_MANAGER_SUCCESS {
- error!("Failed to process app labels monitor. error={}", ret);
- unsafe { security_manager_app_labels_monitor_finish(self.handle) };
- return Err(());
- }
-
- let mut fd: i32 = -1;
- let ret = unsafe { security_manager_app_labels_monitor_get_fd(self.handle, &mut fd) };
- if ret != SECURITY_MANAGER_SUCCESS {
- error!("Failed to get file descriptor. error={}", ret);
- unsafe { security_manager_app_labels_monitor_finish(self.handle) };
- return Err(());
- }
-
- self.source_id = unsafe {
- g_unix_fd_add(
- fd,
- G_IO_IN,
- Some(app_labels_monitor_callback),
- self as *mut _ as *mut c_void
- )
- };
-
- self.disposed = false;
- Ok(())
- }
-
- pub fn dispose(&mut self) {
- if self.disposed {
- return;
- }
-
- if self.source_id != 0 {
- unsafe {
- g_source_remove(self.source_id);
- self.source_id = 0;
- }
- }
-
- if !self.handle.is_null() {
- unsafe {
- security_manager_app_labels_monitor_finish(self.handle);
- self.handle = ptr::null_mut();
- }
- }
-
- if self.write_fd > -1 {
- unsafe {
- close(self.write_fd);
- self.write_fd = -1;
- }
- }
-
- self.disposed = true;
- }
-
- fn process(&mut self) {
- let ret = unsafe { security_manager_app_labels_monitor_process(self.handle) };
- let mut parcel = Parcel::new();
- parcel.write_i32(ret as i32);
- self.write_parcel(&mut parcel);
- }
-
- fn write_parcel(&mut self, parcel: &mut Parcel) -> Result<(), ()> {
- let mut data = parcel.get_raw_data().unwrap();
- let mut data_size: c_ulong = (data.len() as usize).try_into().unwrap();
- let nbytes = unsafe {
- write(
- self.write_fd,
- (&mut data_size as *mut c_ulong).cast::<u8>() as *mut c_void,
- mem::size_of::<c_ulong>(),
- )
- };
- if nbytes < 0 {
- error!("Failed to write data size");
- return Err(());
- }
-
- let nbytes = unsafe { write(self.write_fd, data.as_mut_ptr() as *mut _, data.len()) };
- if nbytes < 0 {
- error!("Failed to write data");
- return Err(());
- }
-
- Ok(())
- }
-}
+++ /dev/null
-extern crate glib_sys;
-extern crate libc;
-
-use glib_sys::*;
-use libc::*;
-use std::env;
-use std::ffi::{c_char, c_void, CStr, CString};
-
-#[link(name = "vconf")]
-extern "C" {
- fn vconf_get_str(key: *const c_char) -> *mut c_char;
- fn vconf_notify_key_changed(
- key: *const c_char,
- callback: extern "C" fn(*mut c_void, *mut c_void),
- user_data: *mut c_void,
- ) -> c_int;
- fn vconf_ignore_key_changed(
- key: *const c_char,
- callback: extern "C" fn(*mut c_void, *mut c_void),
- ) -> c_int;
- fn vconf_keynode_get_str(keynode: *mut c_void) -> *mut c_char;
-}
-
-extern "C" fn language_changed_callback(keynode: *mut c_void, user_data: *mut c_void) {
- unsafe {
- let handle: &mut LanguageConfig = &mut *(user_data as *mut LanguageConfig);
- let value = vconf_keynode_get_str(keynode);
- if value.is_null() {
- error!("vconf_keynode_get_str() is failed");
- return;
- }
-
- let c_str = CStr::from_ptr(value);
- handle.lang = c_str.to_string_lossy().into_owned();
- env::set_var("LANG", handle.lang.clone());
- }
-}
-
-pub struct LanguageConfig {
- vconf_key: CString,
- lang: String,
-}
-
-impl Drop for LanguageConfig {
- fn drop(&mut self) {
- unsafe {
- vconf_ignore_key_changed(self.vconf_key.as_ptr(), language_changed_callback);
- }
- }
-}
-
-impl LanguageConfig {
- pub fn new() -> Self {
- let vconf_key = CString::new("db/menu_widget/language").unwrap();
- let lang = unsafe {
- let value: *mut c_char = vconf_get_str(vconf_key.as_ptr());
- if value.is_null() {
- panic!("Failed to get language");
- }
- let result = CString::from_raw(value).into_string().unwrap();
- env::set_var("LANG", result.clone());
- result
- };
- Self { vconf_key, lang }
- }
-
- pub fn listen(&mut self) {
- unsafe {
- vconf_notify_key_changed(
- self.vconf_key.as_ptr(),
- language_changed_callback,
- self as *mut _ as *mut c_void,
- );
- }
- }
-}
+++ /dev/null
-extern crate glib_sys;
-extern crate libc;
-extern crate tizen_bundle;
-extern crate tizen_parcel;
-
-mod app_labels_monitor;
-mod sigchld_manager;
-mod language_config;
-mod region_format_config;
-
-use glib_sys::*;
-use libc::*;
-use std::mem;
-use std::process;
-use tizen_bundle::*;
-use tizen_parcel::*;
-
-use self::app_labels_monitor::*;
-use self::sigchld_manager::*;
-use self::language_config::*;
-use self::region_format_config::*;
-
-const AUL_K_LUX_CMD: &str = "__AUL_LUX_CMD__";
-const LUX_CMD_EXECUTE_PROCESS_POOL: i32 = 0;
-const LUX_CMD_EXECUTE_APP: i32 = 1;
-const LUX_CMD_EXECUTE_LOADER: i32 = 2;
-
-#[link(name = "launchpad-core")]
-extern "C" {
- fn launchpad_core_execute_app(request: *mut c_void);
- fn launchpad_core_execute_process_pool(request: *mut c_void);
- fn launchpad_core_execute_loader(request: *mut c_void);
-}
-
-#[link(name = "security-manager-client")]
-extern "C" {
- fn security_manager_prepare_app_candidate() -> c_int;
-}
-
-#[repr(C)]
-pub struct ResourcePidInfo {
- pid: c_int,
- tid: *mut c_int,
- tid_count: c_int,
-}
-
-#[link(name = "capi-system-resource")]
-extern "C" {
- fn resource_clear_cpu_boosting(pid: ResourcePidInfo) -> c_int;
-}
-
-pub struct Lux {
- mainloop: *mut GMainLoop,
- language_config: LanguageConfig,
- region_format_config: RegionFormatConfig,
- app_labels_monitor: AppLabelsMonitor,
- sigchld_manager: SigchldManager,
- read_fd: i32,
- read_source_id: c_uint,
- write_fd: i32,
-}
-
-extern "C" fn g_unix_fd_func(fd: c_int, cond: c_uint, data: *mut c_void) -> glib_sys::gboolean {
- unsafe {
- let handle: &mut Lux = &mut *(data as *mut Lux);
- handle.handle_event_received();
- G_SOURCE_CONTINUE
- }
-}
-
-impl Drop for Lux {
- fn drop(&mut self) {
- if self.read_fd > -1 {
- unsafe {
- close(self.read_fd);
- self.read_fd = -1;
- }
- }
-
- if self.read_source_id != 0 {
- unsafe {
- g_source_remove(self.read_source_id);
- self.read_source_id = 0;
- }
- }
-
- if self.write_fd > -1 {
- unsafe {
- close(self.write_fd);
- self.write_fd = -1;
- }
- }
-
- if !self.mainloop.is_null() {
- unsafe {
- g_main_loop_unref(self.mainloop);
- self.mainloop = std::ptr::null_mut() as *mut GMainLoop;
- }
- }
- }
-}
-
-impl Lux {
- pub fn new() -> Self {
- Self {
- mainloop: unsafe { g_main_loop_new(g_main_context_default(), false as gboolean) },
- language_config: LanguageConfig::new(),
- region_format_config: RegionFormatConfig::new(),
- app_labels_monitor: AppLabelsMonitor::new(),
- sigchld_manager: SigchldManager::new(),
- read_fd: -1,
- read_source_id: 0,
- write_fd: -1,
- }
- }
-
- pub fn run(&mut self, read_fd: i32, write_fd: i32, sigchld_fd: i32, label_monitor_fd: i32) -> Result<(), ()> {
- self.read_fd = read_fd;
- self.write_fd = write_fd;
- self.sigchld_manager.init(sigchld_fd);
- self.read_source_id = unsafe {
- g_unix_fd_add(
- self.read_fd,
- G_IO_IN,
- Some(g_unix_fd_func),
- self as *mut _ as *mut c_void,
- )
- };
- if self.read_source_id == 0 {
- error!("g_unix_fd_add() is failed");
- return Err(());
- }
-
- self.app_labels_monitor.init(label_monitor_fd);
- self.region_format_config.listen();
- self.language_config.listen();
- self.clear_boosting();
- unsafe { g_main_loop_run(self.mainloop) }
- self.app_labels_monitor.dispose();
- Ok(())
- }
-
- pub fn quit(&mut self) {
- if !self.mainloop.is_null() {
- unsafe {
- g_main_loop_quit(self.mainloop);
- }
- }
- }
-
- fn handle_event_received(&mut self) {
- match self.read_parcel() {
- Ok(mut parcel) => {
- self.process_request(&mut parcel);
- }
- Err(_) => {
- error!("Error occurs");
- }
- }
- }
-
- fn process_request(&mut self, parcel: &mut Parcel) {
- let raw = parcel.read_string().unwrap();
- let mut envelope = Bundle::decode(&raw).unwrap();
- let pid = unsafe { fork() };
- if pid == 0 {
- unsafe { setsid() };
- self.sigchld_manager.unblock();
-
- let result = unsafe { security_manager_prepare_app_candidate() };
- if result != 0 {
- error!("Failed to prepare app candidate process. error={}", result);
- std::process::exit(1);
- }
-
- let cmd_str = envelope.get_str(AUL_K_LUX_CMD).unwrap();
- let cmd = cmd_str.parse().unwrap();
- match cmd {
- LUX_CMD_EXECUTE_PROCESS_POOL => unsafe {
- warn!("[EXECUTE_PROCESS_POOL]");
- launchpad_core_execute_process_pool(envelope.get_raw_handle())
- },
- LUX_CMD_EXECUTE_APP => unsafe {
- warn!("[EXECUTE_APP]");
- launchpad_core_execute_app(envelope.get_raw_handle())
- },
- LUX_CMD_EXECUTE_LOADER => unsafe {
- warn!("[EXECUTE_LOADER]");
- launchpad_core_execute_loader(envelope.get_raw_handle())
- },
- _ => panic!("Unexpected command {}", cmd),
- }
- } else {
- self.write_result(pid as i32);
- warn!("children process={}", pid);
- }
- }
-
- fn read_parcel(&mut self) -> Result<Parcel, ()> {
- let mut data_size: c_ulong = 0;
- let nbytes = unsafe {
- read(
- self.read_fd,
- (&mut data_size as *mut c_ulong).cast::<u8>() as *mut c_void,
- mem::size_of::<c_ulong>(),
- )
- };
- if nbytes <= 0 {
- error!("Failed to read data size");
- return Err(());
- }
-
- let mut data: Vec<u8> = vec![0; data_size as usize];
- let nbytes = unsafe { read(self.read_fd, data.as_mut_ptr() as *mut _, data.len()) };
- if nbytes <= 0 {
- error!("Failed to read data");
- return Err(());
- }
-
- let mut parcel = Parcel::new();
- parcel.write(data.as_ref()).unwrap();
- Ok(parcel)
- }
-
- fn write_result(&mut self, result: i32) -> Result<(), ()> {
- let mut data: i32 = result;
- let nbytes = unsafe {
- write(
- self.write_fd,
- (&mut data as *mut c_int).cast::<u8>() as *mut c_void,
- mem::size_of::<c_int>(),
- )
- };
- if nbytes < 0 {
- error!("Failed to write result");
- return Err(());
- }
-
- Ok(())
- }
-
- fn clear_boosting(&self) {
- let mut pid: c_int = process::id() as c_int;
- let mut resource_pid = ResourcePidInfo {
- pid: 0,
- tid: &mut pid,
- tid_count: 1,
- };
- unsafe { resource_clear_cpu_boosting(resource_pid); }
- }
-}
+++ /dev/null
-extern crate glib_sys;
-extern crate libc;
-
-use glib_sys::*;
-use libc::*;
-use std::env;
-use std::ffi::{c_char, c_void, CStr, CString};
-
-#[link(name = "vconf")]
-extern "C" {
- fn vconf_get_str(key: *const c_char) -> *mut c_char;
- fn vconf_notify_key_changed(
- key: *const c_char,
- callback: extern "C" fn(*mut c_void, *mut c_void),
- user_data: *mut c_void,
- ) -> c_int;
- fn vconf_ignore_key_changed(
- key: *const c_char,
- callback: extern "C" fn(*mut c_void, *mut c_void),
- ) -> c_int;
- fn vconf_keynode_get_str(keynode: *mut c_void) -> *mut c_char;
-}
-
-extern "C" fn region_format_changed_callback(keynode: *mut c_void, user_data: *mut c_void) {
- unsafe {
- let handle: &mut RegionFormatConfig = &mut *(user_data as *mut RegionFormatConfig);
- let value = vconf_keynode_get_str(keynode);
- if value.is_null() {
- error!("vconf_keynode_get_str() is failed");
- return;
- }
-
- let c_str = CStr::from_ptr(value);
- handle.region = c_str.to_string_lossy().into_owned();
- env::set_var("LC_CTYPE", handle.region.clone());
- }
-}
-
-pub struct RegionFormatConfig {
- vconf_key: CString,
- region: String,
-}
-
-impl Drop for RegionFormatConfig {
- fn drop(&mut self) {
- unsafe {
- vconf_ignore_key_changed(self.vconf_key.as_ptr(), region_format_changed_callback);
- }
- }
-}
-
-impl RegionFormatConfig {
- pub fn new() -> Self {
- let vconf_key = CString::new("db/menu_widget/regionformat").unwrap();
- let region = unsafe {
- let value: *mut c_char = vconf_get_str(vconf_key.as_ptr());
- if value.is_null() {
- panic!("Failed to get region format");
- }
- let result = CString::from_raw(value).into_string().unwrap();
- env::set_var("LC_CTYPE", result.clone());
- result
- };
- Self { vconf_key, region }
- }
-
- pub fn listen(&mut self) {
- unsafe {
- vconf_notify_key_changed(
- self.vconf_key.as_ptr(),
- region_format_changed_callback,
- self as *mut _ as *mut c_void,
- );
- }
- }
-}
+++ /dev/null
-extern crate glib_sys;
-extern crate libc;
-extern crate tizen_parcel;
-
-use glib_sys::*;
-use libc::*;
-use std::mem;
-use tizen_parcel::*;
-
-pub struct SigchldManager {
- mask: sigset_t,
- old_mask: sigset_t,
- sfd: i32,
- write_fd: i32,
- source_id: c_uint,
-}
-
-impl Drop for SigchldManager {
- fn drop(&mut self) {
- self.unblock();
- if self.sfd > -1 {
- unsafe {
- close(self.sfd);
- self.sfd = -1;
- }
- }
-
- if self.source_id != 0 {
- unsafe {
- g_source_remove(self.source_id);
- self.source_id = 0;
- }
- }
-
- if self.write_fd > -1 {
- unsafe {
- close(self.write_fd);
- self.write_fd = -1;
- }
- }
- }
-}
-
-extern "C" fn sigchld_event_callback(
- fd: c_int,
- cond: c_uint,
- data: *mut c_void,
-) -> glib_sys::gboolean {
- unsafe {
- let handle: &mut SigchldManager = &mut *(data as *mut SigchldManager);
- let mut info: signalfd_siginfo = std::mem::zeroed();
- let mut status: c_int = 0;
- let mut child_pid: pid_t;
- let nbytes = read(
- fd,
- (&mut info as *mut signalfd_siginfo).cast::<u8>() as *mut c_void,
- mem::size_of::<signalfd_siginfo>(),
- );
- if nbytes <= 0 {
- error!("Failed to read signchld info");
- return G_SOURCE_CONTINUE;
- }
-
- let child_pgid = getpgid(info.ssi_pid as i32);
- loop {
- child_pid = waitpid(-1, &mut status, WNOHANG);
- if child_pid <= 0 {
- break;
- }
-
- if child_pid == child_pgid {
- killpg(child_pgid, SIGKILL);
- }
-
- handle.handle_sigchld(child_pid, status);
- }
-
- G_SOURCE_CONTINUE
- }
-}
-
-impl SigchldManager {
- pub fn new() -> Self {
- unsafe {
- let mut mask: sigset_t = std::mem::zeroed();
- sigemptyset(&mut mask);
- let mut old_mask: sigset_t = std::mem::zeroed();
- sigemptyset(&mut old_mask);
- SigchldManager { mask, old_mask, sfd: -1, write_fd: -1, source_id: 0 }
- }
- }
-
- pub fn init(&mut self, write_fd: i32) {
- self.block().unwrap();
- self.write_fd = write_fd;
- self.sfd = self.get_fd();
- self.source_id = unsafe {
- g_unix_fd_add(
- self.sfd,
- G_IO_IN,
- Some(sigchld_event_callback),
- self as *mut _ as *mut c_void
- )
- };
- }
-
- fn block(&mut self) -> Result<(), ()> {
- let result = unsafe {
- sigaddset(&mut self.mask, libc::SIGCHLD);
- sigprocmask(SIG_BLOCK, &mut self.mask, &mut self.old_mask)
- };
- if result != 0 {
- Err(())
- } else {
- Ok(())
- }
- }
-
- pub fn unblock(&mut self) -> Result<(), ()> {
- let result = unsafe { sigprocmask(SIG_SETMASK, &mut self.old_mask, std::ptr::null_mut()) };
- if result != 0 {
- Err(())
- } else {
- Ok(())
- }
- }
-
- fn get_fd(&mut self) -> i32 {
- let result = unsafe { signalfd(-1, &mut self.mask, SFD_NONBLOCK | SFD_CLOEXEC) };
- result as i32
- }
-
- fn handle_sigchld(&mut self, pid: i32, status: i32) {
- error!("pid={}, status={}", pid, status);
- let mut parcel = Parcel::new();
- parcel.write_i32(pid);
- parcel.write_i32(status);
- self.write_parcel(&mut parcel);
- }
-
- fn write_parcel(&mut self, parcel: &mut Parcel) -> Result<(), ()> {
- let mut data = parcel.get_raw_data().unwrap();
- let mut data_size: c_ulong = (data.len() as usize).try_into().unwrap();
- let nbytes = unsafe {
- write(
- self.write_fd,
- (&mut data_size as *mut c_ulong).cast::<u8>() as *mut c_void,
- mem::size_of::<c_ulong>(),
- )
- };
- if nbytes < 0 {
- error!("Failed to write data size");
- return Err(());
- }
-
- let nbytes = unsafe { write(self.write_fd, data.as_mut_ptr() as *mut _, data.len()) };
- if nbytes < 0 {
- error!("Failed to write data");
- return Err(());
- }
-
- Ok(())
- }
-}
+++ /dev/null
-extern crate glib_sys;
-extern crate libc;
-
-#[macro_use]
-mod dlog_wrapper;
-mod lux;
-
-use lux::*;
-use std::env;
-use std::vec::Vec;
-
-fn main() {
- debug!("main");
- let read_fd = env::var("LUX_READ_FD")
- .ok()
- .and_then(|fd| fd.parse::<i32>().ok())
- .unwrap_or(-1);
- let write_fd = env::var("LUX_WRITE_FD")
- .ok()
- .and_then(|fd| fd.parse::<i32>().ok())
- .unwrap_or(-1);
- let sigchld_fd = env::var("LUX_SIGCHLD_FD")
- .ok()
- .and_then(|fd| fd.parse::<i32>().ok())
- .unwrap_or(-1);
- let label_monitor_fd = env::var("LUX_LABEL_MONITOR_FD")
- .ok()
- .and_then(|fd| fd.parse::<i32>().ok())
- .unwrap_or(-1);
-
- if read_fd < 0 || write_fd < 0 || sigchld_fd < 0 || label_monitor_fd < 0 {
- print!("Failed to find read/write fds. {read_fd} : {write_fd} : {sigchld_fd} : {label_monitor_fd}");
- std::process::exit(-1);
- }
-
- debug!("read_fd={}, write_fd={}, sigchld_fd={}, label_monitor_fd={}", read_fd, write_fd, sigchld_fd, label_monitor_fd);
- let mut lux = Lux::new();
- lux.run(read_fd, write_fd, sigchld_fd, label_monitor_fd);
-}