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 #51726

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

crash can not be captured on windows #51726

chenxinhua2021 opened this issue Mar 14, 2023 · 16 comments
Assignees
Labels
area-vm Use area-vm for VM related issues, including code coverage, and the AOT and JIT backends. library-ffi

Comments

@chenxinhua2021
Copy link

chenxinhua2021 commented Mar 14, 2023

I am using flutter to develop app. and use sentry to capture crash. C PlusPlus code is called by ffi . Now, The crash is not captured in c plusplus code, try to use crashpad/breakpad, fail to capture the crash. They use the api of windows system SetUnhandledExceptionFilter to capture the crash. Other crashes which are not called by ffi can be captured. Found The issue
#39140 FFI is only a C-based. Maybe c plus plus exceptions can not be captured. Is that why Crash can not be captured?
If i want to capture the crash, which methods can be used ?

@lrhn lrhn added area-vm Use area-vm for VM related issues, including code coverage, and the AOT and JIT backends. library-ffi labels Mar 16, 2023
@a-siva
Copy link
Contributor

a-siva commented Mar 16, 2023

//cc @dcharkes

@dcharkes
Copy link
Contributor

Hi @chenxinhua2021,

Nice to meet you!

To capture C++ exceptions you will have to write C++ wrapper code that catches the exception and does a normal return from C to Dart. You can create a struct that contains two fields, one with your normal return value, and the other for the exceptional return value. Then you can check that struct in Dart to see if you got an exception, and you can then throw a Dart exception.

You can use flutter create --template=plugin_ffi --target=windows to create the bundling/build-files to place your C++ code that catches the exception and converts it to a normal return.

@chenxinhua2021
Copy link
Author

Thank you very much for your reply. Crashes can be captured by plugins indeed. Unfortunately we use a lot of ffi to call c++, crashes which is made can not be captured. It is a pretty terrible thing to modify from ffi to plugins. Is there any way to capture crashes via ffi?

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. We use sentry to captured in the demo. The result is the same to use carshpad/breakpad/windows system api(SetUnhandledExceptionFilter).

We hope that the crashes can be captured which is made that ffi call c++. Maybe it is impossible to modify from ffi to plugins.
hoping for your further guidance. Thanks.

@dcharkes
Copy link
Contributor

I'm not fully able to understand your English, could you clarify what you mean?

It is a pretty terrible thing to modify from ffi to plugins.

You should not switch FFI to method channels.

Using an FFI plugin (not normal plugin) helps you with bundling and building the native code.
It is possible to use it without the FFI plugin, but you'll have to modify the CMakeBuild files manually to build/bundle your native code.

The glue code to catch exception should look something like

int makeException(int);

struct IntOrException {
    int value;
    int exception;
};

extern "C" IntOrException noException(int arg) {
  IntOrException result;
  result.value = -1;
  result.exception = -1;
  try
  {
     result.value = makeException(arg);
  }
  catch (int e)
  {
     result.exception = e;
  }
  return result;
}

Then use package:ffigen on noException instead of makeException.

@chenxinhua2021
Copy link
Author

I am sorry that I don't make myself clear. I am worried about that a lot of work need to be done. Because a lot of ffi is used in our project. we do not use ffi plugin, then we will try to use ffi plugin , thank you very much.

@dcharkes
Copy link
Contributor

I am sorry that I don't make myself clear. I am worried about that a lot of work need to be done. Because a lot of ffi is used in our project.

I understand. If many of your calls can throw exceptions, and you have to wrap all of them, that is a lot of work. Maybe you can write a code-generator that creates the glue-code for you instead of doing it manually.

@andyzhuang2015
Copy link

andyzhuang2015 commented Mar 17, 2023

@dcharkes I am working on this issue together with @chenxinhua2021 . Thanks for you reply.

Actually we want to integrate Crashpad for our APP in Windows. When our APP crashed, Crashpad will generate the dump file, and upload the file to server, so that we can recover the calling stack and identify the issue.

