-
-
Save lewissbaker/4784a07e916867835853ba267f8c93b1 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
ssize_t getAsyncStackTraceSafe(uintptr_t* addresses, size_t maxAddresses) { | |
size_t numFrames = 0; | |
// Start by walking the normal stack until we get to the frame right before | |
// the frame that holds the async root. | |
StackFrame* normalStackFrame = (StackFrame*)FOLLY_ASYNC_STACK_FRAME_POINTER(); | |
StackFrame* normalStackFrameStop = nullptr; | |
const auto* asyncStackRoot = tryGetCurrentAsyncStackRoot(); | |
AsyncStackFrame* asyncStackFrame = nullptr; | |
if (asyncStackRoot != nullptr) { | |
normalStackFrameStop = (StackFrame*)asyncStackRoot->getStackFramePointer(); | |
asyncStackFrame = asyncStackRoot->topFrame; | |
} | |
// Walk normal stack-frames | |
walk_normal_stack: | |
while (numFrames < maxAddresses && normalStackFrame != nullptr) { | |
auto* nextStackFrame = normalStackFrame->parentFrame; | |
if (normalStackFrameStop != nullptr && nextStackFrame == normalStackFrameStop) { | |
// Reached end of normal stack-frame. Continue walking async stack frame. | |
goto walk_async_stack; | |
} | |
addresses[numFrames++] = reinterpret_cast<std::uintptr_t>(normalStackFrame->returnAddress); | |
normalStackFrame = nextStackFrame; | |
} | |
// Reached end of normal stack without hitting the stop stack-frame, or the buffer is full. | |
// Stop walking here. | |
goto walk_done; | |
walk_async_stack: | |
while (numFrames < maxAddresses && asyncStackFrame != nullptr) { | |
addresses[numFrames++] = reinterpret_cast<std::uintptr_t>(asyncStackFrame->getReturnAddress()); | |
auto* nextAsyncFrame = asyncStackFrame->getParentFrame(); | |
if (nextAsyncFrame == nullptr) { | |
// Reached end of async stack. | |
// The last async frame may have an AsyncStackRoot that points to the StackFrame that | |
// we should continue walking on. If so then continue walking the normal stack. | |
asyncStackRoot = asyncStackFrame->getStackRoot(); | |
if (asyncStackRoot != nullptr) { | |
normalStackFrame = (StackFrame*)asyncStackRoot->getStackFramePointer(); | |
if (normalStackFrame != nullptr) { | |
// Continue walking on the normal stack-frames | |
// Check if there is another stack root that indicates where we should stop | |
// walking the normal stack and resume walking another async stack. | |
asyncStackRoot = asyncStackRoot->getNextRoot(); | |
if (asyncStackRoot != nullptr) { | |
normalStackFrameStop = (StackFrame*)asyncStackRoot->getStackFramePointer(); | |
} else { | |
normalStackFrameStop = nullptr; | |
} | |
goto walk_normal_stack; | |
} | |
} | |
} | |
asyncStackFrame = nextAsyncFrame; | |
} | |
// Reached end of async stack with no chained on normal stack, or the buffer is full. | |
// Stop walking here. | |
walk_done: | |
return numFrames; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment