• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2023 Huawei Device Co., Ltd.
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  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 #include "faultloggerd_client.h"
16 
17 #include <cstdint>
18 
19 #include <securec.h>
20 #include <sys/un.h>
21 
22 #include "dfx_cutil.h"
23 #include "dfx_define.h"
24 #include "dfx_log.h"
25 #include "dfx_socket_request.h"
26 #include "dfx_util.h"
27 #include "faultloggerd_socket.h"
28 
29 using namespace OHOS::HiviewDFX;
30 namespace {
31 constexpr const char* const FAULTLOGGERD_CLIENT_TAG = "FAULT_LOGGERD_CLIENT";
32 constexpr int32_t SDKDUMP_SOCKET_TIMEOUT = 1;
33 constexpr int32_t COREDUMP_SOCKET_TIMEOUT = 5;
34 constexpr int32_t CRASHDUMP_SOCKET_TIMEOUT = 3;
GetSocketName()35 std::string GetSocketName()
36 {
37     char content[NAME_BUF_LEN];
38     GetProcessName(content, sizeof(content));
39     return strcmp(content, "processdump") == 0 ? SERVER_CRASH_SOCKET_NAME : SERVER_SOCKET_NAME;
40 }
41 
FillRequestHeadData(RequestDataHead & head,FaultLoggerClientType clientType)42 void FillRequestHeadData(RequestDataHead& head, FaultLoggerClientType clientType)
43 {
44     head.clientType = clientType;
45     head.clientPid = getpid();
46 }
47 
SendRequestToServer(const char * socketName,const SocketRequestData & socketRequestData,int32_t timeout,SocketFdData * socketFdData=nullptr,bool signalSafely=false)48 int32_t SendRequestToServer(const char* socketName, const SocketRequestData& socketRequestData, int32_t timeout,
49     SocketFdData* socketFdData = nullptr, bool signalSafely = false)
50 {
51     FaultLoggerdSocket faultLoggerdSocket(signalSafely);
52     int32_t retCode{ResponseCode::DEFAULT_ERROR_CODE};
53     if (!faultLoggerdSocket.CreateSocketFileDescriptor(timeout)) {
54         return ResponseCode::CONNECT_FAILED;
55     }
56     if (!faultLoggerdSocket.StartConnect(socketName)) {
57         retCode = ResponseCode::CONNECT_FAILED;
58     } else {
59         retCode = socketFdData ? faultLoggerdSocket.RequestFdsFromServer(socketRequestData, *socketFdData) :
60             faultLoggerdSocket.RequestServer(socketRequestData);
61     }
62     faultLoggerdSocket.CloseSocketFileDescriptor();
63     return retCode;
64 }
65 
RequestFileDescriptor(const struct FaultLoggerdRequest & request)66 int32_t RequestFileDescriptor(const struct FaultLoggerdRequest &request)
67 {
68     int32_t fd{-1};
69     SocketRequestData socketRequestData = {&request, sizeof(request)};
70     SocketFdData socketFdData = {&fd, 1};
71     switch (request.type) {
72         case FFRT_CRASH_LOG:
73             SendRequestToServer(SERVER_SOCKET_NAME, socketRequestData, CRASHDUMP_SOCKET_TIMEOUT,
74                 &socketFdData, true);
75             return fd;
76         case CPP_CRASH:
77         case CPP_STACKTRACE:
78         case LEAK_STACKTRACE:
79         case JIT_CODE_LOG:
80             SendRequestToServer(SERVER_CRASH_SOCKET_NAME, socketRequestData, CRASHDUMP_SOCKET_TIMEOUT, &socketFdData);
81             return fd;
82         default:
83             SendRequestToServer(SERVER_SOCKET_NAME, socketRequestData, CRASHDUMP_SOCKET_TIMEOUT, &socketFdData);
84             return fd;
85     }
86 }
87 }
88 
RequestFileDescriptor(int32_t type)89 int32_t RequestFileDescriptor(int32_t type)
90 {
91     struct FaultLoggerdRequest request{};
92     FillRequestHeadData(request.head, FaultLoggerClientType::LOG_FILE_DES_CLIENT);
93     request.type = type;
94     request.pid = request.head.clientPid;
95     request.tid = gettid();
96     request.time = OHOS::HiviewDFX::GetTimeMilliSeconds();
97     return RequestFileDescriptor(request);
98 }
99 
RequestFileDescriptorEx(struct FaultLoggerdRequest * request)100 int32_t RequestFileDescriptorEx(struct FaultLoggerdRequest* request)
101 {
102     if (request == nullptr) {
103         DFXLOGE("%{public}s.%{public}s :: RequestFileDescriptorEx nullptr.", FAULTLOGGERD_CLIENT_TAG, __func__);
104         return -1;
105     }
106     FillRequestHeadData(request->head, FaultLoggerClientType::LOG_FILE_DES_CLIENT);
107     return RequestFileDescriptor(*request);
108 }
109 
RequestSdkDump(int32_t pid,int32_t tid,int (& pipeReadFd)[2],bool isJson,int timeout)110 int32_t RequestSdkDump(int32_t pid, int32_t tid, int (&pipeReadFd)[2], bool isJson, int timeout)
111 {
112 #ifndef is_ohos_lite
113     DFXLOGI("%{public}s.%{public}s :: pid: %{public}d, tid: %{public}d, isJson: %{public}d.",
114         FAULTLOGGERD_CLIENT_TAG, __func__, pid, tid, isJson);
115     if (pid <= 0 || tid < 0) {
116         return ResponseCode::DEFAULT_ERROR_CODE;
117     }
118     struct SdkDumpRequestData request{};
119     FillRequestHeadData(request.head, FaultLoggerClientType::SDK_DUMP_CLIENT);
120     request.sigCode = isJson ? DUMP_TYPE_REMOTE_JSON : DUMP_TYPE_REMOTE;
121     request.pid = pid;
122     request.tid = tid;
123     request.callerTid = gettid();
124     request.time = OHOS::HiviewDFX::GetTimeMilliSeconds();
125     request.endTime = GetAbsTimeMilliSeconds() + static_cast<uint64_t>(timeout);
126     SocketRequestData socketRequestData = {&request, sizeof(request)};
127     SocketFdData socketFdData = {pipeReadFd, PIPE_NUM_SZ};
128     return SendRequestToServer(SERVER_SDKDUMP_SOCKET_NAME, socketRequestData, SDKDUMP_SOCKET_TIMEOUT, &socketFdData);
129 #else
130     return ResponseCode::DEFAULT_ERROR_CODE;
131 #endif
132 }
133 
RequestLitePerfPipeFd(int32_t pipeType,int (& pipeFd)[2],int timeout)134 int32_t RequestLitePerfPipeFd(int32_t pipeType, int (&pipeFd)[2], int timeout)
135 {
136 #ifndef is_ohos_lite
137     if (pipeType < FaultLoggerPipeType::PIPE_FD_READ || pipeType > FaultLoggerPipeType::PIPE_FD_DELETE) {
138         DFXLOGE("%{public}s.%{public}s :: pipeType: %{public}d failed.", FAULTLOGGERD_CLIENT_TAG, __func__, pipeType);
139         return ResponseCode::DEFAULT_ERROR_CODE;
140     }
141     DFXLOGI("%{public}s.%{public}s :: pipeType: %{public}d.", FAULTLOGGERD_CLIENT_TAG, __func__, pipeType);
142     LitePerfFdRequestData request{};
143     FillRequestHeadData(request.head, FaultLoggerClientType::PIPE_FD_LITEPERF_CLIENT);
144     request.pipeType = static_cast<int8_t>(pipeType);
145     request.pid = getpid();
146     request.uid = getuid();
147     request.timeout = timeout;
148     SocketRequestData socketRequestData = {&request, sizeof(request)};
149     SocketFdData socketFdData = {pipeFd, PIPE_NUM_SZ};
150     return SendRequestToServer(GetSocketName().c_str(), socketRequestData, CRASHDUMP_SOCKET_TIMEOUT, &socketFdData);
151 #else
152     return ResponseCode::DEFAULT_ERROR_CODE;
153 #endif
154 }
155 
RequestLitePerfDelPipeFd()156 int32_t RequestLitePerfDelPipeFd()
157 {
158 #ifndef is_ohos_lite
159     LitePerfFdRequestData request{};
160     FillRequestHeadData(request.head, FaultLoggerClientType::PIPE_FD_LITEPERF_CLIENT);
161     request.pipeType = FaultLoggerPipeType::PIPE_FD_DELETE;
162     request.pid = getpid();
163     request.uid = getuid();
164     return SendRequestToServer(GetSocketName().c_str(), {&request, sizeof(request)}, SDKDUMP_SOCKET_TIMEOUT);
165 #else
166     return ResponseCode::DEFAULT_ERROR_CODE;
167 #endif
168 }
169 
RequestPipeFd(int32_t pid,int32_t pipeType,int (& pipeFd)[2])170 int32_t RequestPipeFd(int32_t pid, int32_t pipeType, int (&pipeFd)[2])
171 {
172 #ifndef is_ohos_lite
173     if (pipeType < FaultLoggerPipeType::PIPE_FD_READ || pipeType > FaultLoggerPipeType::PIPE_FD_DELETE) {
174         DFXLOGE("%{public}s.%{public}s :: pipeType: %{public}d failed.", FAULTLOGGERD_CLIENT_TAG, __func__, pipeType);
175         return ResponseCode::DEFAULT_ERROR_CODE;
176     }
177     PipFdRequestData request{};
178     FillRequestHeadData(request.head, FaultLoggerClientType::PIPE_FD_CLIENT);
179     request.pipeType = static_cast<int8_t>(pipeType);
180     request.pid = pid;
181     SocketRequestData socketRequestData = {&request, sizeof(request)};
182     SocketFdData socketFdData = {pipeFd, PIPE_NUM_SZ};
183     return SendRequestToServer(GetSocketName().c_str(), socketRequestData, CRASHDUMP_SOCKET_TIMEOUT, &socketFdData);
184 #else
185     return ResponseCode::DEFAULT_ERROR_CODE;
186 #endif
187 }
188 
RequestDelPipeFd(int32_t pid)189 int32_t RequestDelPipeFd(int32_t pid)
190 {
191 #ifndef is_ohos_lite
192     PipFdRequestData request{};
193     FillRequestHeadData(request.head, FaultLoggerClientType::PIPE_FD_CLIENT);
194     request.pipeType = FaultLoggerPipeType::PIPE_FD_DELETE;
195     request.pid = pid;
196     return SendRequestToServer(GetSocketName().c_str(), {&request, sizeof(request)}, SDKDUMP_SOCKET_TIMEOUT);
197 #else
198     return ResponseCode::DEFAULT_ERROR_CODE;
199 #endif
200 }
201 
ReportDumpStats(struct FaultLoggerdStatsRequest * request)202 int32_t ReportDumpStats(struct FaultLoggerdStatsRequest *request)
203 {
204     if (request == nullptr) {
205         return ResponseCode::DEFAULT_ERROR_CODE;
206     }
207     int32_t retCode{ResponseCode::REQUEST_SUCCESS};
208 #ifndef HISYSEVENT_DISABLE
209     FillRequestHeadData(request->head, FaultLoggerClientType::DUMP_STATS_CLIENT);
210     FaultLoggerdSocket faultLoggerdSocket;
211     if (!faultLoggerdSocket.CreateSocketFileDescriptor(SDKDUMP_SOCKET_TIMEOUT)) {
212         return ResponseCode::CONNECT_FAILED;
213     }
214     if (!faultLoggerdSocket.StartConnect(GetSocketName().c_str())) {
215         retCode = ResponseCode::CONNECT_FAILED;
216     } else if (!faultLoggerdSocket.SendMsgToSocket(request, sizeof (FaultLoggerdStatsRequest))) {
217         retCode = ResponseCode::SEND_DATA_FAILED;
218     }
219     faultLoggerdSocket.CloseSocketFileDescriptor();
220 #endif
221     return retCode;
222 }
223 
SaveCoredumpToFileTimeout(int32_t targetPid,int timeout)224 std::string SaveCoredumpToFileTimeout(int32_t targetPid, int timeout)
225 {
226 #ifndef is_ohos_lite
227     DFXLOGI("%{public}s.%{public}s :: pid: %{public}d.", FAULTLOGGERD_CLIENT_TAG, __func__, targetPid);
228     if (targetPid <= 0) {
229         return "";
230     }
231 
232     struct CoreDumpRequestData request{};
233     FillRequestHeadData(request.head, FaultLoggerClientType::COREDUMP_CLIENT);
234     request.pid = targetPid;
235     request.endTime = GetAbsTimeMilliSeconds() + static_cast<uint64_t>(timeout);
236     request.coredumpAction = CoreDumpAction::DO_CORE_DUMP;
237 
238     SocketRequestData socketRequestData = {&request, sizeof(request)};
239     FaultLoggerdSocket faultLoggerdSocket;
240     int32_t retCode{ResponseCode::DEFAULT_ERROR_CODE};
241     if (!faultLoggerdSocket.CreateSocketFileDescriptor(COREDUMP_SOCKET_TIMEOUT)) {
242         DFXLOGE("%{public}s create socket fail", __func__);
243         return "";
244     }
245     if (!faultLoggerdSocket.StartConnect(SERVER_SOCKET_NAME)) {
246         retCode = ResponseCode::CONNECT_FAILED;
247     } else {
248         retCode = faultLoggerdSocket.RequestServer(socketRequestData);
249     }
250     if (retCode != ResponseCode::REQUEST_SUCCESS) {
251         DFXLOGE("%{public}s connect server fail, retCode : %{public}d", __func__, retCode);
252         return "";
253     }
254     DFXLOGI("%{public}s connect request retCode : %{public}d", __func__, retCode);
255     CoreDumpResult coredumpResult = {"", ResponseCode::RECEIVE_DATA_FAILED};
256     faultLoggerdSocket.GetMsgFromSocket(&coredumpResult, sizeof(coredumpResult));
257 
258     DFXLOGI("%{public}s has received retCode : %{public}d and filename: %{public}s", __func__,
259             coredumpResult.retCode, coredumpResult.fileName);
260     return coredumpResult.fileName;
261 #else
262     return "";
263 #endif
264 }
265 
CancelCoredump(int32_t targetPid)266 int32_t CancelCoredump(int32_t targetPid)
267 {
268 #ifndef is_ohos_lite
269     DFXLOGI("%{public}s.%{public}s :: pid: %{public}d.", FAULTLOGGERD_CLIENT_TAG, __func__, targetPid);
270     if (targetPid <= 0) {
271         return ResponseCode::DEFAULT_ERROR_CODE;
272     }
273 
274     struct CoreDumpRequestData request{};
275     FillRequestHeadData(request.head, FaultLoggerClientType::COREDUMP_CLIENT);
276     request.pid = targetPid;
277     request.coredumpAction = CoreDumpAction::CANCEL_CORE_DUMP;
278 
279     SocketRequestData socketRequestData = {&request, sizeof(request)};
280     int32_t retCode =
281         SendRequestToServer(SERVER_SOCKET_NAME, socketRequestData, COREDUMP_SOCKET_TIMEOUT);
282 
283     DFXLOGI("%{public}s has received retcode : %{public}d %{public}d", __func__, retCode, __LINE__);
284     return retCode;
285 #else
286     return ResponseCode::DEFAULT_ERROR_CODE;
287 #endif
288 }
289 
StartCoredumpCb(int32_t targetPid,int32_t processDumpPid)290 int32_t StartCoredumpCb(int32_t targetPid, int32_t processDumpPid)
291 {
292 #ifndef is_ohos_lite
293     DFXLOGI("%{public}s.%{public}s :: targetpid: %{public}d, processDumpPid: %{public}d.",
294         FAULTLOGGERD_CLIENT_TAG, __func__, targetPid, processDumpPid);
295     if (targetPid <= 0 || processDumpPid <= 0) {
296         return ResponseCode::DEFAULT_ERROR_CODE;
297     }
298 
299     struct CoreDumpStatusData request{};
300     FillRequestHeadData(request.head, FaultLoggerClientType::COREDUMP_PROCESS_DUMP_CLIENT);
301     request.pid = targetPid;
302     request.processDumpPid = processDumpPid;
303     request.coredumpStatus = CoreDumpStatus::CORE_DUMP_START;
304 
305     SocketRequestData socketRequestData = {&request, sizeof(request)};
306     int32_t retCode =
307         SendRequestToServer(SERVER_SOCKET_NAME, socketRequestData, COREDUMP_SOCKET_TIMEOUT);
308 
309     DFXLOGI("%{public}s has received retcode : %{public}d %{public}d", __func__, retCode, __LINE__);
310     return retCode;
311 #else
312     return ResponseCode::DEFAULT_ERROR_CODE;
313 #endif
314 }
315 
FinishCoredumpCb(int32_t targetPid,std::string & fileName,int32_t ret)316 int32_t FinishCoredumpCb(int32_t targetPid, std::string& fileName, int32_t ret)
317 {
318 #ifndef is_ohos_lite
319     DFXLOGI("%{public}s.%{public}s :: targetpid: %{public}d.",
320         FAULTLOGGERD_CLIENT_TAG, __func__, targetPid);
321     if (targetPid <= 0) {
322         return ResponseCode::DEFAULT_ERROR_CODE;
323     }
324 
325     struct CoreDumpStatusData request{};
326     FillRequestHeadData(request.head, FaultLoggerClientType::COREDUMP_PROCESS_DUMP_CLIENT);
327     request.pid = targetPid;
328     request.coredumpStatus = CoreDumpStatus::CORE_DUMP_END;
329     request.retCode = ret;
330     if (strncpy_s(request.fileName, sizeof(request.fileName), fileName.c_str(), sizeof(request.fileName) - 1) != 0) {
331         DFXLOGE("%{public}s :: strncpy failed.", __func__);
332         return ResponseCode::DEFAULT_ERROR_CODE;
333     }
334 
335     SocketRequestData socketRequestData = {&request, sizeof(request)};
336     int32_t retCode =
337         SendRequestToServer(SERVER_SOCKET_NAME, socketRequestData, COREDUMP_SOCKET_TIMEOUT);
338 
339     DFXLOGI("%{public}s has received retcode : %{public}d %{public}d", __func__, retCode, __LINE__);
340     return retCode;
341 #else
342     return ResponseCode::DEFAULT_ERROR_CODE;
343 #endif
344 }