Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

First round of converting System.Drawing.Common to COMWrappers#54636

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 ourterms of service andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Merged
eerhardt merged 13 commits intodotnet:mainfromeerhardt:DrawingCOM
Jun 28, 2021

Conversation

@eerhardt
Copy link
Member

Using COM Wrappers makes the library trim compatible.

I also added a trimming test to ensure the method in question works with trimming.

@ericstj@ViktorHofer - this is another case where we are splitting ".NET Core 3.1" build with ".NET Current" build. (I had to do that in order to use ComWrappers, because that API came in 5.0.) This means we are going to be missing test coverage for all of these COM interop scenarios for System.Drawing.Common v6.0.0 when running on .NET Core 3.1.

cc@kant2002

kant2002 reacted with thumbs up emoji
@ghost
Copy link

Tagging subscribers to this area:@safern,@tarekgh
See info inarea-owners.md if you want to be subscribed.

Issue Details

Using COM Wrappers makes the library trim compatible.

I also added a trimming test to ensure the method in question works with trimming.

@ericstj@ViktorHofer - this is another case where we are splitting ".NET Core 3.1" build with ".NET Current" build. (I had to do that in order to use ComWrappers, because that API came in 5.0.) This means we are going to be missing test coverage for all of these COM interop scenarios for System.Drawing.Common v6.0.0 when running on .NET Core 3.1.

cc@kant2002

Author:eerhardt
Assignees:-
Labels:

area-System.Drawing

Milestone:-

@ViktorHofer
Copy link
Member

@ericstj@ViktorHofer - this is another case where we are splitting ".NET Core 3.1" build with ".NET Current" build. (I had to do that in order to use ComWrappers, because that API came in 5.0.) This means we are going to be missing test coverage for all of these COM interop scenarios for System.Drawing.Common v6.0.0 when running on .NET Core 3.1.

I agree that is painful and should be fixed by adding support for testing on older .NETCoreApp versions and run them either per rolling build or nightly. We don't have capacity to run them on every PR.

@ericstj
Copy link
Member

@ViktorHofer what if this was opt-in per test? A test project could decide to add a configuration fornetcore3.1-Windows and we could have one of the build legs (either windows or all-configurations) create the helix work items. Would this require more capacity than a single test additional test assembly?

@ericstj
Copy link
Member

cc@michaelgsharp as well, who's been doing a lot of helix work lately. ML.NET has a similar requirement around wanting to run tests against multiple different framework versions.

Also, maybe we should move this discussion to an issue. Do we have a good one already?

@ViktorHofer
Copy link
Member

ViktorHofer commentedJun 23, 2021
edited
Loading

@ViktorHofer what if this was opt-in per test? A test project could decide to add a configuration for netcore3.1-Windows and we could have one of the build legs (either windows or all-configurations) create the helix work items. Would this require more capacity than a single test additional test assembly?

The overall issue isn't specific to Windows, we need coverage on as many OSs that a library supports, as possible. The cost that I'm concerned about isn't observable in the amount of build agents but in the number of Helix clients that accept work items.

I imagine support for testing on older .NETCoreApp configurations could be implemented in the following way in order:

  • Downgrade the TestUtilities.csproj to netcoreapp3.1 (use$(NetCoreAppMinimum) which will be introduced soon).
  • Add infra support for running .NETCoreApp tests without a testhost (same as for .NETFramework testing)here.
  • Add two legs (or as an optimization only one leg) for netcoreapp3.1 and net5.0 that build the respective configuration and submit jobs to helix for all OSs. Consider adding a new pipeline for that so that it can be scheduled (i.e. nightly).
  • Add netcoreapp3.1/net5.0 TFMs in the OOB test projects either everywhere or on a per project basis where it makes sense (I think the former would make more sense).
  • Make sure that the new pipeline is monitored to catch regressions in the older .NETCoreApp TFM assets.
ericstj and safern reacted with thumbs up emojiericstj reacted with heart emoji

@ViktorHofer
Copy link
Member

ViktorHofer commentedJun 23, 2021
edited
Loading

Moved test infrastructure discussion into#54639.

* Use function pointers instead of delegates* Rename Guid to IID* Better interop to closely match the native side* Release any COM pointer that was QueryInterface* Use pointers instead of Marshal.PtrToStructure/StructureToPtr
* No need for a VTable struct, just set each function pointer right into the table* Wrap all managed calls in try-catch and return HResult
* Rename methods* Use COM naming* Fix method signature to use pointer instead of out.* CheckStatus => ThrowExceptionForHR
@eerhardt
Copy link
MemberAuthor

Looks like the x86 tests are failing:

