[libvirt] alignment of data fields when compiling with mingwin
arnaud.champion at devatom.fr
arnaud.champion at devatom.fr
Sun Oct 17 18:47:35 UTC 2010
Wow, we got it !
In fact, you got it...
By pinning strdup function, it works. No more heap problem !!!!!
I'm now able to use the virConnectOpenAuth function, and that's great.
Thanks a lot for your help.
Arnaud
--------------------------------------------------
From: <arnaud.champion at devatom.fr>
Sent: Sunday, October 17, 2010 8:39 PM
To: "Matthias Bolte" <matthias.bolte at googlemail.com>
Cc: <libvir-list at redhat.com>
Subject: Re: [libvirt] alignment of data fields when compiling with mingwin
> I will try these ways, in my search I have also seen some explainations
> that said to PInvoke char* as IntPtr instead of string in structures, then
> use Marshal.PtrToStringAnsi/Marshal.StringToHGlobalAnsi but for now it
> fails. I will try with the strdup PInvoke.
>
> --------------------------------------------------
> From: "Matthias Bolte" <matthias.bolte at googlemail.com>
> Sent: Sunday, October 17, 2010 6:58 PM
> To: <arnaud.champion at devatom.fr>
> Cc: <libvir-list at redhat.com>
> Subject: Re: [libvirt] alignment of data fields when compiling with
> mingwin
>
>> A bit of googling turns this function up
>>
>> Marshal.StringToHGlobalAnsi
>> Marshal.StringToHGlobalAuto
>> Marshal.StringToHGlobalUni
>>
>> they create an unmanaged copy a managed string.
>>
>> But those might not help, because the docs say that the returned
>> IntPtr must be freed using Marshal.FreeHGlobal. All this methods use
>> the GlobalAlloc function from the WinAPI to allocate memory. Maybe
>> GlobalAlloc is not compatible with the "libc" free function that
>> libvirt will use to free the memory.
>>
>> A bit more googling told me how to import functions from DLLs in C#.
>> This one imports strdup:
>>
>> [DllImport("msvcrt.dll"), CLSCompliant(false)]
>> public static extern IntPtr _strdup([Const] IntPtr strSource);
>>
>> Maybe you can do something like this:
>>
>> string result_original = ...;
>> IntPtr result_global = StringToHGlobalAuto(result_original);
>> IntPtr result_duplicated = _strdup(result_global);
>> FreeHGlobal(result_global);
>>
>> Then pass result_duplicated to libvirt.
>>
>> I'm not sure if that works at all. Maybe there is a simpler/better
>> solution for this.
>>
>> Matthias
>>
>> 2010/10/17 <arnaud.champion at devatom.fr>:
>>> You are perfectly right, I have to find the way to avoid C# memory
>>> freeing !
>>> You're a master ;)
>>>
>>> Arnaud
>>>
>>> --------------------------------------------------
>>> From: "Matthias Bolte" <matthias.bolte at googlemail.com>
>>> Sent: Sunday, October 17, 2010 3:21 PM
>>> To: <arnaud.champion at devatom.fr>
>>> Cc: <libvir-list at redhat.com>
>>> Subject: Re: [libvirt] alignment of data fields when compiling with
>>> mingwin
>>>
>>>> 2010/10/17 <arnaud.champion at devatom.fr>:
>>>>>
>>>>> Hi Matthias,
>>>>>
>>>>> I'm working on the virConnectOpenAuth method C# binding. And in fact,
>>>>> It
>>>>> partially work. Let me explain you :
>>>>>
>>>>
>>>>
>>>>> Now, I have made a little code to connect to an esx hypervisor like
>>>>> this
>>>>> :
>>>>>
>>>>> ... some init stuff...
>>>>>
>>>>> // Define the virConnectAuth struct
>>>>> virConnectAuth auth = new virConnectAuth
>>>>> {
>>>>> cbdata = authDataPtr,
>>>>> cb = AuthCallback,
>>>>> credtypes = credtypesPtr,
>>>>> ncredtype = (uint)credtypes.Length
>>>>> };
>>>>>
>>>>> IntPtr conn = libVirt.virConnectOpenAuth(tbURI.Text, ref
>>>>> auth,
>>>>> 0);
>>>>>
>>>>> I have the call back method "AuthCallback" defined like this :
>>>>>
>>>>> private int AuthCallback(IntPtr creds, uint ncred, IntPtr cbdata)
>>>>> {
>>>>>
>>>>> AuthData authData = (AuthData) Marshal.PtrToStructure(cbdata,
>>>>> typeof (AuthData));
>>>>> int offset = 0;
>>>>> int credIndex = 0;
>>>>>
>>>>> while (credIndex < ncred)
>>>>> {
>>>>> IntPtr currentCred = new IntPtr(creds.ToInt32() +
>>>>> offset);
>>>>>
>>>>> virConnectCredential cred = (virConnectCredential)
>>>>> Marshal.PtrToStructure(currentCred, typeof (virConnectCredential));
>>>>> offset += Marshal.SizeOf(cred);
>>>>> switch(cred.type)
>>>>> {
>>>>> case virConnectCredentialType.VIR_CRED_AUTHNAME:
>>>>> cred.result = authData.user_name;
>>>>> cred.resultlen = (uint)authData.user_name.Length;
>>>>> break;
>>>>> case virConnectCredentialType.VIR_CRED_PASSPHRASE:
>>>>> cred.result = authData.password;
>>>>> cred.resultlen = (uint) authData.password.Length;
>>>>> break;
>>>>> default:
>>>>> return -1;
>>>>> }
>>>>> Marshal.StructureToPtr(cred, currentCred, true);
>>>>>
>>>>> credIndex++;
>>>>> }
>>>>> return 0;
>>>>> }
>>>>>
>>>>> When I test this code, all seems to work well, I mean the
>>>>> "AuthCallback"
>>>>> method is called twice, once for authname and once for passphrase.
>>>>>
>>>>> But when I run my code in a debugger of Visual Studio I have these
>>>>> messages
>>>>> :
>>>>>
>>>>> HEAP[Win32_virConnectOpenAuth.exe]: Invalid address specified to
>>>>> RtlFreeHeap( 00700000, 00EE6D78 )
>>>>> HEAP[Win32_virConnectOpenAuth.exe]: Invalid address specified to
>>>>> RtlFreeHeap( 00700000, 00EE6A80 )
>>>>> HEAP[Win32_virConnectOpenAuth.exe]: Invalid address specified to
>>>>> RtlFreeHeap( 00700000, 00EE6D78 )
>>>>> HEAP[Win32_virConnectOpenAuth.exe]: Invalid address specified to
>>>>> RtlFreeHeap( 00700000, 00EE6A80 )
>>>>> HEAP[Win32_virConnectOpenAuth.exe]: Invalid address specified to
>>>>> RtlFreeHeap( 00EE0000, 007DE480 )
>>>>>
>>>>> but the connection is done, and I am able to list domains of the
>>>>> hypervisor
>>>>> for example. The real problem is that this program only work inside
>>>>> the
>>>>> the
>>>>> visual studio debugger, when I launch the executable without debugger,
>>>>> it
>>>>> fails.
>>>>> So I am searching why this doesn't work, I want to check the bindings.
>>>>> And I
>>>>> also want to try to fill the "result" member of the
>>>>> virConnectCredential
>>>>> structure directly to understanding what can be the problem.
>>>>
>>>>
>>>> Okay, you see an invalid free call either because free is called on an
>>>> initial invalid pointer of because free is called twice on the same
>>>> pointer (on the second call the pointer is invalid).
>>>>
>>>> When you look at the libvirt codebase in src/util/authhelper.c in
>>>> virRequestUsername you'll see that the cred.result is returned to the
>>>> driver directly without making a copy of it. The driver is then
>>>> responsible for freeing this memory. So the ownership of the memory
>>>> cred.result points to is transferred from your callback to the driver.
>>>>
>>>> I think you see a double-free here because libvirt and C# are both
>>>> trying to free the same memory, but C# should not do this. I'm not
>>>> familiar with C#, so I'm just guessing here based on what you have
>>>> described. This cannot be a problem with the alignment or struct
>>>> layout, otherwise authentication would not work.
>>>>
>>>> You can test if it's double-free by applying the attached patch to
>>>> libvirt. This patch stops the virRequestUsername and
>>>> virRequestPassword functions from transferring ownership of the
>>>> cred.result by copying the string. This creates a memory leak in the
>>>> normal case, but should stop the double-free in case C# is freeing
>>>> cred.result here.
>>>>
>>>> Matthias
>>>>
>>>>
>>>>> Anyway, thanks ofr these informations, this can help.
>>>>>
>>>>> Best regards,
>>>>>
>>>>> Arnaud
>>>>>
>>>>> --------------------------------------------------
>>>>> From: "Matthias Bolte" <matthias.bolte at googlemail.com>
>>>>> Sent: Sunday, October 17, 2010 12:04 PM
>>>>> To: <arnaud.champion at devatom.fr>
>>>>> Cc: <libvir-list at redhat.com>
>>>>> Subject: Re: [libvirt] alignment of data fields when compiling with
>>>>> mingwin
>>>>>
>>>>>> 2010/10/15 <arnaud.champion at devatom.fr>:
>>>>>>>
>>>>>>> Hi,
>>>>>>>
>>>>>>> I'm currently working on libvirt csharp bindings, and I have some
>>>>>>> trouble
>>>>>>> with virConnectOpenAuth marshaling.
>>>>>>> I need to know what is the alignment of data fields in structure
>>>>>>> when
>>>>>>> compiling with mingwin.
>>>>>>> Anyone know that ?
>>>>>>>
>>>>>>> cheers,
>>>>>>>
>>>>>>> Arnaud Champion
>>>>>>>
>>>>>>
>>>>>> Why do you need to know the alignment? Do you need to build or access
>>>>>> members of the virConnectCredential or virConnectAuth structs by
>>>>>> offset in memory?
>>>>>>
>>>>>> The Wikipedia article about data structure alignment might be helpful
>>>>>> when you really need to care about alignment.
>>>>>>
>>>>>> If you actually need the offset of the members in those structs you
>>>>>> can just use the offsetof macro and let the compiler tell you:
>>>>>>
>>>>>> #include <stdio.h>
>>>>>> #include <stddef.h>
>>>>>> #include <libvirt/libvirt.h>
>>>>>>
>>>>>> void main(void)
>>>>>> {
>>>>>> printf("virConnectCredential\n");
>>>>>> printf(" type %2u\n", offsetof(virConnectCredential, type));
>>>>>> printf(" prompt %2u\n", offsetof(virConnectCredential, prompt));
>>>>>> printf(" challenge %2u\n", offsetof(virConnectCredential,
>>>>>> challenge));
>>>>>> printf(" defresult %2u\n", offsetof(virConnectCredential,
>>>>>> defresult));
>>>>>> printf(" result %2u\n", offsetof(virConnectCredential, result));
>>>>>> printf(" resultlen %2u\n", offsetof(virConnectCredential,
>>>>>> resultlen));
>>>>>> printf("\n");
>>>>>> printf("virConnectAuth\n");
>>>>>> printf(" credtype %2u\n", offsetof(virConnectAuth, credtype));
>>>>>> printf(" ncredtype %2u\n", offsetof(virConnectAuth, ncredtype));
>>>>>> printf(" cb %2u\n", offsetof(virConnectAuth, cb));
>>>>>> printf(" cbdata %2u\n", offsetof(virConnectAuth, cbdata));
>>>>>> }
>>>>>>
>>>>>>
>>>>>> Output on x86:
>>>>>>
>>>>>> virConnectCredential
>>>>>> type 0
>>>>>> prompt 4
>>>>>> challenge 8
>>>>>> defresult 12
>>>>>> result 16
>>>>>> resultlen 20
>>>>>>
>>>>>> virConnectAuth
>>>>>> credtype 0
>>>>>> ncredtype 4
>>>>>> cb 8
>>>>>> cbdata 12
>>>>>>
>>>>>>
>>>>>> Output on x86_64:
>>>>>>
>>>>>> virConnectCredential
>>>>>> type 0
>>>>>> prompt 8
>>>>>> challenge 16
>>>>>> defresult 24
>>>>>> result 32
>>>>>> resultlen 40
>>>>>>
>>>>>> virConnectAuth
>>>>>> credtype 0
>>>>>> ncredtype 8
>>>>>> cb 16
>>>>>> cbdata 24
>>>>>>
>>>>>> [1]
>>>>>>
>>>>>> http://en.wikipedia.org/wiki/Data_structure_alignment#Typical_alignment_of_C_structs_on_x86
>>>>>>
>>>>>> Matthias
>>>>>
>>>>>
>>>>>
>>>>
>>>
>>>
>>
>
> --
> libvir-list mailing list
> libvir-list at redhat.com
> https://www.redhat.com/mailman/listinfo/libvir-list
More information about the libvir-list
mailing list