Merge pull request #64795 from RandomShaper/fix_saferefcount

Prevent misuse of SafeRefCount
This commit is contained in:
Rémi Verschelde 2023-01-09 14:18:53 +01:00
commit d46568205d
No known key found for this signature in database
GPG key ID: C3336907360768E1
2 changed files with 27 additions and 7 deletions

View file

@ -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)

View file

@ -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();
}