From be085bf2fd2ce796f7bfaf081f75937fa55ad3e7 Mon Sep 17 00:00:00 2001 From: Hwankyu Jhun Date: Tue, 18 Apr 2023 06:39:19 +0000 Subject: [PATCH] Support Process pool feature Launchpad is introducing a process pool. The process pool class creates child processes, which are used to execute application launch requests or to create loader processes. This feature is used to improve performance. The PSS memory usage of candidate processes is not high, typically ranging from 400 to 500. Change-Id: I0142e7c15d12295741c46fa5e203caa664dea0d9 Signed-off-by: Hwankyu Jhun --- CMakeLists.txt | 1 + packaging/launchpad.spec | 1 + src/launchpad-process-pool/app_executor.cc | 33 +++- src/launchpad-process-pool/app_executor.hh | 7 +- src/launchpad-process-pool/loader_executor.cc | 69 +++++--- src/launchpad-process-pool/loader_executor.hh | 12 +- src/launchpad-process-pool/process_pool.cc | 173 +++++++++++++++++++++ src/launchpad-process-pool/process_pool.hh | 80 ++++++++++ src/launchpad-process-pool/worker.cc | 16 +- src/launchpad-process-pool/worker.hh | 1 - src/lib/launchpad-common/CMakeLists.txt | 1 + src/lib/launchpad-common/app_packet.cc | 65 ++++++++ src/lib/launchpad-common/app_packet.hh | 59 +++++++ .../pkgconfig/liblaunchpad-common.pc.in | 2 +- src/lib/launchpad-common/procfs.cc | 13 ++ src/lib/launchpad-common/procfs.hh | 1 + 16 files changed, 492 insertions(+), 42 deletions(-) create mode 100644 src/launchpad-process-pool/process_pool.cc create mode 100644 src/launchpad-process-pool/process_pool.hh create mode 100644 src/lib/launchpad-common/app_packet.cc create mode 100644 src/lib/launchpad-common/app_packet.hh diff --git a/CMakeLists.txt b/CMakeLists.txt index 2814f5b..ac8c783 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -72,6 +72,7 @@ PKG_CHECK_MODULES(TANCHOR_DEPS REQUIRED tanchor) PKG_CHECK_MODULES(TIZEN_SHARED_QUEUE_DEPS REQUIRED tizen-shared-queue) PKG_CHECK_MODULES(TTRACE_DEPS REQUIRED ttrace) PKG_CHECK_MODULES(VCONF_DEPS REQUIRED vconf) +PKG_CHECK_MODULES(PARCEL_DEPS REQUIRED parcel) ENABLE_TESTING() ADD_TEST(NAME ${TARGET_LAUNCHPAD_PROCESS_POOL_UNITTEST} diff --git a/packaging/launchpad.spec b/packaging/launchpad.spec index 4dc7d5f..bb01a7d 100644 --- a/packaging/launchpad.spec +++ b/packaging/launchpad.spec @@ -35,6 +35,7 @@ BuildRequires: pkgconfig(tanchor) BuildRequires: pkgconfig(tizen-shared-queue) BuildRequires: pkgconfig(ttrace) BuildRequires: pkgconfig(vconf) +BuildRequires: pkgconfig(parcel) Requires(post): /sbin/ldconfig Requires(post): /usr/bin/systemctl diff --git a/src/launchpad-process-pool/app_executor.cc b/src/launchpad-process-pool/app_executor.cc index a5d6f95..a4155aa 100644 --- a/src/launchpad-process-pool/app_executor.cc +++ b/src/launchpad-process-pool/app_executor.cc @@ -25,6 +25,7 @@ #include #include +#include #include #include @@ -39,8 +40,26 @@ namespace launchpad { namespace fs = std::filesystem; +namespace { -AppExecutor::AppExecutor() : Executor(this) { +std::shared_ptr CreateAppPacketFromAppInfo(const AppInfo* app_info) { + auto raw = const_cast(app_info->GetBundle()).ToRaw(); + std::vector data(raw.first.get(), raw.first.get() + raw.second); + return std::shared_ptr(new AppPacket(0, 0, std::move(data))); +} + +std::shared_ptr CreateAppInfoFromAppPacket( + const AppPacket* app_packet) { + auto& data = app_packet->GetData(); + std::string raw(data.begin(), data.end()); + tizen_base::Bundle b(raw); + return std::shared_ptr(AppInfo::Create(std::move(b))); +} + +} // namespace + +AppExecutor::AppExecutor() + : Executor(this), process_pool_(new ProcessPool(2, this)) { LauncherInfoInflator inflator; launcher_infos_ = inflator.Inflate("/usr/share/aul"); @@ -75,6 +94,11 @@ AppExecutor::AppExecutor() : Executor(this) { } pid_t AppExecutor::Execute(const AppInfo* app_info) { + if (process_pool_->IsPrepared()) { + auto app_packet = CreateAppPacketFromAppInfo(app_info); + return process_pool_->Execute(std::move(app_packet)); + } + app_info_ = app_info; return Executor::Execute(); } @@ -122,6 +146,13 @@ void AppExecutor::OnExecution() { } } +void AppExecutor::OnRequestReceived(std::shared_ptr app_packet) { + _W("Request received"); + auto app_info = CreateAppInfoFromAppPacket(app_packet.get()); + app_info_ = app_info.get(); + OnExecution(); +} + int AppExecutor::Prepare() { for (auto& func : prepare_funcs_) { if (func() != 0) diff --git a/src/launchpad-process-pool/app_executor.hh b/src/launchpad-process-pool/app_executor.hh index 78bebc9..2977219 100644 --- a/src/launchpad-process-pool/app_executor.hh +++ b/src/launchpad-process-pool/app_executor.hh @@ -22,16 +22,19 @@ #include #include #include +#include #include #include "launchpad-process-pool/executor.hh" #include "launchpad-process-pool/launcher_info.hh" +#include "launchpad-process-pool/process_pool.hh" namespace launchpad { class AppExecutor : public Executor::Delegator, - public Executor { + public Executor, + public ProcessPool::IEvent { public: AppExecutor(); @@ -39,6 +42,7 @@ class AppExecutor : public Executor::Delegator, private: void OnExecution() override; + void OnRequestReceived(std::shared_ptr app_packet) override; int Prepare(); int StepCreateNewSession(); @@ -64,6 +68,7 @@ class AppExecutor : public Executor::Delegator, private: using PrepareFunc = std::function; + std::unique_ptr process_pool_; std::vector launcher_infos_; std::vector prepare_funcs_; const AppInfo* app_info_ = nullptr; diff --git a/src/launchpad-process-pool/loader_executor.cc b/src/launchpad-process-pool/loader_executor.cc index 7f66558..601a61d 100644 --- a/src/launchpad-process-pool/loader_executor.cc +++ b/src/launchpad-process-pool/loader_executor.cc @@ -22,14 +22,36 @@ #include +#include + #include "launchpad-process-pool/log_private.hh" #include "launchpad-process-pool/signal_manager.hh" #include "lib/common/inc/launchpad_common.h" #include "lib/common/inc/launchpad_types.h" namespace launchpad { +namespace { + +std::shared_ptr CreateAppPacketFromArgs( + const std::vector& args) { + tizen_base::Bundle b; + b.Add("LOADER_ARGS", args); + auto raw = b.ToRaw(); + std::vector data(raw.first.get(), raw.first.get() + raw.second); + return std::shared_ptr(new AppPacket(0, 0, std::move(data))); +} -LoaderExecutor::LoaderExecutor() : Executor(this) {} +std::vector CreateArgsFromAppPacket(const AppPacket* app_packet) { + auto& data = app_packet->GetData(); + std::string raw(data.begin(), data.end()); + tizen_base::Bundle b(raw); + return b.GetStringArray("LOADER_ARGS"); +} + +} // namespace + +LoaderExecutor::LoaderExecutor() + : Executor(this), process_pool_(new ProcessPool(2, this)) {} LoaderExecutor& LoaderExecutor::GetInst() { static LoaderExecutor inst; @@ -38,22 +60,20 @@ LoaderExecutor& LoaderExecutor::GetInst() { pid_t LoaderExecutor::Execute(const LoaderContext* loader_context, int priority) { - loader_context_ = loader_context; + loader_argv_ = CreateLoaderArgv(loader_context); + if (process_pool_->IsPrepared()) { + auto app_packet = CreateAppPacketFromArgs(loader_argv_); + return process_pool_->Execute(std::move(app_packet)); + } + return Executor::Execute(priority); } void LoaderExecutor::OnExecution() { - std::vector argv = CreateLoaderArgv(); - char** loader_argv = static_cast( - calloc(argv.size() + 1, sizeof(char*))); - if (loader_argv == nullptr) { - _E("Out of memory"); - exit(EXIT_FAILURE); - } - - int loader_argc = argv.size(); + std::vector 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(argv[i].c_str()); + loader_argv[i] = const_cast(loader_argv_[i].c_str()); if ((i + 1) != loader_argc) SECURE_LOGD("loader argument %d : %s##", i, loader_argv[i]); } @@ -62,24 +82,31 @@ void LoaderExecutor::OnExecution() { _close_all_fds(); _setup_stdio(basename(loader_argv[LOADER_ARG_PATH])); - if (execv(loader_argv[LOADER_ARG_PATH], loader_argv) < 0) { + if (execv(loader_argv[LOADER_ARG_PATH], loader_argv.data()) < 0) { char err_buf[1024]; fprintf(stderr, "Failed to execute a file. path: %s, errno: %d:%s\n", - loader_argv[LOADER_ARG_PATH], errno, - strerror_r(errno, err_buf, sizeof(err_buf))); + loader_argv[LOADER_ARG_PATH], errno, + strerror_r(errno, err_buf, sizeof(err_buf))); exit(EXIT_FAILURE); } } -std::vector LoaderExecutor::CreateLoaderArgv() { +void LoaderExecutor::OnRequestReceived(std::shared_ptr app_packet) { + _W("Request received"); + loader_argv_ = CreateArgsFromAppPacket(app_packet.get()); + OnExecution(); +} + +std::vector LoaderExecutor::CreateLoaderArgv( + const LoaderContext* loader_context) { std::string dummy(LOADER_ARG_LEN - 1, ' '); std::vector argv(LOADER_ARG_DUMMY + 1); argv[LOADER_ARG_DUMMY] = std::move(dummy); - argv[LOADER_ARG_PATH] = loader_context_->GetLoaderPath(); - argv[LOADER_ARG_TYPE] = std::to_string(loader_context_->GetType()); - argv[LOADER_ARG_ID] = std::to_string(loader_context_->GetLoaderId()); - argv[LOADER_ARG_HYDRA] = loader_context_->IsHydraMode() ? "1" : "0"; - argv[LOADER_ARG_EXTRA] = loader_context_->GetLoaderExtra(); + argv[LOADER_ARG_PATH] = loader_context->GetLoaderPath(); + argv[LOADER_ARG_TYPE] = std::to_string(loader_context->GetType()); + argv[LOADER_ARG_ID] = std::to_string(loader_context->GetLoaderId()); + argv[LOADER_ARG_HYDRA] = loader_context->IsHydraMode() ? "1" : "0"; + argv[LOADER_ARG_EXTRA] = loader_context->GetLoaderExtra(); return argv; } diff --git a/src/launchpad-process-pool/loader_executor.hh b/src/launchpad-process-pool/loader_executor.hh index b2cafaa..b703249 100644 --- a/src/launchpad-process-pool/loader_executor.hh +++ b/src/launchpad-process-pool/loader_executor.hh @@ -17,16 +17,19 @@ #ifndef LAUNCHPAD_PROCESS_POOL_LOADER_EXECUTOR_HH_ #define LAUNCHPAD_PROCESS_POOL_LOADER_EXECUTOR_HH_ +#include #include #include #include "launchpad-process-pool/executor.hh" #include "launchpad-process-pool/loader_context.hh" +#include "launchpad-process-pool/process_pool.hh" namespace launchpad { class LoaderExecutor : public Executor::Delegator, - public Executor { + public Executor, + public ProcessPool::IEvent { public: LoaderExecutor(const LoaderExecutor&) = delete; LoaderExecutor& operator=(const LoaderExecutor&) = delete; @@ -42,10 +45,13 @@ class LoaderExecutor : public Executor::Delegator, ~LoaderExecutor() = default; void OnExecution() override; - std::vector CreateLoaderArgv(); + void OnRequestReceived(std::shared_ptr app_packet) override; + std::vector CreateLoaderArgv( + const LoaderContext* loader_context); private: - const LoaderContext* loader_context_ = nullptr; + std::unique_ptr process_pool_; + std::vector loader_argv_; }; } // namespace launchpad diff --git a/src/launchpad-process-pool/process_pool.cc b/src/launchpad-process-pool/process_pool.cc new file mode 100644 index 0000000..cec1c39 --- /dev/null +++ b/src/launchpad-process-pool/process_pool.cc @@ -0,0 +1,173 @@ +/* + * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "launchpad-process-pool/process_pool.hh" + +#include +#include +#include +#include +#include +#include + +#include + +#include +#include + +#include "launchpad-process-pool/log_private.hh" + +namespace launchpad { + +ProcessPool::ProcessPool(int num_processes, IEvent* event_listener = nullptr) + : Executor(this), + num_processes_(num_processes), + event_listener_(event_listener) { + PrepareProcess(); +} + +ProcessPool::~ProcessPool() { + while (!queue_.empty()) { + auto process = std::move(queue_.front()); + queue_.pop(); + process->Kill(); + } +} + +bool ProcessPool::IsPrepared() const { + return !queue_.empty(); +} + +pid_t ProcessPool::Execute(std::shared_ptr app_packet) { + SetTimer(); + if (!IsPrepared()) + return -1; + + auto process = std::move(queue_.front()); + queue_.pop(); + process->Send(std::move(app_packet)); + return process->GetPid(); +} + +ProcessPool::Process::Process(pid_t pid, int fd) + : pid_(pid), socket_(new Socket(fd)) { +} + +pid_t ProcessPool::Process::GetPid() const { + return pid_; +} + +int ProcessPool::Process::Send(std::shared_ptr app_packet) { + _W("Send execution request. process ID: %d", pid_); + tizen_base::Parcel parcel; + app_packet->WriteToParcel(&parcel); + return socket_->Write(parcel.GetData(), parcel.GetDataSize()); +} + +void ProcessPool::Process::Kill() { + socket_->Close(); + if (kill(pid_, SIGKILL) == -1) { + _E("Failed to send kill signal to the process. pid(%d), errno(%d)", + pid_, errno); + } +} + +void ProcessPool::OnExecution() { + _W("Candidate Process"); + Procfs::SetComm(getpid(), "process-pool+"); + close(pipe_fd_[1]); + int ret = WaitForRequest(std::make_unique(pipe_fd_[0])); + exit(ret); +} + +void ProcessPool::PrepareProcess() { + int current_process_count = static_cast(queue_.size()); + for (int i = current_process_count; i < num_processes_; ++i) { + pipe_fd_[0] = -1; + pipe_fd_[1] = -1; + if (pipe(pipe_fd_) == -1) { + _E("Failed to create pipe. errno(%d)", errno); + return; + } + + if (fcntl(pipe_fd_[0], F_SETPIPE_SZ, AppPacket::kMaxPacketSize) == -1) + _E("Failed to set pipe size. errno(%d)", errno); + + if (fcntl(pipe_fd_[1], F_SETPIPE_SZ, AppPacket::kMaxPacketSize) == -1) + _E("Failed to set pipe size. errno(%d)", errno); + + pid_t pid = Executor::Execute(); + if (pid == -1) { + _E("Failed to fork process. errno(%d)", errno); + close(pipe_fd_[0]); + close(pipe_fd_[1]); + return; + } + + close(pipe_fd_[0]); + queue_.push(std::make_shared(pid, pipe_fd_[1])); + } +} + +int ProcessPool::WaitForRequest(std::unique_ptr socket) { + auto app_packet = std::make_shared(); + int ret = 0; + do { + char buf[AppPacket::GetHeaderSize()] = { 0, }; + ret = socket->Read(buf, sizeof(buf)); + if (ret != 0) { + _E("Failed to read from socket. error(%d)", ret); + return -1; + } + + tizen_base::Parcel parcel(buf, sizeof(buf)); + app_packet->ReadFromParcel(&parcel); + + std::vector data; + data.resize(app_packet->GetDataSize()); + ret = socket->Read(data.data(), app_packet->GetDataSize()); + if (ret != 0) { + _E("Failed to read from socket. error(%d)", ret); + return -1; + } + + parcel.Write(data.data(), data.size()); + parcel.ResetReader(); + app_packet->ReadFromParcel(&parcel); + } while (ret != 0); + + if (event_listener_ != nullptr) + event_listener_->OnRequestReceived(std::move(app_packet)); + + return 0; +} + +void ProcessPool::SetTimer() { + if (timer_ != 0) + return; + + timer_ = g_timeout_add(1000, OnTimeout, this); +} + +gboolean ProcessPool::OnTimeout(gpointer user_data) { + auto* process_pool = static_cast(user_data); + process_pool->PrepareProcess(); + process_pool->timer_ = 0; + return G_SOURCE_REMOVE; +} + +} // namespace launchpad + diff --git a/src/launchpad-process-pool/process_pool.hh b/src/launchpad-process-pool/process_pool.hh new file mode 100644 index 0000000..302a826 --- /dev/null +++ b/src/launchpad-process-pool/process_pool.hh @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef LAUNCHPAD_PROCESS_POOL_PROCESS_POOL_HH_ +#define LAUNCHPAD_PROCESS_POOL_PROCESS_POOL_HH_ + +#include +#include + +#include +#include +#include + +#include +#include + +#include "launchpad-process-pool/executor.hh" + +namespace launchpad { + +class ProcessPool : public Executor::Delegator, + public Executor { + public: + class IEvent { + public: + virtual ~IEvent() = default; + virtual void OnRequestReceived(std::shared_ptr app_packet) = 0; + }; + + explicit ProcessPool(int num_processes, IEvent* event_listener); + virtual ~ProcessPool(); + + bool IsPrepared() const; + pid_t Execute(std::shared_ptr app_packet); + + private: + class Process { + public: + Process(pid_t pid, int fd); + + pid_t GetPid() const; + int Send(std::shared_ptr app_packet); + void Kill(); + + private: + pid_t pid_; + std::unique_ptr socket_; + }; + + void OnExecution() override; + + void PrepareProcess(); + int WaitForRequest(std::unique_ptr socket); + void SetTimer(); + static gboolean OnTimeout(gpointer user_data); + + private: + int num_processes_; + IEvent* event_listener_; + int pipe_fd_[2] = { -1, -1 }; + std::queue> queue_; + guint timer_ = 0; +}; + +} // namespace launchpad + +#endif // LAUNCHPAD_PROCESS_POOL_PROCESS_POOL_HH_ diff --git a/src/launchpad-process-pool/worker.cc b/src/launchpad-process-pool/worker.cc index ec8a4d6..0b2dd45 100644 --- a/src/launchpad-process-pool/worker.cc +++ b/src/launchpad-process-pool/worker.cc @@ -22,6 +22,7 @@ #include #include +#include #include "launchpad-process-pool/log_private.hh" @@ -54,22 +55,9 @@ void Worker::Add(std::shared_ptrjob) { 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(); + Procfs::SetComm(gettid(), name_); while (true) { auto job = queue_->WaitAndPop(); job->Do(); diff --git a/src/launchpad-process-pool/worker.hh b/src/launchpad-process-pool/worker.hh index 32afdaf..c8dff3f 100644 --- a/src/launchpad-process-pool/worker.hh +++ b/src/launchpad-process-pool/worker.hh @@ -41,7 +41,6 @@ class Worker { void Add(std::shared_ptr job); private: - void SetComm(); void RunThread(); private: diff --git a/src/lib/launchpad-common/CMakeLists.txt b/src/lib/launchpad-common/CMakeLists.txt index b62e8c5..e655544 100644 --- a/src/lib/launchpad-common/CMakeLists.txt +++ b/src/lib/launchpad-common/CMakeLists.txt @@ -18,6 +18,7 @@ APPLY_PKG_CONFIG(${TARGET_LAUNCHPAD_COMMON} PUBLIC GIO_DEPS INIPARSER_DEPS VCONF_DEPS + PARCEL_DEPS ) TARGET_LINK_LIBRARIES(${TARGET_LAUNCHPAD_COMMON} PUBLIC "-ldl") diff --git a/src/lib/launchpad-common/app_packet.cc b/src/lib/launchpad-common/app_packet.cc new file mode 100644 index 0000000..519ac4b --- /dev/null +++ b/src/lib/launchpad-common/app_packet.cc @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "launchpad-common/app_packet.hh" + +#include + +#include + +namespace launchpad { + +AppPacket::AppPacket(int command, int option, std::vector data) + : command_(command), + option_(option), + data_size_(static_cast(data.size())), + data_(std::move(data)) {} + +void AppPacket::WriteToParcel(tizen_base::Parcel* parcel) const { + parcel->WriteInt32(command_); + parcel->WriteInt32(option_); + parcel->WriteInt32(data_size_); + if (data_size_ > 0) + parcel->Write(data_.data(), data_.size()); +} + +void AppPacket::ReadFromParcel(tizen_base::Parcel* parcel) { + parcel->ReadInt32(&command_); + parcel->ReadInt32(&option_); + parcel->ReadInt32(&data_size_); + if (data_size_ > 0) { + data_.resize(data_size_); + parcel->Read(data_.data(), data_.size()); + } +} + +int AppPacket::GetCommand() const { + return command_; +} + +int AppPacket::GetOption() const { + return option_; +} + +int AppPacket::GetDataSize() const { + return data_size_; +} + +const std::vector& AppPacket::GetData() const { + return data_; +} + +} // namespace launchpad diff --git a/src/lib/launchpad-common/app_packet.hh b/src/lib/launchpad-common/app_packet.hh new file mode 100644 index 0000000..983ae2b --- /dev/null +++ b/src/lib/launchpad-common/app_packet.hh @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef LIB_LAUNCHPAD_COMMON_APP_PACKET_HH_ +#define LIB_LAUNCHPAD_COMMON_APP_PACKET_HH_ + +#include +#include + +#include + +#undef EXPORT_API +#define EXPORT_API __attribute__((visibility("default"))) + +namespace launchpad { + +class EXPORT_API AppPacket : public tizen_base::Parcelable { + public: + AppPacket() = default; + AppPacket(int command, int option, std::vector data); + virtual ~AppPacket() = default; + + void WriteToParcel(tizen_base::Parcel* parcel) const override; + void ReadFromParcel(tizen_base::Parcel* parcel) override; + + static constexpr size_t GetHeaderSize() { + return sizeof(int) + sizeof(int) + sizeof(int); + } + + int GetCommand() const; + int GetOption() const; + int GetDataSize() const; + const std::vector& GetData() const; + + static constexpr int kMaxPacketSize = 131071; + + private: + int command_ = 0; + int option_ = 0; + int data_size_ = 0; + std::vector data_; +}; + +} // namespace launchpad + +#endif // LIB_LAUNCHPAD_COMMON_APP_PACKET_HH_ diff --git a/src/lib/launchpad-common/pkgconfig/liblaunchpad-common.pc.in b/src/lib/launchpad-common/pkgconfig/liblaunchpad-common.pc.in index 6b5cff3..c1fad50 100644 --- a/src/lib/launchpad-common/pkgconfig/liblaunchpad-common.pc.in +++ b/src/lib/launchpad-common/pkgconfig/liblaunchpad-common.pc.in @@ -8,6 +8,6 @@ includedir=@INCLUDE_INSTALL_DIR@ Name: liblaunchpad-common Description: launchpad common library Version: @VERSION@ -Requires: bundle dlog +Requires: bundle dlog parcel Libs: -L${libdir} -llaunchpad-common Cflags: -I${includedir} -I${includedir}/launchpad-common diff --git a/src/lib/launchpad-common/procfs.cc b/src/lib/launchpad-common/procfs.cc index 54009e2..eaf3605 100644 --- a/src/lib/launchpad-common/procfs.cc +++ b/src/lib/launchpad-common/procfs.cc @@ -127,4 +127,17 @@ std::string Procfs::GetAttrCurrent(pid_t pid) { return result; } +void Procfs::SetComm(pid_t pid, const std::string& comm) { + const std::string path = "/proc/" + std::to_string(pid) + "/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 << comm; + comm_file.close(); +} + } // namespace launchpad diff --git a/src/lib/launchpad-common/procfs.hh b/src/lib/launchpad-common/procfs.hh index 4c45e7a..71f3318 100644 --- a/src/lib/launchpad-common/procfs.hh +++ b/src/lib/launchpad-common/procfs.hh @@ -31,6 +31,7 @@ class EXPORT_API Procfs { static void GetMemoryUsage(uint32_t* usage); static void GetPssMemory(pid_t pid, uint64_t* mem_pss); static std::string GetAttrCurrent(pid_t pid); + static void SetComm(pid_t pid, const std::string& comm); }; } // namespace launchpad -- 2.7.4