• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# FaultLogger Development
2
3
4## Overview
5
6
7### Function Introduction
8
9FaultLogger is a maintenance and debugging log framework provided by OpenHarmony. It enables unified detection, log collection, log storage, and log reporting for application, ability, and system service process crashes. It is available for the standard system and the Linux kernel-based small system.
10
11FaultLogger is responsible for fault recording of OpenHarmony. It runs on the following two components based on the service object:
12
13- Hiview: serves functional modules at the application layer and native layer. It manages various fault information in the system and provides APIs for modules to query faults.
14
15- Faultloggerd: serves the crash process. It collects information about the abnormal daemon process in C/C++ and obtains call stack information of the process.
16
17The following figure shows the process of handling a process crash based on the FaultLogger service.
18
19  **Figure 1** Process crash handling flowchart
20
21![Process crash handling flowchart](figures/process_crash_handling_flowchart.png)
22
231. After the signal processor is installed, SignalHandler uses the **DFX_SignalHandler** function to detect and respond to the process crash exception signal thrown by the kernel.
24
252. When detecting a process crash exception signal, SignalHandler forks a child process and runs ProcessDump to dump the stack information of the crashed process and thread.
26
273. ProcessDump applies to Faultloggerd for a file handle for storing fault logs. After reading the exception stack information, ProcessDump writes the information to the file to generate a complete crash log.
28
294. After collecting the complete crash log, ProcessDump reports the log to Hiview by using the **AddFaultLog()** API. Hiview generates a simplified crash log and reports a system event through HiSysEvent.
30
31With this design, a small-system with limited resources can obtain logs for locating crash faults as long as Faultloggerd is deployed.
32
33
34### Use Cases
35
36Faultloggerd provides a lightweight approach for you to locate crash or suspension problems during development and testing.
37
38The following table describes the application scenarios.
39
40  **Table 1** Application scenarios of the Faultloggerd module
41
42| Scenario| Tool| Usage|
43| -------- | -------- | -------- |
44| Understanding of the function call sequence| DumpCatcher API |  See [Using DumpCatcher APIs to Obtain Call Stack Information](#using-dumpcatcher-apis-to-obtain-call-stack-information).|
45| Application suspension or high CPU usage| DumpCatcher Command Tool |  See [Using DumpCatcher Commands to Obtain Call Stack Information](#using-dumpcatcher-commands-to-obtain-call-stack-information).|
46| Crash fault location| Crash log and addr2line tool| For details, see [Locating Faults Based on the Crash Log](#locating-faults-based-on-the-crash-log).|
47
48
49## Using DumpCatcher APIs to Obtain Call Stack Information
50
51
52### Available APIs
53
54DumpCatcher can capture the call stack information of the specified process (thread) on OpenHarmony.
55
56  **Table 2** DumpCatcher APIs
57
58| Class| API| Description|
59| -------- | -------- | -------- |
60| DfxDumpCatcher | bool DumpCatch(const int pid, const int tid, std::string&amp; msg) |   Return value:<br>- **true**: Dumping of stack information is successful. Related information is stored in the msg string object.<br>- **false**: Dumping of stack information has failed.<br>  Input arguments:<br>- **pid**: target process ID.<br>- **tid**: target thread ID. If all threads in the process need to be back traced, set **tid** to **0**.<br>  Output arguments:<br>- **msg**: If back trace is successful, call stack information is returned through **msg**.|
61| DfxDumpCatcher | bool DumpCatchMix(const int pid, const int tid, std::string&amp; msg) |   Return value:<br>- **true**: Dumping of stack information is successful. Related information is stored in the msg string object.<br>- **false**: Dumping of stack information has failed.<br>  Input arguments:<br>**pid**: target process ID.<br>- **tid**: target thread ID. If all threads in the process need to be back traced, set **tid** to **0**.<br>  Output arguments:<br>- **msg**: If back trace is successful, hybrid stack information is returned through **msg**.|
62| DfxDumpCatcher | bool DumpCatchFd(const int pid, const int tid, std::string&amp; msg, int fd) |   Return value:<br>- **true**: Dumping of stack information is successful. Related information is stored in the msg string object.<br>- **false**: Dumping of stack information has failed.<br>  Input arguments:<br>**pid**: target process ID.<br>- **tid**: target thread ID. If all threads in the process need to be back traced, set **tid** to **0**.<br>- **fd**: handle of the file to be written.<br>  Output parameters:<br>- **msg**: If back trace is successful, call stack information is returned through **msg**.|
63| DfxDumpCatcher | bool DumpCatchMultiPid(const std::vector\<int> pidV, std::string&amp; msg) |   Return value:<br>- **true**: Dumping of stack information is successful. Related information is stored in the msg string object.<br>- **false**: Dumping of stack information has failed.<br>  Input arguments:<br>- **pidV**: target process ID list.<br>  Output arguments:<br>- **msg**: If back trace is successful, call stack information is returned through **msg**.|
64
65> **NOTE**
66> If the PID that calls this API is different from the target PID, the caller must be the **system** or **root** user.
67
68
69### How to Develop
70
71
72You can use DumpCatcher to obtain call stack information for the specified process (thread) of an application. The following uses the **dumpcatcherdemo** module as an example to describe how to use the DumpCatcher APIs to obtain the call stack information.
73
74
751. Add the DumpCatcher dependency to the build file. Take /base/hiviewdfx/faultloggerd/example/BUILD.gn as an example. Add the **dump_catcher.h** file path to **include_dirs** and add the required **//base/hiviewdfx/faultloggerd/interfaces/innerkits/dump_catcher:lib_dfx_dump_catcher** module to **deps**.
76
77   ```
78   import("//base/hiviewdfx/faultloggerd/faultloggerd.gni")
79   import("//build/ohos.gni")
80
81   config("dumpcatcherdemo_config") {
82     visibility = [ ":*" ]
83
84     include_dirs = [
85       ".",
86       "//utils/native/base/include",
87       "//base/hiviewdfx/faultloggerd/interfaces/innerkits/dump_catcher/include/",  # Add the path of the dump_catcher header file.
88     ]
89   }
90
91   ohos_executable("dumpcatcherdemo") {
92    sources = [ "dump_catcher_demo.cpp" ]
93    configs = [ ":dumpcatcherdemo_config" ]
94    deps = [
95      "//base/hiviewdfx/faultloggerd/interfaces/innerkits/dump_catcher:lib_dfx_dump_catcher", # Add the DumpCatcher module dependency.
96      "//utils/native/base:utils",
97    ]
98    external_deps = [ "hilog_native:libhilog" ]
99    install_enable = true
100    part_name = "faultloggerd"
101    subsystem_name = "hiviewdfx"
102   }
103   ```
104
1052. Define the header file. Take **/base/hiviewdfx/faultloggerd/example/dump_catcher_demo.h** as an example. In the sample code, the function of the stack depth test is called to construct a call stack with a specified depth.
106
107   ```
108   #ifndef DUMP_CATCHER_DEMO_H
109   #define DUMP_CATCHER_DEMO_H
110
111   #include <inttypes.h>
112
113   #define NOINLINE __attribute__((noinline))
114
115   // Define the macro function to automatically generate a function call chain.
116   #define GEN_TEST_FUNCTION(FuncNumA, FuncNumB)          \
117       __attribute__((noinline)) int TestFunc##FuncNumA() \
118       {                                                  \
119           return TestFunc##FuncNumB();                   \
120       }
121
122   // Call the function of the stack depth test.
123   int TestFunc0(void);
124   int TestFunc1(void);
125   int TestFunc2(void);
126   int TestFunc3(void);
127   int TestFunc4(void);
128   int TestFunc5(void);
129   int TestFunc6(void);
130   int TestFunc7(void);
131   int TestFunc8(void);
132   int TestFunc9(void);
133   int TestFunc10(void);
134
135   #endif // DUMP_CATCHER_DEMO_H
136   ```
137
1383. Call the **DumpCatch** API in the source file. Take **/base/hiviewdfx/faultloggerd/example/dump_catcher_demo.cpp** as an example. Include the **dfx_dump_catcher.h** file, declare the **DfxDumpCatcher** object, use the macro function to construct a function call chain, call the **DumpCatch** method, and pass the required process ID and thread ID of the call stack into this method.
139
140   ```
141   #include "dump_catcher_demo.h"
142
143   #include <iostream>
144   #include <string>
145   #include <unistd.h>
146   // Include the dfx_dump_catcher.h file.
147   #include "dfx_dump_catcher.h"
148   using namespace std;
149
150   NOINLINE int TestFunc10(void)
151   {
152       OHOS::HiviewDFX::DfxDumpCatcher dumplog;
153       string msg = "";
154       bool ret = dumplog.DumpCatch(getpid(), gettid(), msg);  // Call the DumpCatch API to obtain the call stack information.
155       if (ret) {
156           cout << msg << endl;
157       }
158       return 0;
159   }
160
161   // Use the macro function to automatically generate a function call chain.
162   GEN_TEST_FUNCTION(0, 1)
163   GEN_TEST_FUNCTION(1, 2)
164   GEN_TEST_FUNCTION(2, 3)
165   GEN_TEST_FUNCTION(3, 4)
166   GEN_TEST_FUNCTION(4, 5)
167   GEN_TEST_FUNCTION(5, 6)
168   GEN_TEST_FUNCTION(6, 7)
169   GEN_TEST_FUNCTION(7, 8)
170   GEN_TEST_FUNCTION(8, 9)
171   GEN_TEST_FUNCTION(9, 10)
172
173   int main(int argc, char *argv[])
174   {
175       TestFunc0();
176       return 0;
177   }
178   ```
179
180
181## Using DumpCatcher Commands to Obtain Call Stack Information
182
183
184### Tool Description
185
186DumpCatcher Command Tool is a command line interface (CLI)-based tool for capturing call stack information on OpenHarmony. It uses the **-p** and **-t** parameters to specify the process and thread. After the command is executed, the thread stack information of the specified process is displayed in the CLI window. By specifying the **-m** parameter, you can also capture the JS and Native hybrid stack information of an application process.
187
188  **Table 3** Usage of the DumpCatcher Command Tool
189
190| Tool| Path| Command| Description|
191| -------- | -------- | -------- | -------- |
192| dumpcatcher | /system/bin | - dumpcatcher -p [pid]<br>- dumpcatcher -p [pid] -t [tid]<br>- dumpcatcher -m -p [pid]<br>- dumpcatcher -m -p [pid] -t [tid]<br>| **Description:**<br>- **-p [pid]**: prints all thread stack information of the specified process.<br>- **-p [pid] -t [tid]**: prints stack information for the specified thread of the specified process.<br>- **-m -p [pid]**: prints hybrid stack information for all threads of the specified process.<br>- **-m -p [pid] -t [tid]**: prints hybrid stack information for the specified thread of the specified process.<br>**Return value:**<br>If the stack information is parsed successfully, the information is displayed in the standard output. If the stack information fails to be parsed, error information is displayed.|
193
194
195### Development Example
196
197Print call stack information of the **hiview** process.
198
199
200```
201# ps -ef |grep hiview
202hiview         240     1 0 17:01:49 ?     00:00:14 hiview
203root          1822  1560 7 20:56:36 pts/0 00:00:00 grep hiview
204# dumpcatcher -p 240 -t 240
205Result: 0 ( no error )
206Timestamp:2017-08-05 20:56:43.000
207Pid:240
208Uid:1201
209Process name:/system/bin/hiview
210Tid:240, Name:hiview
211#00 pc 00098f8c /system/lib/ld-musl-arm.so.1(ioctl+68)
212#01 pc 0000e2a1 /system/lib/chipset-pub-sdk/libipc_single.z.so
213#02 pc 0000ed59 /system/lib/chipset-pub-sdk/libipc_single.z.so
214#03 pc 0000ee1f /system/lib/chipset-pub-sdk/libipc_single.z.so
215#04 pc 0000f745 /system/lib/chipset-pub-sdk/libipc_single.z.so
216#05 pc 00037577 /system/bin/hiview
217#06 pc 00025973 /system/bin/hiview
218#07 pc 000db210 /system/lib/ld-musl-arm.so.1
219#08 pc 000258d8 /system/bin/hiview
220#09 pc 0002587c /system/bin/hiview
221```
222
223
224## Locating Faults Based on the Crash Log
225
226You can locate faults based on the crash stack logs generated by Faultloggerd. This section describes how to use the addr2line tool to locate a crash fault.
227
2281. Find a program crash or construct a crash.
229   For example, insert the following code into your code to trigger an invalid memory access fault (SIGSEGV).
230
231
232   ```
233   NOINLINE int TriggerSegmentFaultException()
234   {
235       printf("test TriggerSegmentFaultException \n");
236       // Forcibly convert the type to construct a crash.
237       int *a = (int *)(&RaiseAbort);
238       *a = SIGSEGV;
239       return 0;
240   }
241   ```
242
2432. Obtain the crash function call stack log.
244   The process generates a temporary log file in the** /data/log/faultlog/temp** directory due to an exception that is not handled. The naming rule of the temporary log file is as follows:
245
246
247   ```
248   cppcrash-pid-time
249   ```
250
251   The generated call stack information is as follows:
252
253
254   ```
255   Timestamp:2017-08-05 17:35:03.000
256   Pid:816
257   Uid:0
258   Process name:./crasher_c
259   Reason:Signal:SIGSEGV(SEGV_ACCERR)@0x0042d33d
260   Fault thread Info:
261   Tid:816, Name:crasher
262   #00 pc 0000332c /data/crasher(TriggerSegmentFaultException+15)(8bc37ceb8d6169e919d178fdc7f5449e)
263   #01 pc 000035c7 /data/crasher(ParseAndDoCrash+277)(8bc37ceb8d6169e919d178fdc7f5449e)
264   #02 pc 00003689 /data/crasher(main+39)(8bc37ceb8d6169e919d178fdc7f5449e)
265   #03 pc 000c3b08 /system/lib/ld-musl-arm.so.1(__libc_start_main+116)
266   #04 pc 000032f8 /data/crasher(_start_c+112)(8bc37ceb8d6169e919d178fdc7f5449e)
267   #05 pc 00003284 /data/crasher(_start+32)(8bc37ceb8d6169e919d178fdc7f5449e)
268   Registers:
269   r0:0042d33d r1:0000000b r2:1725d4c4 r3:b6f9fa84
270   r4:bec97e69 r5:b6fc0268 r6:0042d661 r7:bec97d60
271   r8:00000000 r9:00000000 r10:00000000
272   fp:bec97d20 ip:00000020 sp:bec97cd0 lr:b6f9fae4 pc:0042d32c
273   ```
274
2753. Use the addr2line tool to analyze the call stack information.
276   Then, parse the line number based on the offset address.
277
278
279   ```
280   root:~/OpenHarmony/out/hi3516dv300/exe.unstripped/hiviewdfx/faultloggerd$ addr2line -e crasher 0000332c
281   base/hiviewdfx/faultloggerd/tools/crasher/dfx_crasher.c:57
282   ```
283
284   The crash is caused by assigning a value to an unwritable area. It is in code line 57 in the **dfx_crasher.c** file. You can modify it to avoid the crash.
285