Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

crash can not be captured on windows #818

Closed
chenxinhua2021 opened this issue Mar 14, 2023 · 22 comments
Closed

crash can not be captured on windows #818

chenxinhua2021 opened this issue Mar 14, 2023 · 22 comments
Labels
area: integration Platform: Native Platform: Windows upstream The issue is related to an upstream dependency

Comments

@chenxinhua2021
Copy link

I am using flutter to develop app. and use sentry to capture crash. C PlusPlus code is called by ffi which is manged by dart in flutter. Now, The crash is not captured in c plusplus code, try to use crashpad/breakpad/inproc backend, fail to capture the crash.
Found The issue which is in the dart website. dart-lang/sdk#39140
FFI is only a C-based. Maybe c plus plus exceptions can not be captured. Is that why Crash can not be captured by sentry ?
If i want to capture the crash, which methods can be used ?

  • OS: [e.g. Windows 10, 64-bit]
  • Compiler: [e.g. MSVC 22]
  • CMake version and config: [e.g. 3.17.2, SENTRY_BACKEND=inproc]
@supervacuus
Copy link
Collaborator

Hi @chenxinhua2021! I need more context because I am not well-versed in Flutter. Especially the following questions immediately pop up in my head:

  • do you only initialize the Native SDK in a C++ FFI module?
  • (or) are you using the Dart SDK for your flutter application too?
  • how do you initialize the Native SDK? does the FFI library keep a global sentry context?
  • does the initialization work for you (would you see any error when you enable the debug output)?
  • can you send normal events successfully?

What I can tell you:

  • There is an open ticket to integrate the Native SDK into the Dart SDK to support Flutter Desktop applications on Windows: Support native crash reporting for Windows sentry-dart#896. This means there is currently no support for native crashes on Windows in the Dart SDK.
  • The Native SDK doesn't handle C++ exceptions on a language level (i.e., we do not hook into std::terminate), but every uncaught C++ exception will lead to a low-level exception which we will capture.
  • The issue you linked to talks about safely handling exceptions through the FFI boundary. This is only partially related: you must provide a C wrapper to your C++ code when using the Dart FFI to guarantee defined behavior in an error case. If the VM crashes due to letting a C++ exception escape through the FFI boundary, then our crash handler should be able to capture this too. But:
  • It is entirely unclear to me how Dart handles (SEH) exceptions on Windows and how FFI modules might be sandboxed in a way that will prevent the useful operation of unhandled exception filters (which our backends would need to function correctly). A core task of Support native crash reporting for Windows sentry-dart#896 is figuring out how (and if) Dart allows FFI code to set this up correctly.

@chenxinhua2021
Copy link
Author

Thank you very much for your fast reply @supervacuus . I use dart sdk and native sdk in my flutter application.
Native sdk Initialize:
sentry_options_t* options = sentry_options_new();
sentry_options_set_dsn(options, "https://@sentry.io/");
sentry_init(options);
I can get dump file in the path of my project by making some crashes which is not in ffi module.
In addition, normal events can be successfully sent. and other crashes can be captured, only the crash that c++ is called by ffi module can not be captured.

@supervacuus
Copy link
Collaborator

When you say "other crashes can be captured", do you mean dart crashes or other native crashes (like an access violation) from an FFI module? I guess any other SEH exception from an FFI module would also not be reported. I cannot tell you when I will have time to investigate this further, but it is on our agenda.

@chenxinhua2021
Copy link
Author

Yes, any other SEH exception from an FFI module is not reported. Other crashes Which is maked by c++ plugin to be called by flutter can be captured. I will try to do a simple demo to present the problem.

@supervacuus
Copy link
Collaborator

Ok, thanks for verifying. So the C++ FFI aspect seems to be a red herring in this issue since C++ exceptions on Windows are just SEH exceptions.

If SEH exceptions fail to report, the problem lies with the registration or the execution environment of the unhandled exception filter in our backend because Dart installs one itself during the startup of the runtime.

This filter would normally print a stack trace if there was a native crash. The Native SDK in turn would overwrite that filter with its backend-specific implementation. Can you compare whether crashing from the FFI module prints a stack trace without initializing the Native SDK?

@chenxinhua2021
Copy link
Author

I try to use windows system api (SetUnhandledExceptionFilter), crash can not be captured which is maked c++ code which is called FFI module.

Stack information can be printed in visual studio tool when crash from ffi module.

@chenxinhua2021
Copy link
Author

Hi @supervacuus we make a simple demo to present the problem. this is url. https://github.com/Arctuition/dart-ffi-crash
There are two ways to verify crash. Same program call ffi interface and c++ plugin. Crash in Ffi module( c++ code be called) can not be captured. Crash in c++ plugins can be captured.

