-
Notifications
You must be signed in to change notification settings - Fork 6k
Add Windows support for //flutter/fml/backtrace.h
#36202
Conversation
fml/backtrace.cc
Outdated
#include <dlfcn.h> | ||
#include <execinfo.h> | ||
#endif // FML_OS_WIN | ||
|
||
namespace fml { | ||
|
||
static std::string kKUnknownFrameName = "Unknown"; | ||
|
||
static std::string DemangleSymbolName(const std::string& mangled) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
According to docs, the absl::Symbolize
is already doing demangling, and the mangled
here would be demangled name by absl::Symbolize
.
Can we remove this function for all platforms?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It looks like this can be removed for all platforms. It looks like DemangleSymbolName
was needed by the original implementation but should've been removed when we moved to abseil's implementation. @chinmaygarde @jason-simmons Is that correct?
FWIW, absl::Symbolize
definitely demangles on Windows (referred to as undecorating by MSVC):
- In initialization it sets the
SYMOPT_UNDNAME
option Symbolize
callsSymFromAddr
, which does the demangling.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If the demangler is no longer necessary, let's remove it. It was needed when I first wired it up.
450e5f2
to
760e866
Compare
fml/backtrace.cc
Outdated
SIGSYS, // non-existent system call invoked | ||
SIGPIPE, // write on a pipe with no reader | ||
SIGALRM, // real-time timer expired | ||
SIGTERM, // software termination signal | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Without this line, the formatter makes additional whitespace to the comment below.
SIGALRM, // real-time timer expired
#endif // !FML_OS_WIN
// Here ^^^
Should we keep this line to remove these space, or remove this line?
fml/backtrace_unittests.cc
Outdated
@@ -19,18 +19,21 @@ TEST(BacktraceTest, CanGatherBacktrace) { | |||
auto trace = BacktraceHere(0); | |||
ASSERT_GT(trace.size(), 0u); | |||
ASSERT_NE(trace.find("Frame 0"), std::string::npos); | |||
std::cout << trace << std::endl; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please remove these std::cout
lines
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
fml/backtrace_unittests.cc
Outdated
@@ -19,18 +19,21 @@ TEST(BacktraceTest, CanGatherBacktrace) { | |||
auto trace = BacktraceHere(0); | |||
ASSERT_GT(trace.size(), 0u); | |||
ASSERT_NE(trace.find("Frame 0"), std::string::npos); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm curious, could these verify that BacktraceHere
is in the string for offset 0
, and CanGatherBacktrace
is in the string for offsets 0
and 1
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
On master, the frame 0 of offset 0 is actually CanGatherBacktrace
. I fixed the PR and added the test.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some CI tests seems to run without symbols. I added skipping the test BacktraceStartsWithCallerName
if the function name in the first line of stacktrace is "Unknown".
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I tried to make all CIs pass, but only on
Linux Unopt, execinfo's backtrace
returns the backtrace which contains itself, and it makes hard to write this test.
I'll remove this test from PR.
@moko256 Thanks for implementing this, it looks great! ~~Have you verified that the CI output now contains a stack traces on Window? If no, perhaps consider creating a draft PR on the engine that contains these changes but then crashes in a test.~~~ EDIT: See below: #36202 (comment) |
Here's example output from CI backtrace (see #36254):
Looks great! 🎉 |
fml/backtrace.cc
Outdated
namespace fml { | ||
|
||
static std::string kKUnknownFrameName = "Unknown"; | ||
|
||
static std::string DemangleSymbolName(const std::string& mangled) { | ||
#if FML_OS_WIN |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@chinmaygarde for thoughts on preprocessor conditionals vs making a posix subclass and a windows subclass? That's something we do with things like files, mutexes etc. typically by adding a platform specific file in fml/platform
that's conditionally compiled in via the BUILD file. e.g. For files we do:
- https://github.com/flutter/engine/blob/main/fml/file.h
- https://github.com/flutter/engine/blob/main/fml/platform/posix/file_posix.cc
We could also do that as a follow-up refactor to get support landed initially.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I haven't looked but do the existing tests cover Windows?
std::string BacktraceHere(size_t offset) { | ||
constexpr size_t kMaxFrames = 256; | ||
void* symbols[kMaxFrames]; | ||
const auto available_frames = ::backtrace(symbols, kMaxFrames); | ||
const auto available_frames = Backtrace(symbols, kMaxFrames); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should/could we use abseil's GetStackTrace
here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It looks nice! I'm replacing with this. I'll check output on linux...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I also find absl::InstallFailureSignalHandler
. The engine doesn't use BacktraceHere
except in signal handler, so we can replace backtrace.cc with absl::InstallFailureSignalHandler
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Source code (prototype): moko256@3ca3f10
Windows:
*** SIGABRT received at time=1663690051 ***
@ 000000014073933C (unknown) absl::AbslFailureSignalHandler
@ 0000000142957225 (unknown) raise
@ 00000001428D5DE9 (unknown) abort
@ 00000001400E74A9 (unknown) fml::testing::BacktracePrinter
@ 00000001400E748E (unknown) fml::testing::BacktraceTest_BacktraceHere_Test::TestBody
@ 00000001427BA210 (unknown) testing::internal::HandleSehExceptionsInMethodIfSupported<testing::Test,void>
@ 00000001427A4201 (unknown) testing::internal::HandleExceptionsInMethodIfSupported<testing::Test,void>
@ 000000014278A59F (unknown) testing::Test::Run
@ 000000014278ADA8 (unknown) testing::TestInfo::Run
@ 000000014278B41C (unknown) testing::TestSuite::Run
@ 00000001427956E5 (unknown) testing::internal::UnitTestImpl::RunAllTests
@ 00000001427BE6F0 (unknown) testing::internal::HandleSehExceptionsInMethodIfSupported<testing::internal::UnitTestImpl,bool>
@ 00000001427A6E91 (unknown) testing::internal::HandleExceptionsInMethodIfSupported<testing::internal::UnitTestImpl,bool>
@ 0000000142795274 (unknown) testing::UnitTest::Run
@ 0000000140279BC1 (unknown) RUN_ALL_TESTS
@ 0000000140279848 (unknown) main
@ 00000001428636A9 (unknown) invoke_main
@ 000000014286358E (unknown) __scrt_common_main_seh
@ 000000014286344E (unknown) __scrt_common_main
@ 000000014286373E (unknown) mainCRTStartup
@ 00007FFFC2AB7034 (unknown) BaseThreadInitThunk
@ 00007FFFC3A426A1 (unknown) RtlUserThreadStart
Linux:
*** SIGABRT received at time=1663721941 on cpu 2 ***
PC: @ 0x7fc0709537bb (unknown) raise
@ 0x55a71acd5eec 64 absl::WriteFailureInfo()
@ 0x55a71acd5c02 64 absl::AbslFailureSignalHandler()
@ 0x7fc070c71730 1470387120 (unknown)
@ 0x55a71a74e941 32 fml::testing::BacktraceTest_BacktraceHere_Test::TestBody()
@ 0x55a71c87107b 96 testing::internal::HandleSehExceptionsInMethodIfSupported<>()
@ 0x55a71c863c27 112 testing::internal::HandleExceptionsInMethodIfSupported<>()
@ 0x55a71c853073 96 testing::Test::Run()
@ 0x55a71c853734 112 testing::TestInfo::Run()
@ 0x55a71c853d3d 112 testing::TestSuite::Run()
@ 0x55a71c85d4e1 208 testing::internal::UnitTestImpl::RunAllTests()
@ 0x55a71c8741fb 96 testing::internal::HandleSehExceptionsInMethodIfSupported<>()
@ 0x55a71c865617 112 testing::internal::HandleExceptionsInMethodIfSupported<>()
@ 0x55a71c85d0df 96 testing::UnitTest::Run()
@ 0x55a71a8d5961 16 RUN_ALL_TESTS()
@ 0x55a71a8d5832 720 main
@ 0x7fc07094009b (unknown) __libc_start_main
@ 0x5541d68949564100 (unknown) (unknown)
Aborted
I am seeing the current master's behavior on host_linux_unopt, but many functions haven't symbolized. auto trace = BacktraceHere(0);
std::cout << trace << std::endl;
|
@moko256 can you try running with |
@cbracken I find it. Thanks. |
I replaced signal handling with |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
lgtm other than the removal of BacktraceHere
, though I'll admit I hadn't actually used it in my own debugging (I usually just use lldb if I want to grab a backtrace).
@chinmaygarde may have thoughts on that.
#include "flutter/fml/macros.h" | ||
|
||
namespace fml { | ||
|
||
std::string BacktraceHere(size_t offset = 0); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why remove this function? I presume the intent was for use when debugging.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since the #16450, which introduced BacktraceHere
, this is only used in signal handler (and test for BacktraceHere
). I thought it was made public to test.
The handler from absl::InstallFailureSignalHandler
also shows stacktrace when receive signal, same as from fml's InstallCrashHandler
before. The stacktrace's format is a little different from BacktraceHere, but it seems that the existing tests doesn't depend on the format.
I just intended to avoid bitrot to follow the style guide. I know this can be used to debug. If any engine's contributors use it to debug, I'll restore it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
sgtm -- I don't use it to debug, so personally I'm fine if we remove it (we can always restore it in a followup patch with appropriate tweaks if desired)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We shouldn't have code that isn't used, but I do end up using this call frequently when debugging/testing locally. Does absl have a similar function?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(This is not blocking for landing, but I'd like to know for my own edification)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If people are using it for development, and if absl doesn't have an equivalent then let's restore it (the existing test will avoid bitrot, at least to some extent).
If absl does have an equivalent call, maybe we could add a "// See: absl::SomethingOrOther" type comment to the class docs as a little breadcrumb to help developers find it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM but please also get approval from @cbracken or @chinmaygarde before merging as they're more familiar with the history here
fml/backtrace_unittests.cc
Outdated
|
||
namespace fml { | ||
namespace testing { | ||
|
||
TEST(BacktraceTest, CanGatherBacktrace) { | ||
TEST(BacktraceDeathTest, CanGatherBacktrace) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This test does nothing useful now. Let's remove this as well as IsCrashHandlingSupported
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
Acoording to CI results, somehow on macOS ,the It looks like the absil's source code contains the implementation using execinfo, and the ifdefs for macOS, but I can't investigate the actual reason right away. I'll revert the PR to the first commit, or defer to other people on investigation on macOS. |
@cbracken @loic-sharma @chinmaygarde @dnfield From PR review triage: It looks like this PR is ready for another review pass. |
This PR adds Windows support for
//flutter/fml/backtrace.h
.This PR fixes flutter/flutter#111614.
No changes in the flutter/tests repo.
Pre-launch Checklist
writing and running engine tests.
///
).If you need help, consider asking for advice on the #hackers-new channel on Discord.