1 //===-- sanitizer_termination.cpp -------------------------------*- C++ -*-===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 /// This file contains the Sanitizer termination functions CheckFailed and Die,
10 /// and the callback functionalities associated with them.
12 //===----------------------------------------------------------------------===//
14 #include "sanitizer_common.h"
15 #include "sanitizer_libc.h"
17 namespace __sanitizer
{
19 static const int kMaxNumOfInternalDieCallbacks
= 5;
20 static DieCallbackType InternalDieCallbacks
[kMaxNumOfInternalDieCallbacks
];
22 bool AddDieCallback(DieCallbackType callback
) {
23 for (int i
= 0; i
< kMaxNumOfInternalDieCallbacks
; i
++) {
24 if (InternalDieCallbacks
[i
] == nullptr) {
25 InternalDieCallbacks
[i
] = callback
;
32 bool RemoveDieCallback(DieCallbackType callback
) {
33 for (int i
= 0; i
< kMaxNumOfInternalDieCallbacks
; i
++) {
34 if (InternalDieCallbacks
[i
] == callback
) {
35 internal_memmove(&InternalDieCallbacks
[i
], &InternalDieCallbacks
[i
+ 1],
36 sizeof(InternalDieCallbacks
[0]) *
37 (kMaxNumOfInternalDieCallbacks
- i
- 1));
38 InternalDieCallbacks
[kMaxNumOfInternalDieCallbacks
- 1] = nullptr;
45 static DieCallbackType UserDieCallback
;
46 void SetUserDieCallback(DieCallbackType callback
) {
47 UserDieCallback
= callback
;
53 for (int i
= kMaxNumOfInternalDieCallbacks
- 1; i
>= 0; i
--) {
54 if (InternalDieCallbacks
[i
])
55 InternalDieCallbacks
[i
]();
57 if (common_flags()->abort_on_error
)
59 internal__exit(common_flags()->exitcode
);
62 static CheckFailedCallbackType CheckFailedCallback
;
63 void SetCheckFailedCallback(CheckFailedCallbackType callback
) {
64 CheckFailedCallback
= callback
;
67 const int kSecondsToSleepWhenRecursiveCheckFailed
= 2;
69 void NORETURN
CheckFailed(const char *file
, int line
, const char *cond
,
71 static atomic_uint32_t num_calls
;
72 if (atomic_fetch_add(&num_calls
, 1, memory_order_relaxed
) > 10) {
73 SleepForSeconds(kSecondsToSleepWhenRecursiveCheckFailed
);
77 if (CheckFailedCallback
) {
78 CheckFailedCallback(file
, line
, cond
, v1
, v2
);
80 Report("Sanitizer CHECK failed: %s:%d %s (%lld, %lld)\n", file
, line
, cond
,
85 } // namespace __sanitizer
87 using namespace __sanitizer
;
90 SANITIZER_INTERFACE_ATTRIBUTE
91 void __sanitizer_set_death_callback(void (*callback
)(void)) {
92 SetUserDieCallback(callback
);