Bug 4722 - ICustomMarshaler CleanUpNativeData called when it shouldn't be, return: MarshalAs
Summary: ICustomMarshaler CleanUpNativeData called when it shouldn't be, return: Marsh...
Alias: None
Product: Runtime
Classification: Mono
Component: Interop ()
Version: unspecified
Hardware: PC Linux
: --- normal
Target Milestone: ---
Assignee: Bugzilla
Depends on:
Reported: 2012-04-29 17:42 UTC by James Bellinger
Modified: 2012-05-03 15:02 UTC (History)
4 users (show)

Is this bug a regression?: ---
Last known good build:

different between Mono for Windows and MS.Net (8.65 KB, application/zip)
2012-05-03 09:39 UTC, James Bellinger

Notice (2018-05-24): bugzilla.xamarin.com is now in read-only mode.

Please join us on Visual Studio Developer Community and in the Xamarin and Mono organizations on GitHub to continue tracking issues. Bugzilla will remain available for reference in read-only mode. We will continue to work on open Bugzilla bugs, copy them to the new locations as needed for follow-up, and add the new items under Related Links.

Our sincere thanks to everyone who has contributed on this bug tracker over the years. Thanks also for your understanding as we make these adjustments and improvements for the future.

Please create a new report on GitHub or Developer Community with your current version information, steps to reproduce, and relevant error messages or log files if you are hitting an issue that looks similar to this resolved bug and you do not yet see a matching new report.

Related Links:

Description James Bellinger 2012-04-29 17:42:52 UTC
I am noticing in my custom marshaler that CleanUpNativeData is being called despite MarshalManagedToNative never being called.

In particular, this is occuring for return values:

[return: MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(Utf8Marshaler))]
public static extern string udev_list_entry_get_name(IntPtr entry);

http://msdn.microsoft.com/en-us/library/system.runtime.interopservices.icustommarshaler.aspx suggests that CleanUpNativeData should be called for the case where MarshalManagedToNative was done. However, I am finding that, despite *MarshalNativeToManaged* being called here, I am receiving a call for CleanUpNativeData on the IntPtr return.

I have worked around this issue in my code by having GetInstance create a new instance each time which stores an _allocated boolean. However, Mono should not be calling CleanUpNativeData when it has not called MarshalManagedToNative. The same error might occur for CleanUpManagedData/MarshalNativeToManaged, but I have not checked.

In any case, this is a Mono bug and definitely worth investigating. It's probably gotten through for so long because it only occurs on return values.
Comment 1 Zoltan Varga 2012-05-02 20:13:14 UTC
We have tests for these behaviour, and as far as I remember, they pass on MS.NET, so the MS implementation also calls CleanupNativeData on the return value. Otherwise, the native memory returned by the native function will never be freed. Could you test what MS does in this case ?
Comment 2 James Bellinger 2012-05-03 09:39:37 UTC
Created attachment 1800 [details]
different between Mono for Windows and MS.Net
Comment 3 James Bellinger 2012-05-03 09:43:33 UTC
Hmm, it appears the same (differing from documentation) behavior occurs in MS.Net. This is trouble for me and unquestionably a bug (this behavior means you can't tell if you're being asked to free something you allocated, or deal with something you didn't), but I guess I can work around it by keeping a Dictionary of all allocations I've done myself with the marshaler.

I did however run into a difference in P/Invoke while investigating this however.
It appears that, if in a single P/Invoke call, the marshaler and marshal cookie are the same, MS.Net will reuse the marshaler instance for both. Mono creates two. The latter's not actually bad, probably better really if I could rely on it, but I should mention it since it's a difference that might result in hard to track down bugs when porting...

MS.Net output:
0 0 0 0 0 1
1/1: 0 0 1 0 0 1
1/1: 0 0 1 1 0 1
1/1: 0 1 1 1 0 1

Mono output:
0 0 0 0 0 1
1/1: 0 0 1 0 0 1
0 0 1 0 0 2
2/2: 0 0 1 1 0 2
2/2: 0 1 1 1 0 2
Comment 4 Zoltan Varga 2012-05-03 10:57:49 UTC
You can embed a flag in the encoded data which tells CleanupNativeData who allocated the data.
Comment 5 James Bellinger 2012-05-03 14:38:08 UTC
Hmm. The difference in marshal instancing are not an issue then?
Comment 6 Zoltan Varga 2012-05-03 15:02:57 UTC
It might become an issue in the future, but until somebody runs into it, it can stay as it is.