Bug 1709352 - Support error stacks only in EARLY_BETA_OR_EARLIER) || DEBUG builds; r=dom-storage-reviewers,jstutte

Differential Revision: https://phabricator.services.mozilla.com/D114736
This commit is contained in:
Jan Varga 2021-05-25 09:06:11 +00:00
parent d3de310d61
commit 1afda44bfb
7 changed files with 76 additions and 3 deletions

View File

@ -6,10 +6,13 @@
#include "QMResult.h"
#include "mozilla/Atomics.h"
#ifdef QM_ERROR_STACKS_ENABLED
# include "mozilla/Atomics.h"
#endif
namespace mozilla {
#ifdef QM_ERROR_STACKS_ENABLED
namespace {
static Atomic<uint64_t> gLastStackId{0};
@ -18,5 +21,6 @@ static Atomic<uint64_t> gLastStackId{0};
QMResult::QMResult(nsresult aNSResult)
: mStackId(++gLastStackId), mFrameId(1), mNSResult(aNSResult) {}
#endif
} // namespace mozilla

View File

@ -9,8 +9,13 @@
#include "ErrorList.h"
#if defined(EARLY_BETA_OR_EARLIER) || defined(DEBUG)
# define QM_ERROR_STACKS_ENABLED
#endif
namespace mozilla {
#ifdef QM_ERROR_STACKS_ENABLED
struct Ok;
template <typename V, typename E>
class Result;
@ -52,12 +57,17 @@ class QMResult {
QMResult(uint64_t aStackId, uint32_t aFrameId, nsresult aNSResult)
: mStackId(aStackId), mFrameId(aFrameId), mNSResult(aNSResult) {}
};
#else
using QMResult = nsresult;
#endif
inline QMResult ToQMResult(nsresult aValue) { return QMResult(aValue); }
#ifdef QM_ERROR_STACKS_ENABLED
inline Result<Ok, QMResult> ToResult(const QMResult& aValue);
inline Result<Ok, QMResult> ToResult(QMResult&& aValue);
#endif
} // namespace mozilla

View File

@ -11,12 +11,15 @@
# error Must include QMResult.h first
#endif
#ifdef QM_ERROR_STACKS_ENABLED
#include "mozilla/Result.h"
#include "mozilla/ResultVariant.h"
#include "nsError.h"
#endif
namespace mozilla {
#ifdef QM_ERROR_STACKS_ENABLED
// Allow QMResult errors to use existing stack id and to increase the frame id
// during error propagation.
template <>
@ -63,6 +66,7 @@ inline Result<Ok, QMResult> ToResult(QMResult&& aValue) {
}
return Ok();
}
#endif
} // namespace mozilla

View File

