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() {
43 while (!queue_.empty()) {
44 auto process = std::move(queue_.front());
50 bool ProcessPool::IsPrepared() const {
51 return !queue_.empty();
54 pid_t ProcessPool::Execute(std::shared_ptr<AppPacket> app_packet) {
59 auto process = std::move(queue_.front());
61 process->Send(std::move(app_packet));
62 return process->GetPid();
65 ProcessPool::Process::Process(pid_t pid, int fd)
66 : pid_(pid), socket_(new Socket(fd)) {
69 pid_t ProcessPool::Process::GetPid() const {
73 int ProcessPool::Process::Send(std::shared_ptr<AppPacket> app_packet) {
74 _W("Send execution request. process ID: %d", pid_);
75 tizen_base::Parcel parcel;
76 app_packet->WriteToParcel(&parcel);
77 return socket_->Write(parcel.GetData(), parcel.GetDataSize());
80 void ProcessPool::Process::Kill() {
82 if (kill(pid_, SIGKILL) == -1) {
83 _E("Failed to send kill signal to the process. pid(%d), errno(%d)",
88 void ProcessPool::OnExecution() {
89 _W("Candidate Process");
90 Procfs::SetComm(getpid(), "process-pool+");
92 int ret = WaitForRequest(std::make_unique<Socket>(pipe_fd_[0]));
96 void ProcessPool::PrepareProcess() {
97 int current_process_count = static_cast<int>(queue_.size());
98 for (int i = current_process_count; i < num_processes_; ++i) {
101 if (pipe(pipe_fd_) == -1) {
102 _E("Failed to create pipe. errno(%d)", errno);
106 if (fcntl(pipe_fd_[0], F_SETPIPE_SZ, AppPacket::kMaxPacketSize) == -1)
107 _E("Failed to set pipe size. errno(%d)", errno);
109 if (fcntl(pipe_fd_[1], F_SETPIPE_SZ, AppPacket::kMaxPacketSize) == -1)
110 _E("Failed to set pipe size. errno(%d)", errno);
112 pid_t pid = Executor::Execute();
114 _E("Failed to fork process. errno(%d)", errno);
121 queue_.push(std::make_shared<Process>(pid, pipe_fd_[1]));
125 int ProcessPool::WaitForRequest(std::unique_ptr<Socket> socket) {
126 auto app_packet = std::make_shared<AppPacket>();
129 char buf[AppPacket::GetHeaderSize()] = { 0, };
130 ret = socket->Read(buf, sizeof(buf));
132 _E("Failed to read from socket. error(%d)", ret);
136 tizen_base::Parcel parcel(buf, sizeof(buf));
137 app_packet->ReadFromParcel(&parcel);
139 std::vector<uint8_t> data;
140 data.resize(app_packet->GetDataSize());
141 ret = socket->Read(data.data(), app_packet->GetDataSize());
143 _E("Failed to read from socket. error(%d)", ret);
147 parcel.Write(data.data(), data.size());
148 parcel.ResetReader();
149 app_packet->ReadFromParcel(&parcel);
152 if (event_listener_ != nullptr)
153 event_listener_->OnRequestReceived(std::move(app_packet));
158 void ProcessPool::SetTimer() {
162 timer_ = g_timeout_add(1000, OnTimeout, this);
165 gboolean ProcessPool::OnTimeout(gpointer user_data) {
166 auto* process_pool = static_cast<ProcessPool*>(user_data);
167 process_pool->PrepareProcess();
168 process_pool->timer_ = 0;
169 return G_SOURCE_REMOVE;
172 } // namespace launchpad