Fatal error. 0xC0000005   at System.Runtime.InteropServices.Marshal.Release(IntPtr)   at System.Drawing.Icon.Save(System.IO.Stream)   at System.Drawing.Tests.IconTests.SaveAndCompare(System.Drawing.Icon, Boolean)   at System.Drawing.Tests.IconTests.FromHandle_IconHandleMultipleTime_Success()

Trying to get a repro locally.

@safern
Copy link
Member

@ViktorHofer do we have a lot of projects that would run on previous versions of .NET Core? What if we start small and run them on Ubuntu, Windows and macOS on the build agent without using helix? If there aren't may projects that would want to do this, we could get away without using helix and running them on the build agent.

@eerhardt
Copy link
MemberAuthor

Looks like the x86 tests are failing:

This is what I see when trying to debug the .dmp file.@AaronRobinsonMSFT any thoughts?

Thread  11Current frame: coreclr!GetCLRRuntimeHost + 0x43f03ChildEBP RetAddr  Caller, Callee072AD388 72d194e2 coreclr!coreclr_shutdown_2 + 0x94a52, calling coreclr!coreclr_shutdown_2 + 0x109cc072AD470 72d194e2 coreclr!coreclr_shutdown_2 + 0x94a52, calling coreclr!coreclr_shutdown_2 + 0x109cc072AD484 72dabc83 coreclr!GetCLRRuntimeHost + 0x43f03, calling coreclr!coreclr_shutdown_2 + 0x2f670072AD698 72c3b2d4 coreclr!coreclr_initialize + 0x42f4, calling coreclr!coreclr_initialize + 0x430b072AD6A8 72d194ef coreclr!coreclr_shutdown_2 + 0x94a5f, calling coreclr!GetCLRRuntimeHost + 0x43e91072AD78C 72c8dec3 coreclr!coreclr_shutdown_2 + 0x9433, calling coreclr!coreclr_shutdown_2 + 0x945f072AD80C 72be1501 coreclr + 0x61501, calling coreclr!coreclr_shutdown_2 + 0x169a3072AD810 72be1462 coreclr + 0x61462, calling coreclr!coreclr_shutdown_2 + 0x169a3072AD828 72be04fe coreclr + 0x604fe, calling coreclr + 0x60517072AD86C 771980a9 ntdll!ExecuteHandler2 + 0x26072AD890 7719807b ntdll!ExecuteHandler + 0x24, calling ntdll!ExecuteHandler2072AD8B4 7719801d ntdll!RtlDispatchException + 0x127, calling ntdll!RtlpExecuteHandlerForException072AD940 77150133 ntdll!KiUserExceptionDispatcher + 0xf, calling ntdll!RtlDispatchException072ADE0C 90ffffd4 90ffffd4 ====> Exception cxr@072AD9A8072ADB94 77172d9a ntdll!RtlpFreeHeap + 0x1f4, calling ntdll!RtlpCoalesceFreeBlocks072ADBE4 0735c49a (MethodDesc 0038f78c + 0xa System.Buffer.Memmove[[System.Byte, System.Private.CoreLib]](Byte ByRef, Byte ByRef, UIntPtr)), calling (MethodDesc 00270f28 + 0 System.Buffer.Memmove(Byte ByRef, Byte ByRef, UIntPtr))072ADD08 72bd86bc coreclr + 0x586bc, calling coreclr!coreclr_shutdown_2 + 0x169a3072ADD0C 72bd80bd coreclr + 0x580bd, calling coreclr + 0x58149072ADD1C 72bd810d coreclr + 0x5810d, calling coreclr!coreclr_shutdown_2 + 0x169a3072ADD74 76615847 gdi32!IcmReleaseCachedColorSpace + 0x41, calling ntdll!RtlLeaveCriticalSection072ADD88 7716e143 ntdll!RtlFreeHeap + 0x105, calling ntdll!RtlpLowFragHeapFree072ADDA0 76c56eaa ole32!CRetailMalloc_Free + 0x1c [d:\w7rtm\com\ole32\com\class\memapi.cxx:687], calling ntdll!RtlFreeHeap072ADDB4 748b470c oleaut32!MemFree + 0x4e072ADDC0 748d357c oleaut32!CPicture::~CPicture + 0xd7, calling oleaut32!_EH_epilog3072ADDC8 748b4795 oleaut32!operator delete + 0xd, calling oleaut32!MemFree072ADDD4 748d34ba oleaut32!CPicture::`scalar deleting destructor' + 0x19, calling oleaut32!operator delete072ADDE4 748d349a oleaut32!CPicture::Release + 0x27, calling oleaut32!CPicture::`scalar deleting destructor'072ADE08 0881ce31 (MethodDesc 002e28f4 + 0x99 System.Runtime.InteropServices.Marshal.Release(IntPtr))072ADE24 0881ce31 (MethodDesc 002e28f4 + 0x99 System.Runtime.InteropServices.Marshal.Release(IntPtr))072ADE58 08c5b0da (MethodDesc 02388b30 + 0x2b2 System.Drawing.Icon.Save(System.IO.Stream)), calling (MethodDesc 002e28f4 + 0 System.Runtime.InteropServices.Marshal.Release(IntPtr))072ADF08 0881b5c2 (MethodDesc 0252e85c + 0x82 System.Drawing.Tests.IconTests.SaveAndCompare(System.Drawing.Icon, Boolean)), calling (MethodDesc 02388b30 + 0 System.Drawing.Icon.Save(System.IO.Stream))

