12498b56bSopenharmony_ci/* 22498b56bSopenharmony_ci * Copyright (c) 2021 Huawei Device Co., Ltd. 32498b56bSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 42498b56bSopenharmony_ci * you may not use this file except in compliance with the License. 52498b56bSopenharmony_ci * You may obtain a copy of the License at 62498b56bSopenharmony_ci * 72498b56bSopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 82498b56bSopenharmony_ci * 92498b56bSopenharmony_ci * Unless required by applicable law or agreed to in writing, software 102498b56bSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 112498b56bSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 122498b56bSopenharmony_ci * See the License for the specific language governing permissions and 132498b56bSopenharmony_ci * limitations under the License. 142498b56bSopenharmony_ci */ 152498b56bSopenharmony_ci#include <algorithm> 162498b56bSopenharmony_ci#include <cstring> 172498b56bSopenharmony_ci#include <iostream> 182498b56bSopenharmony_ci#include <memory> 192498b56bSopenharmony_ci#include <mutex> 202498b56bSopenharmony_ci#include <thread> 212498b56bSopenharmony_ci#include <sys/prctl.h> 222498b56bSopenharmony_ci#include <sys/stat.h> 232498b56bSopenharmony_ci#include <unistd.h> 242498b56bSopenharmony_ci 252498b56bSopenharmony_ci#include <log_utils.h> 262498b56bSopenharmony_ci#include <seq_packet_socket_server.h> 272498b56bSopenharmony_ci 282498b56bSopenharmony_ci#include "service_controller.h" 292498b56bSopenharmony_ci#include "cmd_executor.h" 302498b56bSopenharmony_ci 312498b56bSopenharmony_cinamespace OHOS { 322498b56bSopenharmony_cinamespace HiviewDFX { 332498b56bSopenharmony_cistatic const int MAX_CLIENT_CONNECTIONS = 100; 342498b56bSopenharmony_ci 352498b56bSopenharmony_ciCmdExecutor::~CmdExecutor() 362498b56bSopenharmony_ci{ 372498b56bSopenharmony_ci std::lock_guard<std::mutex> lg(m_clientAccess); 382498b56bSopenharmony_ci for (auto& client : m_clients) { 392498b56bSopenharmony_ci client->m_stopThread.store(true); 402498b56bSopenharmony_ci } 412498b56bSopenharmony_ci for (auto& client : m_clients) { 422498b56bSopenharmony_ci if (client->m_clientThread.joinable()) { 432498b56bSopenharmony_ci client->m_clientThread.join(); 442498b56bSopenharmony_ci } 452498b56bSopenharmony_ci } 462498b56bSopenharmony_ci} 472498b56bSopenharmony_ci 482498b56bSopenharmony_civoid CmdExecutor::MainLoop(const std::string& socketName) 492498b56bSopenharmony_ci{ 502498b56bSopenharmony_ci SeqPacketSocketServer cmdServer(socketName, MAX_CLIENT_CONNECTIONS); 512498b56bSopenharmony_ci if (cmdServer.Init() < 0) { 522498b56bSopenharmony_ci std::cerr << "Failed to init control socket ! \n"; 532498b56bSopenharmony_ci return; 542498b56bSopenharmony_ci } 552498b56bSopenharmony_ci std::cout << "Server started to listen !\n"; 562498b56bSopenharmony_ci using namespace std::chrono_literals; 572498b56bSopenharmony_ci cmdServer.StartAcceptingConnection( 582498b56bSopenharmony_ci [this] (std::unique_ptr<Socket> handler) { 592498b56bSopenharmony_ci OnAcceptedConnection(std::move(handler)); 602498b56bSopenharmony_ci }, 612498b56bSopenharmony_ci 3000ms, 622498b56bSopenharmony_ci [this] () { 632498b56bSopenharmony_ci CleanFinishedClients(); 642498b56bSopenharmony_ci }); 652498b56bSopenharmony_ci} 662498b56bSopenharmony_ci 672498b56bSopenharmony_civoid CmdExecutor::OnAcceptedConnection(std::unique_ptr<Socket> handler) 682498b56bSopenharmony_ci{ 692498b56bSopenharmony_ci std::lock_guard<std::mutex> lg(m_clientAccess); 702498b56bSopenharmony_ci auto newVal = std::make_unique<ClientThread>(); 712498b56bSopenharmony_ci if (newVal != nullptr) { 722498b56bSopenharmony_ci newVal->m_stopThread.store(false); 732498b56bSopenharmony_ci newVal->m_clientThread = std::thread([this](std::unique_ptr<Socket> handler) { 742498b56bSopenharmony_ci ClientEventLoop(std::move(handler)); 752498b56bSopenharmony_ci }, std::move(handler)); 762498b56bSopenharmony_ci m_clients.push_back(std::move(newVal)); 772498b56bSopenharmony_ci } 782498b56bSopenharmony_ci} 792498b56bSopenharmony_ci 802498b56bSopenharmony_civoid CmdExecutor::ClientEventLoop(std::unique_ptr<Socket> handler) 812498b56bSopenharmony_ci{ 822498b56bSopenharmony_ci decltype(m_clients)::iterator clientInfoIt; 832498b56bSopenharmony_ci { 842498b56bSopenharmony_ci std::lock_guard<std::mutex> lg(m_clientAccess); 852498b56bSopenharmony_ci clientInfoIt = std::find_if(m_clients.begin(), m_clients.end(), 862498b56bSopenharmony_ci [](const std::unique_ptr<ClientThread>& ct) { 872498b56bSopenharmony_ci return ct->m_clientThread.get_id() == std::this_thread::get_id(); 882498b56bSopenharmony_ci }); 892498b56bSopenharmony_ci } 902498b56bSopenharmony_ci if (clientInfoIt == m_clients.end()) { 912498b56bSopenharmony_ci std::cerr << "Failed to find client\n"; 922498b56bSopenharmony_ci return; 932498b56bSopenharmony_ci } 942498b56bSopenharmony_ci 952498b56bSopenharmony_ci prctl(PR_SET_NAME, m_name.c_str()); 962498b56bSopenharmony_ci ServiceController serviceCtrl(std::move(handler), m_logCollector, m_hilogBuffer, m_kmsgBuffer); 972498b56bSopenharmony_ci serviceCtrl.CommunicationLoop((*clientInfoIt)->m_stopThread, m_cmdList); 982498b56bSopenharmony_ci 992498b56bSopenharmony_ci std::lock_guard<std::mutex> ul(m_finishedClientAccess); 1002498b56bSopenharmony_ci m_finishedClients.push_back(std::this_thread::get_id()); 1012498b56bSopenharmony_ci} 1022498b56bSopenharmony_ci 1032498b56bSopenharmony_civoid CmdExecutor::CleanFinishedClients() 1042498b56bSopenharmony_ci{ 1052498b56bSopenharmony_ci std::list<std::thread> threadsToJoin; 1062498b56bSopenharmony_ci { 1072498b56bSopenharmony_ci // select clients to clean up - pick threads that we have to be sure are ended 1082498b56bSopenharmony_ci std::scoped_lock sl(m_finishedClientAccess, m_clientAccess); 1092498b56bSopenharmony_ci for (auto threadId : m_finishedClients) { 1102498b56bSopenharmony_ci auto clientInfoIt = std::find_if(m_clients.begin(), m_clients.end(), 1112498b56bSopenharmony_ci [&threadId](const std::unique_ptr<ClientThread>& ct) { 1122498b56bSopenharmony_ci return ct->m_clientThread.get_id() == threadId; 1132498b56bSopenharmony_ci }); 1142498b56bSopenharmony_ci if (clientInfoIt != m_clients.end()) { 1152498b56bSopenharmony_ci threadsToJoin.push_back(std::move((*clientInfoIt)->m_clientThread)); 1162498b56bSopenharmony_ci m_clients.erase(clientInfoIt); 1172498b56bSopenharmony_ci } 1182498b56bSopenharmony_ci } 1192498b56bSopenharmony_ci m_finishedClients.clear(); 1202498b56bSopenharmony_ci } 1212498b56bSopenharmony_ci for (auto& thread : threadsToJoin) { 1222498b56bSopenharmony_ci if (thread.joinable()) { 1232498b56bSopenharmony_ci thread.join(); 1242498b56bSopenharmony_ci } 1252498b56bSopenharmony_ci } 1262498b56bSopenharmony_ci} 1272498b56bSopenharmony_ci} // namespace HiviewDFX 1282498b56bSopenharmony_ci} // namespace OHOS 129