1Title: A common fatal error and assert fail handler 2 3Description: 4 5These two common handlers are developed in order to reduce the redundancy 6code writing for fatal and assert handler for error case testing. They can 7be used both in kernel and userspace, and they are also SMP safe. 8 9 10Why doing this 11============== 12 13When writing error testing case (or we call it negative test case), we might 14have to write self-defined k_sys_fatal_handler or post_assert_handler to deal 15with the errors we caught, in order to make the test continue. This means much 16identical code would be written. So we try to move the error handler definition 17into a common part and let other test suites or applications reuse it, instead 18of defining their own. 19 20And when error happens, we sometimes need a special action to make our testing 21program return back to normal, such as releasing some resource hold before the 22error happened. This is why we add a hook on it, in order to achieve that goal. 23 24 25How to use it in you app 26======================== 27 28(a) Usage for dealing with fatal error: 29 30Step1: Add CONFIG_ZTEST_FATAL_HOOK=y into prj.conf 31 32Step2: Include <ztest_fatal_hook.h> in C source file. 33 34Step3: (optional) Define a hook function call ztest_post_fatal_error_hook(). 35 36Step4: Call ztest_set_fault_valid(true) before where your target function 37 call. 38 39 40(b) Usage for dealing with assert fail: 41 42Step1: Add CONFIG_ZTEST_ASSERT_HOOK=y into prj.conf 43 44Step2: Include <zephyr/ztest_error_hook.h> in your C code. 45 46Step3: (optional) Define a hook function call ztest_post_assert_fail_hook(). 47 48Step4: call ztest_set_assert_valid(true) before where your target function 49 call. 50 51 52You can choose to use one or both of them, depending on your needs. 53If you use none of them, you can still define your own fatal or assert handler 54as usual. 55 56 57Test example in this test set 58============================= 59 60This test verifies if the common fatal error and assert fail handler works. 61If the expected error was caught, the test case will pass. 62 63test_catch_assert_fail 64 - To call a function then giving the condition to trigger the assert fail, 65 then catch it by the assert handler. 66 67test_catch_fatal_error 68 - start a thread to test triggering a null address dereferencing, then catch 69 the (expected) fatal error. 70 - start a thread to test triggering an illegal instruction, then catch 71 the (expected) fatal error. 72 - start a thread to test triggering a divide-by-zero error, then catch 73 the (expected) fatal error. 74 - start a thread to call k_oops() then catch the (expected) fatal error. 75 - start a thread to call k_panel() then catch the (expected) fatal error. 76 77test_catch_assert_in_isr 78 - start a thread to enter ISR context by calling irq_offload(), then trigger 79 an assert fail then catch it. 80 81test_catch_z_oops 82 - Pass illegal address by syscall, then inside the syscall handler, the 83 K_OOPS macro will trigger a fatal error that will get caught (as expected). 84 85 86 87Limitation of this usage 88======================== 89 90Trigger a fatal error in ISR context, that will cause problem due to 91the interrupt stack is already abnormal when we want to continue other 92test case, we do not recover it so far. 93 94 95--------------------------------------------------------------------------- 96 97Sample Output: 98 99Running test suite error_hook_tests 100=================================================================== 101START - test_catch_assert_fail 102ASSERTION FAIL [a != ((void *)0)] @ WEST_TOPDIR/zephyr/tests/ztest/error_hook/src/main.c:41 103 parameter a should not be NULL! 104Caught assert failed 105Assert error expected as part of test case. 106 PASS - test_catch_assert_fail 107=================================================================== 108START - test_catch_fatal_error 109case type is 0 110E: Page fault at address (nil) (error code 0x4) 111E: Linear address not present in page tables 112E: Access violation: user thread not allowed to read 113E: PTE: not present 114E: EAX: 0x00000000, EBX: 0x00000000, ECX: 0x00000000, EDX: 0x0010fe51 115E: ESI: 0x00000000, EDI: 0x0012dfe8, EBP: 0x0012dfcc, ESP: 0x0012dfc4 116E: EFLAGS: 0x00000246 CS: 0x002b CR3: 0x001142c0 117E: call trace: 118E: EIP: 0x00100439 119E: 0x001010ea (0x113068) 120E: >>> ZEPHYR FATAL ERROR 0: CPU exception on CPU 0 121E: Current thread: 0x114000 (unknown) 122Caught system error -- reason 0 1 123Fatal error expected as part of test case. 124case type is 1 125E: Page fault at address 0x12dfc4 (error code 0x15) 126E: Access violation: user thread not allowed to execute 127E: PTE: 0x12d000 -> 0x000000000012d000: RW US A D XD 128E: EAX: 0x0012dfc4, EBX: 0x00000001, ECX: 0x00000001, EDX: 0x0010fe51 129E: ESI: 0x00000000, EDI: 0x0012dfe8, EBP: 0x0012dfcc, ESP: 0x0012dfc0 130E: EFLAGS: 0x00000246 CS: 0x002b CR3: 0x001142c0 131E: call trace: 132E: EIP: 0x0012dfc4 133E: 0x001010ea (0x113068) 134E: >>> ZEPHYR FATAL ERROR 0: CPU exception on CPU 0 135E: Current thread: 0x114000 (unknown) 136Caught system error -- reason 0 1 137Fatal error expected as part of test case. 138case type is 2 139E: Invalid opcode 140E: EAX: 0x00000000, EBX: 0x00000002, ECX: 0x00000002, EDX: 0x0010fe51 141E: ESI: 0x00000000, EDI: 0x0012dfe8, EBP: 0x0012dfcc, ESP: 0x0012dfc4 142E: EFLAGS: 0x00000246 CS: 0x002b CR3: 0x001142c0 143E: call trace: 144E: EIP: 0x00100451 145E: 0x001010ea (0x113068) 146E: >>> ZEPHYR FATAL ERROR 0: CPU exception on CPU 0 147E: Current thread: 0x114000 (unknown) 148Caught system error -- reason 0 1 149Fatal error expected as part of test case. 150case type is 3 151E: EAX: 0x00000000, EBX: 0x00000003, ECX: 0x00000003, EDX: 0x0010fe51 152E: ESI: 0x00000000, EDI: 0x0012dfe8, EBP: 0x0012dfcc, ESP: 0x0012dfc0 153E: EFLAGS: 0x00000246 CS: 0x002b CR3: 0x001142c0 154E: call trace: 155E: EIP: 0x0010045c 156E: 0x001010ea (0x113068) 157E: >>> ZEPHYR FATAL ERROR 3: Kernel oops on CPU 0 158E: Current thread: 0x114000 (unknown) 159Caught system error -- reason 3 1 160Fatal error expected as part of test case. 161case type is 4 162E: EAX: 0x00000000, EBX: 0x00000004, ECX: 0x00000004, EDX: 0x0010fe51 163E: ESI: 0x00000000, EDI: 0x0012dfe8, EBP: 0x0012dfcc, ESP: 0x0012dfc0 164E: EFLAGS: 0x00000246 CS: 0x002b CR3: 0x001142c0 165E: call trace: 166E: EIP: 0x00100465 167E: 0x001010ea (0x113068) 168E: >>> ZEPHYR FATAL ERROR 3: Kernel oops on CPU 0 169E: Current thread: 0x114000 (unknown) 170Caught system error -- reason 3 1 171Fatal error expected as part of test case. 172 PASS - test_catch_fatal_error 173=================================================================== 174START - test_catch_assert_in_isr 175ASSERTION FAIL [a != ((void *)0)] @ WEST_TOPDIR/zephyr/tests/ztest/error_hook/src/main.c:41 176 parameter a should not be NULL! 177Caught assert failed 178Assert error expected as part of test case. 179 PASS - test_catch_assert_in_isr 180=================================================================== 181START - test_catch_z_oops 182E: EAX: 0x00000000, EBX: 0x00000000, ECX: 0x00000000, EDX: 0x00000000 183E: ESI: 0x00000000, EDI: 0x00000000, EBP: 0x00000000, ESP: 0x00000000 184E: EFLAGS: 0x001003c4 CS: 0x0511 CR3: 0x00115740 185E: call trace: 186E: EIP: 0x0010ff9e 187E: NULL base ptr 188E: >>> ZEPHYR FATAL ERROR 3: Kernel oops on CPU 0 189E: Current thread: 0x114120 (unknown) 190Caught system error -- reason 3 1 191Fatal error expected as part of test case. 192 PASS - test_catch_z_oops 193=================================================================== 194Test suite error_hook_tests succeeded 195=================================================================== 196PROJECT EXECUTION SUCCESSFUL 197