@AaronRobinsonMSFT
Copy link
Member

@eerhardt How can I get a hold of that DMP file?

@eerhardt
Copy link
MemberAuthor

I have it locally, and can send it to you. Or:

dotnet tool install --global runfodotnet tool update --global runforunfo get-helix-payload -j 2ebc65eb-6738-4487-9823-d41180299501 -w System.Drawing.Common.Tests -o %WOUTDIR%

Seehttps://github.com/dotnet/runtime/blob/main/eng/testing/debug-dump-template.md

@kant2002
Copy link
Contributor

Lineusing DrawingComWrappers.IPicture picture = (DrawingComWrappers.IPicture)DrawingComWrappers.Instance.GetOrCreateObjectForComInstance(lpPicture, CreateObjectFlags.None); already release instance of lpPicture in Dispose.

https://github.com/dotnet/runtime/pull/54636/files#diff-f587d46981bfe7aeb74b6390ab4035ef7355e1c5cfe849583efb14da68c0aa49R288 maybe here should be added AddRef.

@eerhardt
Copy link
MemberAuthor

Line using DrawingComWrappers.IPicture picture = (DrawingComWrappers.IPicture)DrawingComWrappers.Instance.GetOrCreateObjectForComInstance(lpPicture, CreateObjectFlags.None); already release instance of lpPicture in Dispose.

The AddRef happens (in QueryInterface) before the PictureWrapper class is created, here:

https://github.com/dotnet/runtime/pull/54636/files#diff-f587d46981bfe7aeb74b6390ab4035ef7355e1c5cfe849583efb14da68c0aa49R54-R58

Notice that x64 passes. It is just failing on x86.

kant2002 reacted with thumbs up emoji

@eerhardt
Copy link
MemberAuthor

There are also x64 tests failing, and these I can repro on my machine, but not 100% of the time.

The test failure is:

Assert.Throws() FailureExpected: typeof(System.ObjectDisposedException)Actual:   typeof(System.NotSupportedException): Specified method is not supported.---- System.NotSupportedException : Specified method is not supported.

We are expecting anObjectDisposedException, but aNotSupportedException is being thrown. This appears to be a quirk/bug withMarshal.ThrowExceptionForHR. I got it to repro on my machine and here's what I see in the debugger:

image

0x80131622 is the error code forObjectDisposedException:

internalconstintCOR_E_NOTSUPPORTED=unchecked((int)0x80131515);
internalconstintCOR_E_OBJECTDISPOSED=unchecked((int)0x80131622);

ButMarshal.ThrowExceptionForHR is throwingNotSupportedException, which is odd.@jkotas (or anyone else) have you ever seen this before? The only thing I found while searching was#47329, but that seems like something else.

@eerhardt
Copy link
MemberAuthor

There are also x64 tests failing

I was able to catch some of these in a debugger, and have figured out some more information. The case where it is failing is getting into:

