Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Add macros to throw in debug builds and log in production #534

Merged
merged 2 commits into from
Apr 14, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 0 additions & 7 deletions src/workerd/jsg/jsg.c++
Original file line number Diff line number Diff line change
Expand Up @@ -77,13 +77,6 @@ void Data::destroy() {
}
}

#ifdef KJ_DEBUG
void Data::assertInvariantImpl() {
// Assert that only empty values are associated with null isolates.
KJ_DASSERT(isolate != nullptr || handle.IsEmpty());
}
#endif

Lock::Lock(v8::Isolate* v8Isolate)
: v8Isolate(v8Isolate), locker(v8Isolate), scope(v8Isolate),
previousData(v8Isolate->GetData(2)),
Expand Down
13 changes: 7 additions & 6 deletions src/workerd/jsg/jsg.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include <kj/function.h>
#include <kj/exception.h>
#include <kj/one-of.h>
#include <kj/debug.h>
#include <type_traits>
#include <v8.h>
#include "macro-meta.h"
Expand Down Expand Up @@ -784,13 +785,13 @@ class Data {

// Debugging helpers.
void assertInvariant() {
#ifdef KJ_DEBUG
assertInvariantImpl();
#endif
// Assert that only empty values are associated with null isolates.
//
// Note that we use IASSERT (which is only enabled in debug) here because this function is
// intended to be invoked from the move ctor and assignment operator. We expect them to be
// invoked a lot and want them to be as optimizable as possible.
KJ_IASSERT(isolate != nullptr || handle.IsEmpty());
}
#ifdef KJ_DEBUG
void assertInvariantImpl();
#endif
};

template <typename T>
Expand Down
10 changes: 1 addition & 9 deletions src/workerd/jsg/setup.c++
Original file line number Diff line number Diff line change
Expand Up @@ -391,14 +391,6 @@ bool IsolateBase::allowWasmCallback(
return self->evalAllowed;
}

#ifdef KJ_DEBUG
#define DEBUG_FAIL_PROD_LOG(...) \
KJ_FAIL_ASSERT(__VA_ARGS__);
#else
#define DEBUG_FAIL_PROD_LOG(...) \
KJ_LOG(ERROR, __VA_ARGS__);
#endif

void IsolateBase::jitCodeEvent(const v8::JitCodeEvent* event) noexcept {
// We register this callback with V8 in order to build a mapping of code addresses to source
// code locations, which we use when reporting stack traces during crashes.
Expand Down Expand Up @@ -462,7 +454,7 @@ void IsolateBase::jitCodeEvent(const v8::JitCodeEvent* event) noexcept {

case v8::JitCodeEvent::CODE_REMOVED:
if (!codeMap.erase(startAddr)) {
DEBUG_FAIL_PROD_LOG("CODE_REMOVED for unknown code block?");
DEBUG_FATAL_RELEASE_LOG(ERROR, "CODE_REMOVED for unknown code block?");
}
break;

Expand Down
19 changes: 19 additions & 0 deletions src/workerd/util/sentry.h
Original file line number Diff line number Diff line change
Expand Up @@ -86,4 +86,23 @@ inline kj::StringPtr maybeOmitColoFromSentry(uint32_t coloId) {
} \
} while (0)

// The DEBUG_FATAL_RELEASE_LOG macros is for assertions that should definitely break in tests but
// are not worth breaking production over. Instead, it logs the assertion message to sentry so that
// we can notice the event. If your code requires that an assertion is true for safety (e.g.
// checking if a value is not null), this is not the macro for you.
#ifdef KJ_DEBUG
#define DEBUG_FATAL_RELEASE_LOG(severity, ...) \
([&]() noexcept { \
KJ_FAIL_ASSERT(__VA_ARGS__); \
})()
#else
#define DEBUG_FATAL_RELEASE_LOG(severity, ...) \
do { \
static bool logOnce KJ_UNUSED = [&]() { \
KJ_LOG(severity, __VA_ARGS__); \
return true; \
}(); \
} while (0)
#endif

} // namespace workerd