diff options
author | Rémi Verschelde <rverschelde@gmail.com> | 2023-01-09 14:18:53 +0100 |
---|---|---|
committer | Rémi Verschelde <rverschelde@gmail.com> | 2023-01-09 14:18:53 +0100 |
commit | d46568205de9dcc5bb8367644c5b2f00986b0761 (patch) | |
tree | 2c292e22ed1679738908b98d16cd99583dc86723 /core | |
parent | 4a504e3181c0b6d8ccc19a83452d1639c305b83a (diff) | |
parent | b1c7665866717248a2d90ac8908acb9998da014a (diff) |
Merge pull request #64795 from RandomShaper/fix_saferefcount
Prevent misuse of SafeRefCount
Diffstat (limited to 'core')
-rw-r--r-- | core/error/error_macros.h | 14 | ||||
-rw-r--r-- | core/templates/safe_refcount.h | 20 |
2 files changed, 27 insertions, 7 deletions
diff --git a/core/error/error_macros.h b/core/error/error_macros.h index f651ef57a3..63a2d22416 100644 --- a/core/error/error_macros.h +++ b/core/error/error_macros.h @@ -33,7 +33,7 @@ #include "core/typedefs.h" -#include "core/templates/safe_refcount.h" +#include <atomic> // We'd normally use safe_refcount.h, but that would cause circular includes. class String; @@ -737,10 +737,10 @@ void _err_flush_stdout(); */ #define WARN_DEPRECATED \ if (true) { \ - static SafeFlag warning_shown; \ - if (!warning_shown.is_set()) { \ + static std::atomic<bool> warning_shown; \ + if (!warning_shown.load()) { \ _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "This method has been deprecated and will be removed in the future.", false, ERR_HANDLER_WARNING); \ - warning_shown.set(); \ + warning_shown.store(true); \ } \ } else \ ((void)0) @@ -750,10 +750,10 @@ void _err_flush_stdout(); */ #define WARN_DEPRECATED_MSG(m_msg) \ if (true) { \ - static SafeFlag warning_shown; \ - if (!warning_shown.is_set()) { \ + static std::atomic<bool> warning_shown; \ + if (!warning_shown.load()) { \ _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "This method has been deprecated and will be removed in the future.", m_msg, false, ERR_HANDLER_WARNING); \ - warning_shown.set(); \ + warning_shown.store(true); \ } \ } else \ ((void)0) diff --git a/core/templates/safe_refcount.h b/core/templates/safe_refcount.h index 4d32e421cd..58ed019287 100644 --- a/core/templates/safe_refcount.h +++ b/core/templates/safe_refcount.h @@ -33,6 +33,10 @@ #include "core/typedefs.h" +#ifdef DEV_ENABLED +#include "core/error/error_macros.h" +#endif + #include <atomic> #include <type_traits> @@ -163,6 +167,16 @@ public: class SafeRefCount { SafeNumeric<uint32_t> count; +#ifdef DEV_ENABLED + _ALWAYS_INLINE_ void _check_unref_sanity() { + // This won't catch every misuse, but it's better than nothing. + CRASH_COND_MSG(count.get() == 0, + "Trying to unreference a SafeRefCount which is already zero is wrong and a symptom of it being misused.\n" + "Upon a SafeRefCount reaching zero any object whose lifetime is tied to it, as well as the ref count itself, must be destroyed.\n" + "Moreover, to guarantee that, no multiple threads should be racing to do the final unreferencing to zero."); + } +#endif + public: _ALWAYS_INLINE_ bool ref() { // true on success return count.conditional_increment() != 0; @@ -173,10 +187,16 @@ public: } _ALWAYS_INLINE_ bool unref() { // true if must be disposed of +#ifdef DEV_ENABLED + _check_unref_sanity(); +#endif return count.decrement() == 0; } _ALWAYS_INLINE_ uint32_t unrefval() { // 0 if must be disposed of +#ifdef DEV_ENABLED + _check_unref_sanity(); +#endif return count.decrement(); } |