if (pErrInfo !=NULL)
{
// If this represents a managed object...
// ...then get the managed exception object and also check if it is a __ComObject...
if (IsManagedObject(pErrInfo))

pErrInfo is non-null. When this occurs, the code inside thatif is settingpProtectedThrowable to aNotSupportedException, and that is what is getting returned to managed code and getting thrown byMarshal.ThrowExceptionForHR, even though I explicitly passed in0x80131622 (COR_E_OBJECTDISPOSED) to the method.

AFAICT, the reasonpErrInfo is non-null is because of this line in the calling method:

if (SafeGetErrorInfo(&pErrorInfo) != S_OK)

The managed C# code is passing inNULL for the error info, but this line is reading it fromSafeGetErrorInfo. Sometimes that is returningS_OK and an error info. From where? I don't have a clue 😄. But it feels like someone isn't clearing the previous error info here.

A naïve question: If I'm callingMarshal.ThrowExceptionForHR(int) and not passing in anerrorInfo, should this code even be readingSafeGetErrorInfo? It looks like there is support to pass-1 to the native code, and it won't read it. So should this C# line

publicstaticException?GetExceptionForHR(interrorCode)=>GetExceptionForHR(errorCode,IntPtr.Zero);

be changed toGetExceptionForHR(errorCode, new IntPtr(-1));?

@jkotas
Copy link
Member

Yes, COM IErrorInfo is mess. .NET interop assumes that all COM calls set it, but it is not the case in practice.

If I'm calling Marshal.ThrowExceptionForHR(int) and not passing in an errorInfo, should this code even be reading SafeGetErrorInfo?

Changing that would be breaking behavior change. It should be fine to pass innew IntPtr(-1) in the wrappers you have written in this PR.

AaronRobinsonMSFT reacted with thumbs up emoji

* Pass -1 to Marshal.GetExceptionForHR so it doesn't query GetErrorInfo, and always returns the correct exception type* Create the PictureWrapper with UniqueInstance, so it doesn't get cached. Caching it causes lifetime issues.
@eerhardt
Copy link
MemberAuthor

The musl library test leg is failing HTTP and sockets tests - unrelated to this change.

The CoreClr Pri0 arm64 test failure also look unrelated, but I can’t find a current issue tracking the failures.

kant2002 added a commit to kant2002/runtime that referenced this pull requestJun 28, 2021
This change just remove warning from ILLink and do not make attemptto convert other COM object creation to use ComWrappersAlso I have to add target net5.0-windows where ComWrappers would beused. Same concerns regarding testing as indotnet#54636Two calls inside OleDbDataAdapter call GetErrorInfo but do not do anything with results. That's probably mistake from previous refactoring. These parts does not touched and left as is. Need advice on that specific parts how to proceed.
@eerhardt
Copy link
MemberAuthor

Test failures are unrelated. Merging.

@eerhardteerhardt merged commit8707275 intodotnet:mainJun 28, 2021
@eerhardteerhardt deleted the DrawingCOM branchJune 28, 2021 16:39
thaystg added a commit to thaystg/runtime that referenced this pull requestJun 29, 2021
…bugger2* origin/main: (78 commits)  Fix unreached during dump. (dotnet#54861)  Fix lowering usage of an unset LSRA field. (dotnet#54731)  Fix setting breakpoints on AVX 256 instructions and other 32 byte immediate instructions (dotnet#54786)  Add perf_slow yaml (dotnet#54853)  Faster type load for scenarios made more common by generic math (dotnet#54588)  Make sure we consider buffer length when marshalling back Unicode ByValTStr fields (dotnet#54695)  Add YieldProcessor implementation for arm (dotnet#54829)  Remove ActiveIssue fordotnet#50968 (dotnet#54831)  Enable System.Text.Json tests for Wasm AOT (dotnet#54833)  Remove ActiveIssue fordotnet#51723 (dotnet#54830)  Fix load exception on generic covariant return type (dotnet#54790)  Obsolete X509Certificate2.PrivateKey and PublicKey.Key. (dotnet#54562)  First round of converting System.Drawing.Common to COMWrappers (dotnet#54636)  Fix alloc-dealloc mismatches (dotnet#54701)  Add one-shot ECB methods  [Mono] MSBuild Task housekeeping (dotnet#54485)  Move iOS/tvOS simulator AOT imports in the Mono workload (dotnet#54821)  Remove unnecessary char[] allocation from Uri.GetRelativeSerializationString (dotnet#54799)  Reduce overhead of Enumerable.Chunk (dotnet#54782)  Fix EnumMemberRefs always returning NULL (dotnet#54805)  ...
@ghostghost locked asresolvedand limited conversation to collaboratorsJul 28, 2021
Sign up for freeto subscribe to this conversation on GitHub. Already have an account?Sign in.

Reviewers

@jkoritzinskyjkoritzinskyjkoritzinsky left review comments

@jkotasjkotasjkotas left review comments

@tannergoodingtannergoodingtannergooding left review comments

@AaronRobinsonMSFTAaronRobinsonMSFTAaronRobinsonMSFT approved these changes

@krwqkrwqAwaiting requested review from krwq

@safernsafernAwaiting requested review from safern

Assignees

No one assigned

Projects

None yet

Milestone

No milestone

Development

Successfully merging this pull request may close these issues.

9 participants

@eerhardt@ViktorHofer@ericstj@safern@AaronRobinsonMSFT@kant2002@jkotas@jkoritzinsky@tannergooding

[8]ページ先頭

©2009-2025 Movatter.jp