@supervacuus
Copy link
Collaborator

Thank you for preparing a repro that covers the FFI and plugin case, @chenxinhua2021. As I said before, I cannot say when I will have the time to dive into this.

@marandaneto, I think you will be involved in the dart/native evaluation, right? @chenxinhua2021 prepared a repro-repo, that fails at capturing SEH from FFI modules but is successful when crashing in Flutter plugins. Even if this is not actionable for you rn, I think the Dart-SDK team should be aware of this issue. I will try to figure out where in the FFI boundary the exception propagation fails and if we can even do something about it from the Native SDK.

@chenxinhua2021
Copy link
Author

Thank you very much for your reply @supervacuus . I have consulted on drak sdk, some reply may be is worthy for you.

@marandaneto
Copy link
Contributor

Thank you for preparing a repro that covers the FFI and plugin case, @chenxinhua2021. As I said before, I cannot say when I will have the time to dive into this.

@marandaneto, I think you will be involved in the dart/native evaluation, right? @chenxinhua2021 prepared a repro-repo, that fails at capturing SEH from FFI modules but is successful when crashing in Flutter plugins. Even if this is not actionable for you rn, I think the Dart-SDK team should be aware of this issue. I will try to figure out where in the FFI boundary the exception propagation fails and if we can even do something about it from the Native SDK.

That's correct, it's not a supported use case yet, and apparently, there's a dependency with dart-lang/sdk#51726 (comment) and its exception filters.
If @chenxinhua2021 is setting up sentry-native directly in the Flutter app, that should work, that's exactly what we'd do when tackling getsentry/sentry-dart#896 (but automatically) so if there's a problem, we'd need to consider that as well.

@supervacuus
Copy link
Collaborator

Hi @marandaneto, yes, that is why I hooked you in. You will experience the same issue with any native code called from Dart-generated code (it happens with JIT and AOT). As mentioned here, it is not specific to FFI modules (though it will mostly be an issue there) but related to unwinding the Dart code regions in case of a crash on Windows.

@ashwoods ashwoods added the upstream The issue is related to an upstream dependency label Oct 13, 2023
@alexvoina
Copy link

@chenxinhua2021 did you manage to make this work in the end? I see that dart team fixed the underlying issue.

@getsantry getsantry bot moved this to Waiting for: Product Owner in GitHub Issues with 👀 2 Mar 27, 2024
@isaacy13
Copy link

+1 this would be great

ty to Sentry team

@supervacuus
Copy link
Collaborator

To be clear, @isaacy13: the issue had to be fixed in Dart itself and not in Sentry's SDKs. The fix was released with Dart 3.0.0-422.0.dev. The implementation for Windows ARM64 still needs to be completed.

We only keep this issue open as a test target to consider for Windows Desktop support in the Dart SDK. As far as we know, there is nothing to do on the side of the Native SDK to allow crash reporting for Windows native code as long as you deploy to a Dart environment with the above fix.

cc @kahest

@isaacy13
Copy link

Ah perfect, thank you @supervacuus for the clarification

Perhaps this belongs in another ticket (not sure if Dart or Sentry), but whenever FFI C++ code is calling abort(), I'm not seeing logs in Sentry

Sometimes I don't even get the abort() message -- it just crashes, but a little debugging shows the various exceptions that are thrown to crash the program (null access, division by 0, etc.)

For context: media-kit/media-kit#743

  • Flutter 3.19.3
  • Dart 3.3.1
  • Windows 11 x64

I've previously done Sentry quick setup & verified logs do show up when following these steps
https://docs.sentry.io/platforms/flutter/#verify

Also, Sentry is initialized before the exceptions are thrown

@getsantry getsantry bot moved this to Waiting for: Product Owner in GitHub Issues with 👀 2 Mar 31, 2024
@alexvoina
Copy link

@isaacy13 I'm seeing the same behavior (i.e. no information in sentry dashboard on C++ crashes), but from what I understand this is expected behavior.

You would need to integrate the Sentry Native like @chenxinhua2021 in this example if you want to have that work.

I wanted to try this myself but I'm afraid I don't have the time right now, even if it looks like most of the work has been done in that example. Let me know if you try it.

p.s. don't expect native crashes to be reported instantaneously like other flutter exceptions, they only show up after you reopen the app after the crash

@isaacy13
Copy link

isaacy13 commented Apr 2, 2024

@alexvoina Thanks for the info

After re-reading with a fresher pair of eyes, my understanding has changed

As @supervacuus said previously, the Dart team fixed the issue from @chenxinhua2021's post (dart-lang/sdk#51726)

  • so the FFI vs. plugin difference referenced in here turned out to be a symptom of another issue related to stack unwinding

