[libvirt] alignment of data fields when compiling with mingwin

arnaud.champion at devatom.fr arnaud.champion at devatom.fr
Sun Oct 17 15:38:33 UTC 2010


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
>>
>>
>>
> 




More information about the libvir-list mailing list