The launchpad worker is implemented using C++ language.
Change-Id: Ida9775036924f4e148ba5896433634fa20f52d5f
Signed-off-by: Hwankyu Jhun <h.jhun@samsung.com>
#include <vconf.h>
#include <algorithm>
+#include <string>
#include "launchpad-process-pool/debug.hh"
#include "launchpad-process-pool/launcher_info.hh"
#include "launchpad-process-pool/launchpad_io_channel.h"
#include "launchpad-process-pool/launchpad_memory_monitor.h"
#include "launchpad-process-pool/launchpad_signal.h"
-#include "launchpad-process-pool/launchpad_worker.h"
#include "launchpad-process-pool/loader_info.hh"
#include "launchpad-process-pool/slot_info.h"
#include "lib/common/inc/key.h"
#include "launchpad-process-pool/dbus.hh"
#include "launchpad-process-pool/log.hh"
+#include "launchpad-process-pool/worker.hh"
#define AUL_PR_NAME 16
#define EXEC_CANDIDATE_EXPIRED 5
namespace {
+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 __sys_hwacc;
std::unique_ptr<launchpad::LoaderInfoManager> loader_info_manager;
std::unique_ptr<launchpad::LoaderInfoManager> app_defined_loader_info_manager;
io_channel_h __label_monitor_channel;
io_channel_h __launchpad_channel;
int __client_fd = -1;
-worker_h __cleaner;
launchpad::AsanAppChecker __asan_app_checker;
+std::unique_ptr<launchpad::Worker> cleaner;
} // namespace
return true;
}
-static void __destroy_cleanup_info(struct cleanup_info_s* info) {
- if (!info)
- return;
-
- free(info->appid);
- free(info);
-}
-
-static struct cleanup_info_s* __create_cleanup_info(const char* appid,
- int pid) {
- struct cleanup_info_s* info;
-
- info = static_cast<cleanup_info_s*>(malloc(sizeof(struct cleanup_info_s)));
- if (!info) {
- _E("Out of memory");
- return nullptr;
- }
-
- info->appid = strdup(appid);
- if (!info->appid) {
- _E("strdup(%s) is failed", appid);
- __destroy_cleanup_info(info);
- return nullptr;
- }
-
- info->pid = pid;
-
- return info;
-}
-
-static bool __cleanup_app_cb(void* user_data) {
- struct cleanup_info_s* info = (struct cleanup_info_s*)user_data;
-
- _W("security_manager_cleanup_app() ++");
- security_manager_cleanup_app(info->appid, getuid(), info->pid);
- _W("security_manager_cleanup_app() --");
- __destroy_cleanup_info(info);
- return false;
-}
-
static void __handle_sigchild(int pid, void* user_data) {
- candidate_process_context_t* cpc;
- struct cleanup_info_s* info;
- char* appid;
- int ret = -1;
-
- appid = static_cast<char*>(
+ char* appid = static_cast<char*>(
g_hash_table_lookup(__pid_table, GINT_TO_POINTER(pid)));
if (appid) {
- info = __create_cleanup_info(appid, pid);
- if (info)
- ret = _worker_add_job(__cleaner, __cleanup_app_cb, info);
-
- if (ret != 0) {
- __destroy_cleanup_info(info);
- _W("security_manager_cleanup_app() ++");
- security_manager_cleanup_app(appid, getuid(), pid);
- _W("security_manager_cleanup_app() --");
- }
-
+ cleaner->Add(std::make_shared<CleanupInfo>(appid, pid));
g_hash_table_remove(__pid_table, GINT_TO_POINTER(pid));
}
launchpad::Log::Print("[SIGCHLD]", "pid(%7d)", pid);
- cpc = __find_slot_from_pid(pid);
+ candidate_process_context_t* cpc = __find_slot_from_pid(pid);
if (cpc != nullptr) {
cpc->pid = CANDIDATE_NONE;
__dispose_candidate_process(cpc);
return -1;
}
- ret = _worker_create("cleaner+", &__cleaner);
- if (ret < 0)
- return ret;
-
__register_vconf_events();
__init_app_defined_loader_monitor();
+ cleaner.reset(new launchpad::Worker("cleaner+"));
launchpad::Log::Init();
_print_hwc_log("%s(%d): END", __FUNCTION__, __LINE__);
-
return 0;
}
static void __after_loop(void) {
launchpad::Log::Finish();
+ cleaner.reset();
_memory_monitor_fini();
__unregister_vconf_events();
- _worker_destroy(__cleaner);
if (__pid_table)
g_hash_table_destroy(__pid_table);
#include <sys/wait.h>
#include <unistd.h>
+#include <filesystem>
+#include <memory>
#include <string>
#include <vector>
#include "launchpad-process-pool/launchpad_io_channel.h"
-#include "launchpad-process-pool/launchpad_worker.h"
#include "lib/common/inc/launchpad_common.h"
#include "lib/common/inc/launchpad_proc.h"
#include "lib/common/inc/launchpad_socket.h"
#include "lib/common/inc/log_private.h"
#include "launchpad-process-pool/dbus.hh"
+#include "launchpad-process-pool/log_private.hh"
+#include "launchpad-process-pool/worker.hh"
+
+namespace fs = std::filesystem;
namespace {
constexpr const char HYDRA_SIGCHLD_SOCK[] = ".hydra-sigchld-sock";
+class GarbageCollector : public launchpad::Worker::Job {
+ public:
+ explicit GarbageCollector(pid_t pid) : pid_(pid) {}
+
+ void Do() override {
+ _W("pid: %d", pid_);
+ _delete_sock_path(pid_, getuid());
+ DeleteUnusedFiles();
+ SocketGarbadgeCollector();
+ }
+
+ private:
+ void SocketGarbadgeCollector() {
+ std::string path = "/run/aul/apps/" + std::to_string(getuid());
+ for (const auto &entry : fs::directory_iterator(path)) {
+ if (!isdigit(entry.path().filename().string()[0]))
+ continue;
+
+ std::string proc_path = "/proc/" + entry.path().filename().string();
+ if (access(proc_path.c_str(), F_OK) < 0) {
+ _delete_sock_path(atoi(entry.path().filename().string().c_str()),
+ getuid());
+ }
+ }
+ }
+
+ void DeleteUnusedFiles() {
+ std::vector<std::string> files = {
+ "clr-debug-pipe-" + std::to_string(pid_) + "-",
+ "dotnet-diagnostic-" + std::to_string(pid_) + "-"
+ };
+
+ fs::path tmp_path = "/tmp";
+ for (const auto &entry : fs::directory_iterator(tmp_path)) {
+ if (entry.is_directory() || entry.path().filename().string()[0] == '.')
+ continue;
+
+ bool found = false;
+ for (const auto &file : files) {
+ if (entry.path().filename().string().find(file) == 0) {
+ fs::remove(entry.path());
+ _W("Removed file: %s", entry.path().c_str());
+ found = true;
+ break;
+ }
+ }
+
+ if (!found)
+ continue;
+ }
+ }
+
+ private:
+ pid_t pid_;
+};
+
pid_t __pid;
sigset_t __mask;
sigset_t __old_mask;
signal_sigchld_cb __callback;
void* __user_data;
-worker_h recycle_bin;
+std::unique_ptr<launchpad::Worker> recycle_bin;
} // namespace
static gboolean __hydra_sigchld_recovery_cb(gpointer data);
static gboolean __sigchld_recovery_cb(gpointer data);
-static void __socket_garbage_collector(void) {
- DIR* dp;
- struct dirent* dentry = nullptr;
- char path[PATH_MAX];
-
- snprintf(path, sizeof(path), "/run/aul/apps/%d", getuid());
- dp = opendir(path);
- if (!dp)
- return;
-
- while ((dentry = readdir(dp)) != nullptr) {
- if (!isdigit(dentry->d_name[0]))
- continue;
-
- snprintf(path, sizeof(path), "/proc/%s", dentry->d_name);
- if (access(path, F_OK) < 0)
- _delete_sock_path(atoi(dentry->d_name), getuid());
- }
- closedir(dp);
-}
-
-static void __delete_unused_files(pid_t pid) {
- std::vector<std::string> files = {
- "clr-debug-pipe-" + std::to_string(pid) + "-",
- "dotnet-diagnostic-" + std::to_string(pid) + "-"
- };
-
- DIR* dp = opendir("/tmp");
- if (dp == nullptr) {
- _E("opendir() is failed");
- return;
- }
-
- struct dirent* dentry = nullptr;
- while ((dentry = readdir(dp)) != nullptr) {
- if (dentry->d_name[0] == '.')
- continue;
-
- if (dentry->d_name[0] != 'c' && dentry->d_name[0] != 'd')
- continue;
-
- for (size_t i = 0; i < files.size(); ++i) {
- if (files[i].compare(0, files[i].length(), dentry->d_name, 0,
- files[i].length()) == 0) {
- std::string path = std::string("/tmp/") + dentry->d_name;
- unlink(path.c_str());
- _W("unlink(%s)", path.c_str());
- }
- }
- }
- closedir(dp);
-}
-
-static bool __garbage_collector(void *user_data) {
- pid_t pid = GPOINTER_TO_INT(
- reinterpret_cast<unsigned long>(user_data) & UINT32_MAX);
- _W("pid(%d)", pid);
- _delete_sock_path(pid, getuid());
- __delete_unused_files(pid);
- __socket_garbage_collector();
- return false;
-}
-
static void __sigchld_action(int pid) {
launchpad::DBus::SendAppDeadSignal(pid);
- _worker_add_job(recycle_bin, __garbage_collector, GINT_TO_POINTER(pid));
+ recycle_bin->Add(std::make_shared<GarbageCollector>(pid));
}
static int __check_permission(int pid) {
}
}
- ret = _worker_create("RecycleBin+", &recycle_bin);
- if (ret < 0) {
- _E("_worker_create() is failed");
- return ret;
- }
-
+ recycle_bin.reset(new launchpad::Worker("RecycleBin+"));
return 0;
}
#endif
_D("SIGNAL_FINI");
- if (getpid() == __pid)
- _worker_destroy(recycle_bin);
-
+ recycle_bin.reset();
_signal_set_sigchld_cb(nullptr, nullptr);
__hydra_sigchld_fini();
__sigchld_fini();
+++ /dev/null
-/*
- * Copyright (c) 2020 Samsung Electronics Co., Ltd All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "launchpad-process-pool/launchpad_worker.h"
-
-#include <errno.h>
-#include <fcntl.h>
-#include <glib.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/stat.h>
-#include <sys/syscall.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-#include "lib/common/inc/log_private.h"
-
-struct job_s {
- worker_job_cb callback;
- void* user_data;
-};
-
-struct worker_s {
- char* name;
- GThread* thread;
- GMutex mutex;
- GCond cond;
- GQueue* queue;
-};
-
-int _worker_add_job(worker_h worker, worker_job_cb callback, void* user_data) {
- struct job_s* job;
-
- if (!worker || !callback) {
- _E("Invalid parameter");
- return -EINVAL;
- }
-
- job = static_cast<job_s*>(malloc(sizeof(job_s)));
- if (!job) {
- _E("Out of memory");
- return -ENOMEM;
- }
-
- job->callback = callback;
- job->user_data = user_data;
-
- g_mutex_lock(&worker->mutex);
- g_queue_push_tail(worker->queue, job);
- g_cond_signal(&worker->cond);
- g_mutex_unlock(&worker->mutex);
-
- return 0;
-}
-
-static int __set_comm(const char* name) {
- int fd;
- ssize_t bytes_written;
- char path[PATH_MAX];
- pid_t tid = syscall(__NR_gettid);
-
- _I("[%s] TID(%d)", name, tid);
- snprintf(path, sizeof(path), "/proc/%d/comm", tid);
- fd = open(path, O_WRONLY);
- if (fd < 0) {
- _E("Failed to open %s. error(%d)", path, errno);
- return -1;
- }
-
- bytes_written = write(fd, name, strlen(name) + 1);
- if (bytes_written < 0) {
- _E("Failed to write name(%s)", name);
- close(fd);
- return -1;
- }
-
- close(fd);
- return 0;
-}
-
-static gpointer __worker_thread_cb(gpointer data) {
- struct worker_s* worker = (struct worker_s*)data;
- struct job_s* job;
- bool done = false;
-
- __set_comm(worker->name);
- do {
- g_mutex_lock(&worker->mutex);
- if (g_queue_is_empty(worker->queue))
- g_cond_wait(&worker->cond, &worker->mutex);
-
- job = (struct job_s*)g_queue_pop_head(worker->queue);
- g_mutex_unlock(&worker->mutex);
- done = job->callback(job->user_data);
- free(job);
- } while (!done);
-
- return NULL;
-}
-
-int _worker_create(const char* name, worker_h* worker) {
- struct worker_s* handle;
-
- if (name == NULL || worker == NULL) {
- _E("Invalid parameter");
- return -EINVAL;
- }
-
- handle = static_cast<worker_s*>(calloc(1, sizeof(worker_s)));
- if (handle == NULL) {
- _E("calloc() is failed");
- return -ENOMEM;
- }
-
- g_mutex_init(&handle->mutex);
- g_cond_init(&handle->cond);
-
- handle->name = strdup(name);
- if (!handle->name) {
- _E("strdup() is failed");
- _worker_destroy(handle);
- return -ENOMEM;
- }
-
- handle->queue = g_queue_new();
- if (!handle->queue) {
- _E("g_queue_new() is failed");
- _worker_destroy(handle);
- return -ENOMEM;
- }
-
- handle->thread = g_thread_new(name, __worker_thread_cb, handle);
- if (!handle->thread) {
- _E("g_thread_new() is failed");
- _worker_destroy(handle);
- return -ENOMEM;
- }
-
- *worker = handle;
- return 0;
-}
-
-static bool __worker_done_cb(void* user_data) {
- _W("Done");
- return true;
-}
-
-void _worker_destroy(worker_h worker) {
- if (worker == NULL)
- return;
-
- if (worker->thread) {
- _worker_add_job(worker, __worker_done_cb, NULL);
- g_thread_join(worker->thread);
- }
-
- if (worker->queue)
- g_queue_free_full(worker->queue, (GDestroyNotify)free);
-
- if (worker->name)
- free(worker->name);
-
- g_cond_clear(&worker->cond);
- g_mutex_clear(&worker->mutex);
- free(worker);
-}
+++ /dev/null
-/*
- * Copyright (c) 2020 Samsung Electronics Co., Ltd All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef __LAUNCHPAD_WORKER_H__
-#define __LAUNCHPAD_WORKER_H__
-
-#include <stdbool.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-typedef struct worker_s *worker_h;
-
-typedef bool (*worker_job_cb)(void *user_data);
-
-int _worker_add_job(worker_h worker, worker_job_cb callback, void *user_data);
-
-int _worker_create(const char *name, worker_h *worker);
-
-void _worker_destroy(worker_h worker);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* __LAUNCHPAD_WORKER_H__ */
--- /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 "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)) {
+ thread_ = std::thread([&]() -> void { RunThread(); });
+}
+
+Worker::~Worker() {
+ if (getpid() == current_pid) {
+ Add(std::make_shared<Ender>());
+ thread_.join();
+ }
+}
+
+void Worker::Add(std::shared_ptr<Worker::Job >job) {
+ queue_.Push(std::move(job));
+}
+
+void Worker::SetComm() {
+ const std::string path = "/proc/" + std::to_string(gettid()) + "/comm";
+ std::ofstream comm_file;
+ comm_file.open(path);
+ if (!comm_file.is_open()) {
+ _E("Failed to open %s", path.c_str());
+ return;
+ }
+
+ comm_file << name_;
+ comm_file.close();
+}
+
+void Worker::RunThread() {
+ _W("BEGIN");
+ SetComm();
+ 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 SetComm();
+ 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_