I poked around a bit and the problem is indeed not related to FFI, but rather to the failure to unwind the stack.
dart-lang/sdk#51726 (comment)


Ok, thanks for verifying. So the C++ FFI aspect seems to be a red herring in this issue since C++ exceptions on Windows are just SEH exceptions.
#818 (comment)

I suspect the thing I'm missing is initializing Sentry in C++ -- I am currently only initializing Sentry in Flutter

Thank you very much for your fast reply @supervacuus . I use dart sdk and native sdk in my flutter application. Native sdk Initialize: sentry_options_t* options = sentry_options_new(); sentry_options_set_dsn(options, "https://@sentry.io/"); sentry_init(options);
#818 (comment)

But with my current understanding of the various threads, it sounds like things should be working, just need to give it another shot -- I expect to report back to this thread this weekend or the next with results

@supervacuus
Copy link
Collaborator

I suspect the thing I'm missing is initializing Sentry in C++ -- I am currently only initializing Sentry in Flutter

Yes, that's right. The Native SDK and the Dart SDK are not yet integrated for Flutter on Windows (getsentry/sentry-dart#896).

The Native SDK can detect any unhandled crash outside the managed environment, while the Dart SDK will report errors from within Dart/Flutter, such as exceptions or failed assertions.

The latter will be enough for most Flutter Applications, but when using native libraries via Dart's FFI or as Flutter plugins, you might need a native crash handler. For most supported platforms of the Dart SDK, these native crash handlers are already integrated (for instance, on Android, you will get NDK crashes reported via sentry-android, which uses the Native SDK under the hood).

But with my current understanding of the various threads, it sounds like things should be working, just need to give it another shot

There is currently no indication that the Native SDK and the Dart SDK can't operate next to each other (they won't cooperate, you will have to initialize them separately, and scope changes will not be synced).

@alexvoina
Copy link

@isaacy13 really looking forward to hearing your report

@isaacy13
Copy link

isaacy13 commented May 15, 2024

@alexvoina

A lot later than I expected to be replying -- but everything is working as expected

Steps taken on Windows:

  • follow setup steps for Sentry Native (download and build with crashpad_handler)
  • add includes/libs/dlls in windows/runner/CMakeLists.txt
  • make sure crashpad_handler.exe is in windows/runner folder
  • #include "sentry_init.h" in windows/runner/main.cpp

Now, whenever I throw an exception in plugin libraries' C++ code, I get the alert in Sentry!

notes:

  • separate Sentry-native project must be created (cannot use DSN from Sentry-flutter)
  • can use sentry-cli to upload debug symbol files (e.g.: upload files each time running project or running project thru pipeline)
  • TODO: need to test multiple threads in C++

windows/runner/CMakeLists.txt

...
target_include_directories(${BINARY_NAME} PRIVATE "${CMAKE_SOURCE_DIR}" path_to_sentry_include_folder)
target_link_libraries(${BINARY_NAME} PRIVATE path_to_sentry_lib_file)
add_custom_command(TARGET ${BINARY_NAME} POST_BUILD
                   COMMAND ${CMAKE_COMMAND} -E copy_if_different
                   path_to_sentry_dll_file
                   $<TARGET_FILE_DIR:${BINARY_NAME}>)
...

sentry_init.h

#ifndef SENTRY_INIT_H
#define SENTRY_INIT_H

#include "sentry.h"

class SentryInit {
public:
    SentryInit() {
        sentry_options_t *options = sentry_options_new();
        sentry_options_set_dsn(options, your_dsn_here);
        sentry_options_set_handler_path(options, path_to_crashpad);
        sentry_options_set_database_path(options, path_to_db_path);
        sentry_options_set_release(options, "myapp@1.0.0");
        sentry_options_set_debug(options, 1);
        sentry_init(options);
    }

    ~SentryInit() {
        sentry_close();
    }
};

static SentryInit sentryInit;

#endif // SENTRY_INIT_H

@alexvoina
Copy link

@isaacy13 it is never too late! Can't wait to try this myself too <3 Big thanks for all the explanations & code

@kahest
Copy link
Member

kahest commented Dec 12, 2024

closing this now as resolved. related PR for sentry-native integration: getsentry/sentry-dart#2286

@kahest kahest closed this as completed Dec 12, 2024
@github-project-automation github-project-automation bot moved this from Needs Discussion to Done in Mobile & Cross Platform SDK Dec 12, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area: integration Platform: Native Platform: Windows upstream The issue is related to an upstream dependency
Projects
Archived in project
Archived in project
Status: Done
Development

No branches or pull requests

7 participants