@ -6,7 +6,9 @@
#include "QuotaCommon.h"
#include "base/process_util.h"
#ifdef QM_ERROR_STACKS_ENABLED
# include "base/process_util.h"
#endif
#include "mozIStorageConnection.h"
#include "mozIStorageStatement.h"
#include "mozilla/ErrorNames.h"
@ -418,6 +420,7 @@ void LogError(const nsACString& aExpr, const ResultType& aResult,
nsAutoCString extraInfosString;
nsAutoCString rvName;
# ifdef QM_ERROR_STACKS_ENABLED
nsAutoCString frameIdStr;
nsAutoCString stackIdStr;
nsAutoCString processIdStr;
@ -434,6 +437,10 @@ void LogError(const nsACString& aExpr, const ResultType& aResult,
} else {
rv = aResult.as<nsresult>();
}
# else
if (aResult) {
nsresult rv = *aResult;
# endif
if (NS_ERROR_GET_MODULE(rv) == NS_ERROR_MODULE_WIN32) {
// XXX We could also try to get the Win32 error name here.
@ -448,10 +455,12 @@ void LogError(const nsACString& aExpr, const ResultType& aResult,
static_cast<uint32_t>(rv), !rvName.IsEmpty() ? " (" : "",
!rvName.IsEmpty() ? rvName.get() : "", !rvName.IsEmpty() ? ")" : "");
# ifdef QM_ERROR_STACKS_ENABLED
if (aResult.is<QMResult>()) {
extraInfosString.Append(", frameId="_ns + frameIdStr + ", stackId="_ns +
stackIdStr + ", processId="_ns + processIdStr);
}
# endif
}
const auto sourceFileRelativePath =
@ -517,19 +526,23 @@ void LogError(const nsACString& aExpr, const ResultType& aResult,
res.AppendElement(EventExtraEntry{
"context"_ns, nsPromiseFlatCString{*contextIt->second}});
# ifdef QM_ERROR_STACKS_ENABLED
if (!frameIdStr.IsEmpty()) {
res.AppendElement(
EventExtraEntry{"frame_id"_ns, nsCString{frameIdStr}});
}
# endif
// TODO We could still fill the module field, based on the source
// directory, but we probably don't need to.
// res.AppendElement(EventExtraEntry{"module"_ns, aModule});
# ifdef QM_ERROR_STACKS_ENABLED
if (!processIdStr.IsEmpty()) {
res.AppendElement(
EventExtraEntry{"process_id"_ns, nsCString{processIdStr}});
}
# endif
if (!rvName.IsEmpty()) {
res.AppendElement(EventExtraEntry{"result"_ns, nsCString{rvName}});
@ -554,10 +567,12 @@ void LogError(const nsACString& aExpr, const ResultType& aResult,
res.AppendElement(
EventExtraEntry{"source_line"_ns, IntToCString(aSourceFileLine)});
# ifdef QM_ERROR_STACKS_ENABLED
if (!stackIdStr.IsEmpty()) {
res.AppendElement(
EventExtraEntry{"stack_id"_ns, nsCString{stackIdStr}});
}
# endif
return res;
}());

View File

@ -1227,7 +1227,11 @@ enum class Severity {
};
#if defined(EARLY_BETA_OR_EARLIER) || defined(DEBUG)
# ifdef QM_ERROR_STACKS_ENABLED
using ResultType = Variant<QMResult, nsresult, Nothing>;
# else
using ResultType = Maybe<nsresult>;
# endif
void LogError(const nsACString& aExpr, const ResultType& aResult,
const nsACString& aSourceFilePath, int32_t aSourceFileLine,
@ -1312,7 +1316,11 @@ template <typename T>
MOZ_COLD void HandleError(const char* aExpr, const T& aRv,
const char* aSourceFilePath, int32_t aSourceFileLine,
const Severity aSeverity) {
# ifdef QM_ERROR_STACKS_ENABLED
if constexpr (std::is_same_v<T, QMResult> || std::is_same_v<T, nsresult>) {
# else
if constexpr (std::is_same_v<T, nsresult>) {
# endif
mozilla::dom::quota::LogError(nsDependentCString(aExpr), ResultType(aRv),
nsDependentCString(aSourceFilePath),
aSourceFileLine, aSeverity);

View File

@ -18,6 +18,7 @@
#include "mozilla/RefPtr.h"
#include "mozilla/Result.h"
#include "mozilla/dom/Nullable.h"
#include "mozilla/dom/QMResult.h"
#include "mozilla/dom/ipc/IdType.h"
#include "mozilla/dom/quota/CommonMetadata.h"
#include "mozilla/dom/quota/InitializationTypes.h"
@ -49,7 +50,6 @@ class nsPIDOMWindowOuter;
namespace mozilla {
class OriginAttributes;
class QMResult;
namespace ipc {

View File

@ -11,6 +11,7 @@
using namespace mozilla;
#ifdef QM_ERROR_STACKS_ENABLED
TEST(DOM_Quota_QMResult, Construct_Default)
{
QMResult res;
@ -19,16 +20,22 @@ TEST(DOM_Quota_QMResult, Construct_Default)
ASSERT_EQ(res.FrameId(), 1u);
ASSERT_EQ(res.NSResult(), NS_OK);
}
#endif
TEST(DOM_Quota_QMResult, Construct_FromNSResult)
{
QMResult res(NS_ERROR_FAILURE);
#ifdef QM_ERROR_STACKS_ENABLED
ASSERT_EQ(res.StackId(), 2u);
ASSERT_EQ(res.FrameId(), 1u);
ASSERT_EQ(res.NSResult(), NS_ERROR_FAILURE);
#else
ASSERT_EQ(res, NS_ERROR_FAILURE);
#endif
}
#ifdef QM_ERROR_STACKS_ENABLED
TEST(DOM_Quota_QMResult, Propagate)
{
QMResult res1(NS_ERROR_FAILURE);
@ -43,14 +50,19 @@ TEST(DOM_Quota_QMResult, Propagate)
ASSERT_EQ(res2.FrameId(), 2u);
ASSERT_EQ(res2.NSResult(), NS_ERROR_FAILURE);
}
#endif
TEST(DOM_Quota_QMResult, ToQMResult)
{
auto res = ToQMResult(NS_ERROR_FAILURE);
#ifdef QM_ERROR_STACKS_ENABLED
ASSERT_EQ(res.StackId(), 4u);
ASSERT_EQ(res.FrameId(), 1u);
ASSERT_EQ(res.NSResult(), NS_ERROR_FAILURE);
#else
ASSERT_EQ(res, NS_ERROR_FAILURE);
#endif
}
TEST(DOM_Quota_QMResult, ToResult)
@ -62,9 +74,13 @@ TEST(DOM_Quota_QMResult, ToResult)
static_assert(std::is_same_v<decltype(valOrErr), Result<Ok, QMResult>>);
ASSERT_TRUE(valOrErr.isErr());
auto err = valOrErr.unwrapErr();
#ifdef QM_ERROR_STACKS_ENABLED
ASSERT_EQ(err.StackId(), 5u);
ASSERT_EQ(err.FrameId(), 1u);
ASSERT_EQ(err.NSResult(), NS_ERROR_FAILURE);
#else
ASSERT_EQ(err, NS_ERROR_FAILURE);
#endif
}
// move
@ -74,9 +90,13 @@ TEST(DOM_Quota_QMResult, ToResult)
static_assert(std::is_same_v<decltype(valOrErr), Result<Ok, QMResult>>);
ASSERT_TRUE(valOrErr.isErr());
auto err = valOrErr.unwrapErr();
#ifdef QM_ERROR_STACKS_ENABLED
ASSERT_EQ(err.StackId(), 6u);
ASSERT_EQ(err.FrameId(), 1u);
ASSERT_EQ(err.NSResult(), NS_ERROR_FAILURE);
#else
ASSERT_EQ(err, NS_ERROR_FAILURE);
#endif
}
}
@ -84,19 +104,31 @@ TEST(DOM_Quota_QMResult, ErrorPropagation)
{
Result<Ok, QMResult> valOrErr1 = ToResult(ToQMResult(NS_ERROR_FAILURE));
const auto& err1 = valOrErr1.inspectErr();
#ifdef QM_ERROR_STACKS_ENABLED
ASSERT_EQ(err1.StackId(), 7u);
ASSERT_EQ(err1.FrameId(), 1u);
ASSERT_EQ(err1.NSResult(), NS_ERROR_FAILURE);
#else
ASSERT_EQ(err1, NS_ERROR_FAILURE);
#endif
Result<Ok, QMResult> valOrErr2 = valOrErr1.propagateErr();
const auto& err2 = valOrErr2.inspectErr();
#ifdef QM_ERROR_STACKS_ENABLED
ASSERT_EQ(err2.StackId(), 7u);
ASSERT_EQ(err2.FrameId(), 2u);
ASSERT_EQ(err2.NSResult(), NS_ERROR_FAILURE);
#else
ASSERT_EQ(err2, NS_ERROR_FAILURE);
#endif
Result<Ok, QMResult> valOrErr3 = valOrErr2.propagateErr();
const auto& err3 = valOrErr3.inspectErr();
#ifdef QM_ERROR_STACKS_ENABLED
ASSERT_EQ(err3.StackId(), 7u);
ASSERT_EQ(err3.FrameId(), 3u);
ASSERT_EQ(err3.NSResult(), NS_ERROR_FAILURE);
#else
ASSERT_EQ(err3, NS_ERROR_FAILURE);
#endif
}