-
Notifications
You must be signed in to change notification settings - Fork 36
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
System.AccessViolationException on Windows 10 (64 Bit) after 64 bit-fix? #13
Comments
I'm workin on it |
Thanks a lot for your hard work! |
@Bassman2 Sorry to bother, but has there been any progress in that regard? |
Hi ralmo, feel free to help me. It's not so easy to catch the problem because it is sporadic and the exception is catched by the system. |
I'm glad you were at least able to confirm the issue at all. Not sure if I'm of much help with the actual technical implementation but maybe I can manage to get additional information about how to reproduce the issue more reliable or find one of the originating code line. |
The problem is that the exception is catched by the system but I need a full stack trace for analysis. That should be possible with this attributes for the calling function.
But I cannot reproduce it with this attribues. |
I have also encountered this problem, but it appears too rarely to be easily reproduced (I have to do complex operations in my application while repeatedly plugging-in/out the device to even have a chance at reproducing it). And then it crashes without any stack trace, like reported above. I'll add suggested attributes and report back if I find any more info. However, what is more worrying, is that it happens even when the application is running in 32bit mode, which worked well before. Therefore I propose reverting all changes which attempt to make 64bit mode work (436ab2e, maybe more?) and making a new, 32bit only release. It would have all the improvements which were added since that commit, but would be stable for those who rely on the library, and don't need it to be 64bit. Further attempts to make 64bit work could be done on an experimental branch, which would be merged once we figure out and fix what is going wrong now. Thoughts? |
@Bassman2 As always, thanks for your hard work. I will do some tests during the weekend with those attributes and report back. @Darkyenus Your suggestion would be a sensible approach until a fix is determined. The performance optimizations are a huge advancement which I'd love to make use of but cannot right now. |
I tried adding these attributes to almost every method in my call hierarchy but it didn't change anything. I then tried some semi-desperate measures and added a huge load of debug prints. The line where it finally breaks is within public static PropVariant FromValue(PROPVARIANT value)
{
System.Diagnostics.Debug.WriteLine($"FromValue: value = {value}");
var size = Marshal.SizeOf(value);
System.Diagnostics.Debug.WriteLine($"FromValue: sizeof value = { size}");
IntPtr ptrValue = Marshal.AllocHGlobal(size);
System.Diagnostics.Debug.WriteLine($"FromValue: new pointer = {ptrValue} will now structureToPtr");
Marshal.StructureToPtr(value, ptrValue, false);
System.Diagnostics.Debug.WriteLine($"FromValue: structureToPtr was fine, marshalling back to c#");
//
// Marshal the pointer into our C# object
//
var result = (PropVariant)Marshal.PtrToStructure(ptrValue, typeof(PropVariant));
System.Diagnostics.Debug.WriteLine($"FromValue: conversion successful = {result}");
return result;
} Here's the "call stack" after
I hope this helps somehow? |
I have been digging around the documentation, trying to verify if the reported size of PROPVARIANT is correct, but my findings were inconclusive - I am not sure how is this all handled on 64bit systems. But what I did found is the documentation of PROPVARIANT where they claim that it is the same size as DECIMAL (16 bytes, I think). Also, I am not sure if this is not just a problem with my code, but I suspect that there is a native memory leak somewhere. When I do something like
the native memory keeps steadily increasing, up to an out of memory error. I am not opening a separate issue for this yet, because I haven't yet created a minimal repro case to confirm that it really is a problem with the library, but I am mentioning it here, because it may be related. |
Revert 64-bit changes made in 436ab2e, to check whether they fix some problems which appeared lately, especially Bassman2#13.
I have been doing some experiments and have come to a conclusion, that having 64bit support alongside 32bit, in the same dll, is unfeasibly hard. I'll document my findings here, as it may be useful to others and to my future self. Some/all of this may be wrong, so if you spot any mistakes, please let me know. Struct layoutsChecks with native C++ have confirmed, that PROPVARIANT is indeed 16 bytes wide on 32bit and 24bit wide on 64bit. However, it is impossible to have C# struct with different layout on 32/64bit. So we would have to have two different dlls, one with 32bit struct layouts and one for 64bit. Those would have to be distributed separately, as Windows don't support "multi-architecture binaries". 64bit COM wrapper dllThe library depends on slightly modified Generating x64 wrapper is trickier, as tlbimp gets redirected to the 32bit dll and complains that it is not compatible with x64 (at least on my machine: I have also tried to generate .dlls through Memory leaksIt seems that the memory leak I mentioned in the previous comment and in #15 is unrelated to 64-bitness, but is still troubling. Type marshalling done by the wrapper should have been enough to ensure correct memory management, but it seems that this is possible only for reference types (i.e. objects, not structs), in particular for However |
@Darkyenus : Sadly, this appears to be a little out of my league so I can't really suggest an appropriate solution. But if I understand you correctly, MediaDevices will most likely need to be deployed with different dll's for 32/64 bit systems? |
@anothertal3 Yes, I think so. But maybe it would be possible to do it so that the runtime automatically loads the correct dll for the platform, but I don't know how hard that is in C# land. |
Revert 64-bit changes made in 436ab2e, to check whether they fix some problems which appeared lately, especially Bassman2#13.
Haven't tried something like that but there seem to be options, e.g. https://stackoverflow.com/a/2594135 So, regarding the actual files that need to be used: Switching between a |
@anothertal3 Yes, loading different DLL could work well. I am currently shipping with 32bit (default) build of my cleanup branch and I have not had any problems with it (except for those which were caused by Android itself and their slightly idiotic need to refresh manually after each filesystem change, which doesn't properly support file removal, but I digress). Changes made in that fork:
That is basically it. I would suggest against mixing my forked version with the original, because there may have been some minor API changes which could cause problems down the line and also because of that fixed memory leak. If @Bassman2 is insterested, I will create a PR for the changes on the |
Hi All, I added platform handling to the MediaDevices.csproj to switch between different interops made for any, x86 and x64. I hope this will help. |
@Bassman2 : I was able to build a "x64" variant and successfully execute my tests with it. A "x86" build crashes immediately on a 64 bit machine (as expected). I assume one would need to create to application setups for deployment then. @Darkyenus : Thanks for your detailed input. I tested your forked build as well, but wasn't able to get it to work on my 64 bit machine (32 was fine). I've not yet committed a lot of time, though, so maybe there was a simple oversight on my end.
The only change I made was changing the referenced Project from @Bassman2 's MediaDevices to the fork so I'm uncertain if anything more had to be done? |
I can currently not reproduce it with the new Facade branch. The x64 build works for x64 apps, the x86 build works for x86 apps and the "Any CPU" build works for both with on exception. ToByteArray does not work with "Any CPU". Does anyone have an idea? Please try if you can confirm my result. |
I can confirm that x64 seems to be working. I'm not around a different machine, however, to test the other right now. |
To avoid the use of different dlls for x86 and x64 I tried to stop working with the generated COM wrapper classes but to implement the COM wrapper classes manually. This gives me more control over the COM wrapper classes. A first attempt is in the "manual" branch. |
Fixed with own COM wrapper classes |
Can confirm that this worked on x64. I did have a strange crash at first but all further attempts were successful. |
Hello Bassman2,
after my successful performance experiments in #7 using a Windows 7 x64 PC I wanted to repeat the same for my main machine running Windows 10 (v1803) x64.
However, my WPF application always crashes during the run with the following exception.
Sadly I haven't been able to catch this exception or any corresponding callstack at all and I don't really know, which operations actually fails.
The test does the following:
root.EnumerateFileSystemInfos("*", SearchOption.AllDirectories)
MediaFileInfo
handle for each file in a listMediaFileInfo.CopyTo
The exception always triggers during this run but sometimes during phase 2 and during phase 3.
One thing I was able to determine: the issue only appears after commit 436ab2e which included the "64-bit fix" for #6. Using the commit before ( 01a6e6a) works fine (albeit slow).
To be honest: I'm uncertain about the code changes you implemented then and what they actually affect. Do you have any suggestions on how to analyze this appropriately?
Best regards,
tale
The text was updated successfully, but these errors were encountered: