2 * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved
4 * Licensed under the Apache License, Version 2.0 (the License);
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an AS IS BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 #include "launchpad-process-pool/process_pool.hh"
23 #include <sys/types.h>
31 #include "launchpad-process-pool/log_private.hh"
35 ProcessPool::ProcessPool(int num_processes, IEvent* event_listener = nullptr)
37 num_processes_(num_processes),
38 event_listener_(event_listener) {
42 ProcessPool::~ProcessPool() {
46 bool ProcessPool::IsPrepared() const {
47 return !queue_.empty();
50 pid_t ProcessPool::Execute(std::shared_ptr<AppPacket> app_packet) {
55 auto process = std::move(queue_.front());
57 process->Send(std::move(app_packet));
58 return process->GetPid();
61 void ProcessPool::Dispose() {
62 while (!queue_.empty()) {
63 auto process = std::move(queue_.front());
66 _D("Kill process(%d)", process->GetPid());
72 ProcessPool::Process::Process(pid_t pid, int fd)
73 : pid_(pid), socket_(new Socket(fd)) {
76 pid_t ProcessPool::Process::GetPid() const {
80 int ProcessPool::Process::Send(std::shared_ptr<AppPacket> app_packet) {
81 _W("Send execution request. process ID: %d", pid_);
82 tizen_base::Parcel parcel;
83 app_packet->WriteToParcel(&parcel);
84 return socket_->Write(parcel.GetData(), parcel.GetDataSize());
87 void ProcessPool::Process::Kill() {
89 if (kill(pid_, SIGKILL) == -1) {
90 _E("Failed to send kill signal to the process. pid(%d), errno(%d)",
95 void ProcessPool::OnExecution() {
96 _W("Candidate Process");
97 Procfs::SetComm(getpid(), "process-pool+");
99 int ret = WaitForRequest(std::make_unique<Socket>(pipe_fd_[0]));
103 void ProcessPool::PrepareProcess() {
104 int current_process_count = static_cast<int>(queue_.size());
105 for (int i = current_process_count; i < num_processes_; ++i) {
108 if (pipe(pipe_fd_) == -1) {
109 _E("Failed to create pipe. errno(%d)", errno);
113 if (fcntl(pipe_fd_[0], F_SETPIPE_SZ, AppPacket::kMaxPacketSize) == -1)
114 _E("Failed to set pipe size. errno(%d)", errno);
116 if (fcntl(pipe_fd_[1], F_SETPIPE_SZ, AppPacket::kMaxPacketSize) == -1)
117 _E("Failed to set pipe size. errno(%d)", errno);
119 pid_t pid = Executor::Execute();
121 _E("Failed to fork process. errno(%d)", errno);
128 queue_.push(std::make_shared<Process>(pid, pipe_fd_[1]));
132 int ProcessPool::WaitForRequest(std::unique_ptr<Socket> socket) {
133 auto app_packet = std::make_shared<AppPacket>();
136 char buf[AppPacket::GetHeaderSize()] = { 0, };
137 ret = socket->Read(buf, sizeof(buf));
139 _E("Failed to read from socket. error(%d)", ret);
143 tizen_base::Parcel parcel(buf, sizeof(buf));
144 app_packet->ReadFromParcel(&parcel);
146 std::vector<uint8_t> data;
147 data.resize(app_packet->GetDataSize());
148 ret = socket->Read(data.data(), app_packet->GetDataSize());
150 _E("Failed to read from socket. error(%d)", ret);
154 parcel.Write(data.data(), data.size());
155 parcel.ResetReader();
156 app_packet->ReadFromParcel(&parcel);
159 if (event_listener_ != nullptr)
160 event_listener_->OnRequestReceived(std::move(app_packet));
165 void ProcessPool::SetTimer() {
169 timer_ = g_timeout_add(1000, OnTimeout, this);
172 void ProcessPool::UnsetTimer() {
174 g_source_remove(timer_);
179 gboolean ProcessPool::OnTimeout(gpointer user_data) {
180 auto* process_pool = static_cast<ProcessPool*>(user_data);
181 process_pool->PrepareProcess();
182 process_pool->timer_ = 0;
183 return G_SOURCE_REMOVE;
186 } // namespace launchpad