When the C++ code crashed in flutter-plugin or in the C++ threads created by ourself, the dump file can be generated. However, when it crashed in the code called by FFI (in "io.flutter.ui" thread) , the dump file isn't generated. We suppose that the crash can't be catched by Crashpad for some reason, and it may be caused by some special mechnism of FFI (we don't know of the implementation). We are hoping your help for this.

You suggested the glue-code for this, so the C++ exception can be transferred to Dart. It can work for the C++ standard Exceptions. However some crashed caused by memory bad access still unable to be catched (by C++ try...catch... ). For example, int* a = NULL; *a = 3;. With Crashpad the memory issue can be catched to dump file if it happened in Plugin code or a thread created by ourself. However it can't be catched if it happend in the code called by FFI.

@andyzhuang2015
Copy link

@dcharkes We use Sentry to integrate Crashpad in Windows. And we write a test demo to reproduce the issue base on Flutter and Sentry SDK. There are reproduce steps in the readme.

@dcharkes
Copy link
Contributor

Thanks for the clarification @andyzhuang2015. We're talking about actual crashes, not C++ exceptions.

I haven't used Crashpad or Sentry before, I can read up and play around with it. Maybe @mraleph or @mkustermann might know the answer to how Crashpad works and why it doesn't with FFI.

@andyzhuang2015
Copy link

Very appreciate for your help. @dcharkes @mraleph @mkustermann

@mraleph
Copy link
Member

mraleph commented Mar 20, 2023

To be honest, I would not expect any difference between FFI and non-FFI use case. That being said - maybe something goes wrong when unwinding the stack, which causes exception to not reach SetUnhandledExceptionFilter. e.g. when invoking code through FFI we will have a C code on the same stack as Dart AOT compiled code - and Dart AOT compiled code does not have unwinding information associated with it (and does not follow Win X64 ABI). I can't find an explanation for this behaviour in MSDN documentation though - I would expect unwinding to fail, but unhandled exception filter to still be invoked.

@mraleph
Copy link
Member

mraleph commented Mar 20, 2023

I poked around a bit and the problem is indeed not related to FFI, but rather to the failure to unwind the stack. Apparently (though it is not evident from the documentation) SEH does not call SetUnhandledExceptionFilter if something goes awry in the unwinding.

To make things work we need to use RtlAddFunctionTable to register proper unwinding function for our code regions.

PS. Both V8 and SpiderMonkey hit the same problem with their JITs, we can peak at their work-arounds as an inspiration: https://github.com/v8/v8/blob/cef0c00ca670d4471f8c96dbd63b103c13efc3fc/src/diagnostics/unwinding-info-win64.cc#L523

@andyzhuang2015
Copy link

@mraleph Thanks for you detailed explanations. Is there plan for fixing this and release version?

@mraleph
Copy link
Member

mraleph commented Mar 21, 2023

@aam Alex, I think you might have a Windows machine setup for development. Would you have some time to look at this?

@aam
Copy link
Contributor

aam commented Mar 21, 2023

Sure thing

@aam aam self-assigned this Mar 22, 2023
copybara-service bot pushed a commit that referenced this issue Apr 7, 2023
This change adds x64 unwinding information for generated code allowing Windows to actually call registered unhandled exception filters(Crashpad or dart-builtin crash handler).

BUG=#51726
TEST=ffi\ffi_induce_a_crash_test.dart

Change-Id: I1d9dd208f2c030b51a1146afa1048d419847fef7
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/294129
Reviewed-by: Ryan Macnak <rmacnak@google.com>
Commit-Queue: Alexander Aprelev <aam@google.com>
@aam aam closed this as completed Apr 10, 2023
@mraleph
Copy link
Member

mraleph commented Apr 11, 2023

Thanks, @aam!

copybara-service bot pushed a commit that referenced this issue Nov 21, 2023
TEST=ffi_induce_a_crash_test
Bug: #51726
Change-Id: I7df3b56a150434d4c7b0cfbadda4fd9d57606eef
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/336203
Reviewed-by: Alexander Aprelev <aam@google.com>
Commit-Queue: Ryan Macnak <rmacnak@google.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-vm Use area-vm for VM related issues, including code coverage, and the AOT and JIT backends. library-ffi
Projects
None yet
Development

No branches or pull requests

7 participants