• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) Huawei Technologies Co., Ltd. 2022. All rights reserved.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11  * See the License for the specific language governing permissions and
12  * limitations under the License.
13  */
14 
15 #include <csignal>
16 #include <mutex>
17 #include <array>
18 #include <fcntl.h>
19 #include <unistd.h>
20 #include <sys/wait.h>
21 
22 #include "common.h"
23 #include "hiebpf_plugin_config.pb.h"
24 #include "logging.h"
25 #include "plugin_module_api.h"
26 #include "trace_file_writer.h"
27 
28 namespace {
29 constexpr uint32_t MAX_BUFFER_SIZE = 4 * 1024 * 1024;
30 std::mutex g_taskMutex;
31 constexpr int32_t RET_OK = 0;
32 constexpr int32_t RET_ERR = -1;
33 bool g_releaseResources = false;
34 HiebpfConfig g_config;
35 std::shared_ptr<TraceFileWriter> g_splitTraceWriter {nullptr};
36 
RunCmd(std::string & cmd)37 void RunCmd(std::string& cmd)
38 {
39     std::unique_ptr<FILE, decltype(&pclose)> pipe(popen(cmd.c_str(), "r"), pclose);
40     if (pipe == nullptr) {
41         PROFILER_LOG_ERROR(LOG_CORE, "HiebpfPlugin::RunCmd: create popen FAILED!");
42         return;
43     }
44     constexpr uint32_t readBufferSize = 4096;
45     std::array<char, readBufferSize> buffer;
46     std::string result;
47     while (fgets(buffer.data(), buffer.size(), pipe.get()) != nullptr) {
48         result += buffer.data();
49     }
50     PROFILER_LOG_INFO(LOG_CORE, "HiebpfPlugin::run command result: %s", result.c_str());
51 }
52 } // namespace
53 
HiebpfSessionStart(const uint8_t * configData,uint32_t configSize)54 static int32_t HiebpfSessionStart(const uint8_t* configData, uint32_t configSize)
55 {
56     std::lock_guard<std::mutex> guard(g_taskMutex);
57     CHECK_TRUE(!g_releaseResources, 0, "%s: hiebpf released resources, return", __func__);
58     PROFILER_LOG_DEBUG(LOG_CORE, "enter");
59     if (configData == nullptr || configSize < 0) {
60         PROFILER_LOG_ERROR(LOG_CORE, "Parameter error");
61         return RET_ERR;
62     }
63 
64     CHECK_TRUE(g_config.ParseFromArray(configData, configSize) > 0, RET_ERR, "Parameter parsing failed");
65 
66     if (!g_config.split_outfile_name().empty()) {
67         g_splitTraceWriter = std::make_shared<TraceFileWriter>(g_config.split_outfile_name());
68         g_splitTraceWriter->WriteStandalonePluginData(
69             std::string(g_pluginModule.name) + "_config",
70             std::string(reinterpret_cast<const char *>(configData),
71                         configSize));
72         g_splitTraceWriter->SetTimeSource();
73     }
74 
75     size_t defaultSize = sizeof(g_pluginModule.outFileName);
76     CHECK_TRUE(sizeof(g_config.outfile_name().c_str()) <= defaultSize - 1, RET_ERR,
77                "The out file path more than %zu bytes", defaultSize);
78     int32_t ret = strncpy_s(g_pluginModule.outFileName, defaultSize, g_config.outfile_name().c_str(), defaultSize - 1);
79     CHECK_TRUE(ret == EOK, RET_ERR, "strncpy_s error! outfile is %s", g_config.outfile_name().c_str());
80     std::string cmd = g_config.cmd_line();
81     cmd += " --start true --output_file " + g_config.outfile_name();
82     RunCmd(cmd);
83     PROFILER_LOG_DEBUG(LOG_CORE, "leave");
84     return RET_OK;
85 }
86 
HiebpfSessionStop()87 static int32_t HiebpfSessionStop()
88 {
89     std::lock_guard<std::mutex> guard(g_taskMutex);
90     CHECK_TRUE(!g_releaseResources, 0, "%s: hiebpf released resources, return", __func__);
91     PROFILER_LOG_DEBUG(LOG_CORE, "enter");
92 
93     if (!g_config.split_outfile_name().empty()) {
94         CHECK_NOTNULL(g_splitTraceWriter, -1, "%s: writer is nullptr, SetDurationTime failed", __func__);
95         g_splitTraceWriter->SetDurationTime();
96     }
97 
98     std::string stop = "hiebpf --stop true";
99     RunCmd(stop);
100 
101     if (!g_config.split_outfile_name().empty()) { // write split file.
102         CHECK_NOTNULL(g_splitTraceWriter, -1, "%s: writer is nullptr, WriteStandaloneFile failed", __func__);
103         g_splitTraceWriter->WriteStandalonePluginFile(std::string(g_pluginModule.outFileName),
104             std::string(g_pluginModule.name), std::string(g_pluginModule.version), DataType::STANDALONE_DATA);
105         g_splitTraceWriter->Finish();
106         g_splitTraceWriter.reset();
107         g_splitTraceWriter = nullptr;
108     }
109     PROFILER_LOG_DEBUG(LOG_CORE, "leave");
110     return RET_OK;
111 }
112 
113 static PluginModuleCallbacks g_callbacks = {
114     .onPluginSessionStart = HiebpfSessionStart,
115     .onPluginReportResult = nullptr,
116     .onPluginSessionStop = HiebpfSessionStop,
117     .onRegisterWriterStruct = nullptr,
118 };
119 
120 EXPORT_API PluginModuleStruct g_pluginModule = {
121     .callbacks = &g_callbacks,
122     .name = "hiebpf-plugin",
123     .resultBufferSizeHint = MAX_BUFFER_SIZE,
124     .isStandaloneFileData = true,
125     .outFileName = "/data/local/tmp/hiebpf.data",
126 };