1 /*
2 * Copyright (c) 2024 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
16 #include "dfx_signalhandler_exception.h"
17
18 #include <stdio.h>
19 #include <sys/syscall.h>
20 #include <sys/socket.h>
21 #include <sys/time.h>
22 #include <sys/un.h>
23 #include <unistd.h>
24
25 #include "dfx_define.h"
26 #include "dfx_exception.h"
27 #include "errno.h"
28 #include "string.h"
29
30 #ifndef DFX_SIGNAL_LIBC
31 #include "dfx_log.h"
32 #else
33 #include "musl_log.h"
34 #endif
35
36 #ifdef LOG_DOMAIN
37 #undef LOG_DOMAIN
38 #define LOG_DOMAIN 0xD002D11
39 #endif
40
41 #ifdef LOG_TAG
42 #undef LOG_TAG
43 #define LOG_TAG "DfxSignalHandlerException"
44 #endif
45
46 static const int TIME_OUT = 2; /* seconds */
47 static const char FAULTLOGGERD_SOCKET_NAME[] = "/dev/unix/socket/faultloggerd.server";
48
ConnectSocket(const char * path,const int timeout)49 static int ConnectSocket(const char* path, const int timeout)
50 {
51 int fd = -1;
52 if ((fd = syscall(SYS_socket, AF_LOCAL, SOCK_STREAM, 0)) < 0) {
53 DFXLOGE("Failed to create a socket, errno(%{public}d).", errno);
54 return -1;
55 }
56
57 do {
58 if (timeout > 0) {
59 struct timeval timev = {
60 timeout,
61 0
62 };
63 void* pTimev = &timev;
64 if (OHOS_TEMP_FAILURE_RETRY(syscall(SYS_setsockopt, fd, SOL_SOCKET, SO_RCVTIMEO,
65 (const void*)(pTimev), sizeof(timev))) != 0) {
66 DFXLOGE("setsockopt SO_RCVTIMEO error, errno(%{public}d).", errno);
67 syscall(SYS_close, fd);
68 fd = -1;
69 break;
70 }
71 }
72 struct sockaddr_un server;
73 (void)memset(&server, 0, sizeof(server));
74 server.sun_family = AF_LOCAL;
75 (void)strncpy(server.sun_path, path, sizeof(server.sun_path) - 1);
76 int len = sizeof(server.sun_family) + strlen(server.sun_path);
77 int connected = OHOS_TEMP_FAILURE_RETRY(connect(fd, (struct sockaddr*)(&server), len));
78 if (connected < 0) {
79 DFXLOGE("Failed to connect to faultloggerd socket, errno = %{public}d.", errno);
80 syscall(SYS_close, fd);
81 fd = -1;
82 break;
83 }
84 } while (false);
85 return fd;
86 }
87
ReportException(struct CrashDumpException * exception)88 int ReportException(struct CrashDumpException* exception)
89 {
90 if (exception == NULL) {
91 return -1;
92 }
93 exception->head.clientType = REPORT_EXCEPTION_CLIENT;
94 exception->head.clientPid = getpid();
95 int ret = -1;
96 int fd = ConnectSocket(FAULTLOGGERD_SOCKET_NAME, TIME_OUT); // connect timeout
97 if (fd == -1) {
98 DFXLOGE("Failed to connect socket.");
99 return ret;
100 }
101 do {
102 if (OHOS_TEMP_FAILURE_RETRY(write(fd, exception, sizeof(struct CrashDumpException))) !=
103 (long)sizeof(struct CrashDumpException)) {
104 DFXLOGE("Failed to write request message to socket, errno(%{public}d).", errno);
105 break;
106 }
107 ret = 0;
108 } while (false);
109 syscall(SYS_close, fd);
110 return ret;
111 }
112