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/hydra_loader_context.hh"
23 #include <cpu_boost_controller.hh>
24 #include <exception.hh>
25 #include <hydra_request.hh>
28 #include "launchpad-process-pool/log_private.hh"
30 namespace fs = std::filesystem;
35 constexpr const char kHydraLoaderSocketName[] = ".hydra-loader";
36 const int kSocketMaxBufferSize = 131071;
40 HydraLoaderContext::Builder::operator LoaderContext*() {
41 return new HydraLoaderContext(std::move(loader_info_), loader_id_,
42 caller_pid_, activated_, std::move(loader_mount_));
45 HydraLoaderContext::HydraLoaderContext(
46 std::shared_ptr<LoaderInfo> loader_info, int loader_id, pid_t caller_pid,
47 bool activated, std::shared_ptr<LoaderMount> loader_mount)
48 : LoaderContext(std::move(loader_info), loader_id, caller_pid, activated,
49 std::move(loader_mount)) {
53 void HydraLoaderContext::Listen() {
55 std::string socket_path = "/run/aul/daemons/" + std::to_string(getuid()) +
56 "/" + std::string(kHydraLoaderSocketName) + std::to_string(GetType()) +
57 "-" + std::to_string(GetLoaderId());
58 if (fs::exists(socket_path))
59 fs::remove(socket_path);
61 hydra_socket_.reset(new ServerSocket());
62 hydra_socket_->Bind(socket_path);
63 hydra_socket_->Listen(128);
67 hydra_socket_->GetFd(), IOChannel::IOCondition::IO_IN, this));
68 hydra_channel_->SetCloseOnDestroy(false);
69 } catch (const Exception& e) {
70 _E("Exception occurs. error: %s", e.what());
71 THROW(e.GetErrorCode());
75 void HydraLoaderContext::Dispose() {
76 _D("Dispose hydra process. type(%d), loader_name(%s)",
77 GetType(), GetLoaderName().c_str());
79 LoaderContext::Dispose();
81 _D("Kill process(%d)", hydra_pid_);
82 if (kill(hydra_pid_, SIGKILL) != 0)
83 _E("kill() is failed. pid(%d), errno(%d)", hydra_pid_, errno);
88 client_channel_.reset();
89 client_socket_.reset();
90 hydra_prepared_ = false;
93 pid_t HydraLoaderContext::Prepare() {
95 if (hydra_pid_ > 0 && client_socket_.get() != nullptr) {
96 PrepareCandidateProcess();
100 hydra_pid_ = LoaderContext::Prepare();
105 pid_t HydraLoaderContext::GetHydraPid() const {
109 void HydraLoaderContext::SetHydraPid(pid_t hydra_pid) {
110 hydra_pid_ = hydra_pid;
113 void HydraLoaderContext::PrepareCandidateProcess() {
114 _W("Send launch request to hydra loader. fd(%d)", client_socket_->GetFd());
115 HydraRequest request(HydraCmd::LaunchCandidate, GetSchedPriority());
116 tizen_base::Parcel parcel;
117 parcel.WriteParcelable(request);
119 size_t data_size = parcel.GetDataSize();
120 int ret = client_socket_->Send(static_cast<void*>(&data_size),
123 _E("Send() is failed. error: %d", ret);
127 ret = client_socket_->Send(parcel.GetData(), data_size);
129 _E("Send() is failed. error: %d", ret);
132 void HydraLoaderContext::HandleHydraLoaderEvent() {
133 if (!hydra_prepared_) {
135 client_socket_ = hydra_socket_->Accept();
136 client_socket_->SetReceiveBufferSize(kSocketMaxBufferSize);
137 client_socket_->SetReceiveTimeout(5200);
138 client_socket_->SetSendBufferSize(kSocketMaxBufferSize);
141 int ret = client_socket_->Receive(static_cast<void*>(&pid), sizeof(pid));
143 _E("Receive() is failed. error: %d", ret);
144 client_socket_.reset();
148 client_channel_.reset(
149 new IOChannel(client_socket_->GetFd(),
150 IOChannel::IOCondition::IO_IN | IOChannel::IOCondition::IO_HUP,
152 client_channel_->SetCloseOnDestroy(false);
153 hydra_prepared_ = true;
154 SECURE_LOGI("Type %d hydra loader was connected. pid: %d",
155 GetType(), GetHydraPid());
156 } catch (const Exception& e) {
157 _E("Exception occurs. error: %s", e.what());
161 auto client_socket = hydra_socket_->Accept();
162 _E("Refuse hydra process connection");
166 void HydraLoaderContext::HandleHydraLoaderClientEvent(int condition) {
168 (IOChannel::IOCondition::IO_HUP | IOChannel::IOCondition::IO_NVAL)) {
169 SECURE_LOGE("Type %d loader was disconnected. pid: %d",
170 GetType(), GetHydraPid());
176 if (condition & IOChannel::IOCondition::IO_IN) {
178 int ret = client_socket_->Receive(static_cast<void*>(&pid), sizeof(pid));
180 _E("Receive() is failed. error(%d)", ret);
182 _W("Candidate process: %d", pid);
185 if (RefCount() > 0) {
186 CPUBoostController::DoBoost(pid, CPUBoostController::Level::Strong,
194 void HydraLoaderContext::OnIOEventReceived(int fd, int condition) {
195 _W("[DEBUG] fd(%d), condition(%d)", fd, condition);
196 if (hydra_socket_.get() != nullptr && hydra_socket_->GetFd() == fd)
197 HandleHydraLoaderEvent();
198 else if (client_socket_.get() != nullptr && client_socket_->GetFd() == fd)
199 HandleHydraLoaderClientEvent(condition);
201 LoaderContext::OnIOEventReceived(fd, condition);
204 } // namespace launchpad