diff --git a/common/dfxutil/stack_utils.cpp b/common/dfxutil/stack_utils.cpp index ae344333b8fcfa31c4c2a8c9a41ef9e214a75013..ccf2ff6ea26600365b4109912a70a5bdd1da1e57 100644 --- a/common/dfxutil/stack_utils.cpp +++ b/common/dfxutil/stack_utils.cpp @@ -18,25 +18,45 @@ #include #include #include +#include + #include "dfx_define.h" #include "stack_utils.h" namespace OHOS { namespace HiviewDFX { -StackUtils::StackUtils() -{ - ParseSelfMaps(); -} - StackUtils& StackUtils::Instance() { static StackUtils inst; return inst; } -bool StackUtils::GetMainStackRange(uintptr_t& stackBottom, uintptr_t& stackTop) const +bool StackUtils::InitStackRange() +{ + const pid_t selfPid = getpid(); + if (pid_.load(std::memory_order_acquire) == selfPid) { + return mainStack_.IsValid(); + } + + std::lock_guard lock(initMutex_); + + if (pid_.load(std::memory_order_relaxed) == selfPid) { + return mainStack_.IsValid(); + } + mainStack_.Clear(); + arkCode_.Clear(); + ParseSelfMaps(); + + if (mainStack_.IsValid()) { + pid_.store(selfPid, std::memory_order_release); + return true; + } + return false; +} + +bool StackUtils::GetMainStackRange(uintptr_t& stackBottom, uintptr_t& stackTop) { - if (!mainStack_.IsValid()) { + if (!InitStackRange()) { return false; } stackBottom = mainStack_.start; @@ -44,9 +64,9 @@ bool StackUtils::GetMainStackRange(uintptr_t& stackBottom, uintptr_t& stackTop) return true; } -bool StackUtils::GetArkStackRange(uintptr_t& start, uintptr_t& end) const +bool StackUtils::GetArkStackRange(uintptr_t& start, uintptr_t& end) { - if (!arkCode_.IsValid()) { + if (!InitStackRange() || !arkCode_.IsValid()) { return false; } start = arkCode_.start; diff --git a/common/dfxutil/stack_utils.h b/common/dfxutil/stack_utils.h index 2b47b4517011481697d6da56e83344df3330578d..07209f84e46b69d7bd4a3dbcf1aa5ee9a435e1cd 100644 --- a/common/dfxutil/stack_utils.h +++ b/common/dfxutil/stack_utils.h @@ -15,10 +15,12 @@ #ifndef STACK_UTILS_H #define STACK_UTILS_H +#include #include #include #include #include +#include namespace OHOS { namespace HiviewDFX { @@ -30,22 +32,30 @@ public: StackUtils(const StackUtils&) = delete; StackUtils& operator=(const StackUtils&) = delete; - bool GetMainStackRange(uintptr_t& stackBottom, uintptr_t& stackTop) const; - bool GetArkStackRange(uintptr_t& start, uintptr_t& end) const; + bool GetMainStackRange(uintptr_t& stackBottom, uintptr_t& stackTop); + bool GetArkStackRange(uintptr_t& start, uintptr_t& end); static bool GetSelfStackRange(uintptr_t& stackBottom, uintptr_t& stackTop); private: + StackUtils() = default; + void ParseSelfMaps(); + bool InitStackRange(); struct MapRange { bool IsValid() const { return start != 0 && start < end; } + void Clear() + { + start = 0; + end = 0; + } uintptr_t start{0}; uintptr_t end{0}; }; - StackUtils(); - void ParseSelfMaps(); MapRange mainStack_; MapRange arkCode_; + std::atomic pid_{0}; + std::mutex initMutex_; }; } // namespace HiviewDFX } // namespace OHOS diff --git a/test/unittest/unwind/memory_test.cpp b/test/unittest/unwind/memory_test.cpp index 2c2ba7739380c9d128168cabd160a707fa4ab81d..89d48c95e1cdcc0885679451702164c321d75397 100644 --- a/test/unittest/unwind/memory_test.cpp +++ b/test/unittest/unwind/memory_test.cpp @@ -549,7 +549,7 @@ HWTEST_F(DfxMemoryTest, DfxMemoryTest015, TestSize.Level2) /** * @tc.name: DfxMemoryTest016 - * @tc.desc: test GetArkStackRange FUNC + * @tc.desc: test GetMainStackRange FUNC * @tc.type: FUNC */ HWTEST_F(DfxMemoryTest, DfxMemoryTest016, TestSize.Level2) @@ -613,6 +613,43 @@ HWTEST_F(DfxMemoryTest, DfxMemoryTest018, TestSize.Level2) ASSERT_EQ(ret, -1); GTEST_LOG_(INFO) << "DfxMemoryTest018: end."; } + +/** + * @tc.name: DfxMemoryTest019 + * @tc.desc: test GetMainStackRange FUNC + * @tc.type: FUNC + */ +HWTEST_F(DfxMemoryTest, DfxMemoryTest019, TestSize.Level2) +{ + GTEST_LOG_(INFO) << "DfxMemoryTest019: start."; + uintptr_t stackBottom {0}; + uintptr_t stackTop {0}; + auto &stackUtils = StackUtils::Instance(); + stackUtils.GetMainStackRange(stackBottom, stackTop); + pid_t pid = fork(); + if (pid == 0) { + uintptr_t childStackBottom {0}; + uintptr_t childStackTop {0}; + stackUtils.GetMainStackRange(childStackBottom, childStackTop); + EXPECT_EQ(stackUtils.pid_, getpid()); + EXPECT_NE(childStackBottom, 0); + EXPECT_NE(childStackTop, 0); + if (stackBottom == childStackBottom && stackTop == childStackTop) { + GTEST_LOG_(INFO) << "DfxMemoryTest019: stack range is same, exit."; + exit(0); + } + exit(1); + } else { + int status; + pid_t waitPid = wait(&status); + if (waitPid == -1) { + GTEST_LOG_(ERROR) << "DfxMemoryTest019: wait failed, exit."; + } + + EXPECT_EQ(WEXITSTATUS(status), 0); + GTEST_LOG_(INFO) << "DfxMemoryTest019: end."; + } +} } } // namespace HiviewDFX } // namespace OHOS