-
Notifications
You must be signed in to change notification settings - Fork 509
[Windows Forms] Form.Close crash application #7994
Comments
Could you please share the code to reproduce this crash (e.g. a scratch github repo that one can just run |
Sample as simple as application which create new form. and I manually close that form. I have slightly more complicated example, and this is exception message which I manage to capture.
It seems to be COM related |
Can you check if there's any exceptions being thrown before going down that paths? (Here's the doc on how to set up breakpoints on exceptions just in case, but I guess you know about it). From a quick look at WinForms source, this is already related to the error window, so I wonder if this is just WinForms trying to pop a dialog because something before that went wrong. |
Before that was |
Callstack:
We are actually in luck: the COM parameter is a null reference. We can marshal a null reference. It marshals into a null pointer. Adding a COM marshaller that can only marshal a null (and throws for everything else) shouldn't be too difficult. |
I try to debug this issue, to better understand how CoreRT make it's magic and have a set of questions
Next set of questions coming from my attempt to understand magic.
|
PreserveSig is one of the things CoreRT doesn't support. This is a pretty rare flag and mostly matters in COM. I don't think it's a problem for the Forms.Close crash. I'm pretty sure that in this case, the compiler is actually throwing because we can't determine the marshaller kind to marshal an interface type (we take this return statement because none of the Yes, P/invoke is done by emitting IL - it's not a limited subset: all IL is available. The IL is then passed to the native compiler (e.g. RyuJIT) to compile into native code. It works along the lines of this: [DllImport("foo", CharSet = Unicode)]
extern static void Greet(string name); This is converted (within the compiler) into what logically looks like this: [DllImport("foo", CharSet = Unicode, EntryPoint="Greet")]
extern static void rawPinvoke_Greet(char* name);
static void Greet(string name)
{
fixed (char* pName = name)
rawPinvoke_Greet(pName);
} Basically, the marshalling IL generator goes over all parameters/return types, converts them into the representation expected by the native side, and marshals them forward (managed to native) or backward (native to managed, if it's a return value). What's missing here is the handling for interfaces. We'll only be able to handle the null value of an interface. The rest is very complex. Basically we'll want to convert this: [DllImport("foo", CharSet = Unicode)]
extern static void Greet(IFooer nameProvider); Into: [DllImport("foo", CharSet = Unicode, EntryPoint="Greet")]
extern static void rawPinvoke_Greet(IntPtr nameProvider);
static void Greet(IFooer nameProvider)
{
if (nameProvider != null)
throw new NotSupportedException();
rawPinvoke_Greet(null);
} |
If dotnet/runtime#33485 goes through, we are going to have an official API to inject prebuilt COM interop into the app. It can be then used to supply the required COM interop needed by WinForms. |
If I show Form using
Form.Show
orForm.ShowDialog
then after close form, application crashed.The text was updated successfully, but these errors were encountered: