Kestrelhttpserver: uv_buf_t size faulty on windows?

Created on 6 Sep 2016  路  7Comments  路  Source: aspnet/KestrelHttpServer

Hey guys, I was looking at the code of kestrel, in particular here: https://github.com/aspnet/KestrelHttpServer/blob/dev/src/Microsoft.AspNetCore.Server.Kestrel/Internal/Networking/Libuv.cs#L431

And I wondered, isn't sizeof(WSABUF) on windows 8/12 for 32/64 bit systems?

WSABUF consists of ULONG and a pointer, a ULONG according to http://stackoverflow.com/questions/384502/what-is-the-bit-size-of-long-on-64-bit-windows it is 4 bytes (or uint) even on 64bit windows.

I looked at the reference source code, and it seems to be a (int, intptr) too: http://referencesource.microsoft.com/#System/net/System/Net/_OSSOCK.cs,29

corefx: https://github.com/dotnet/corefx/blob/master/src/Common/src/Interop/Windows/Winsock/WSABuffer.cs#L12-L13

How is the current definition of uv_buf_t working on windows?

Most helpful comment

@txdv Yes:

[StructLayout(LayoutKind.Sequential)]
struct WSABuffer
{
    internal int Length; // Length of Buffer
    internal IntPtr Pointer;// Pointer to Buffer
}

class Program
{
    static unsafe void Main(string[] args)
    {
        var s = new WSABuffer();
        int* pLength = &s.Length;
        IntPtr* pPointer = &s.Pointer;
        IntPtr addrLength = (IntPtr)pLength;
        IntPtr addrPointer = (IntPtr)pPointer;

        Console.WriteLine(addrLength.ToString("x"));
        Console.WriteLine(addrPointer.ToString("x"));
    }
}

Output:

f3c1ffebc8

All 7 comments

Alignment. There are 4 bytes of padding in WSABUF after len so buf is aligned to an 8-byte boundary (on 64-bit).

What does the alignment?

A struct member will normally start at an address that matches it's alignment requirement. On 64-bit the pointer should be 8-byte aligned. Since the preceding member takes 4 bytes, the compiler inserts 4 bytes of padding after it so that buf starts at an 8-byte boundary.

Some code:

#include <WinSock2.h>

int main()
{
    WSABUF buf;
    printf("sizeof(WSABUF): %d\n", sizeof(WSABUF));
    printf("sizeof(WSABUF.len): %d\n", sizeof(buf.len));
    printf("sizeof(WSABUF.buf): %d\n", sizeof(buf.buf));
    printf("WSABUF.len: %p\n", &buf.len);
    printf("WSABUF.buf: %p\n", &buf.buf);
    return 0;
}

Output:

sizeof(WSABUF): 16
sizeof(WSABUF.len): 4
sizeof(WSABUF.buf): 8
WSABUF.len: 000000475A7FF6C8
WSABUF.buf: 000000475A7FF6D0

So the jit does the same for this?

    [StructLayout(LayoutKind.Sequential)]
    internal struct WSABuffer
    {
        internal int Length; // Length of Buffer
        internal IntPtr Pointer;// Pointer to Buffer
    }

StructLayout(LayoutKind.Sequential) means maintain the order otherwise it may swap the two fields for tighter packing.

StructLayout(LayoutKind.Explicit) is for exact specified positioning, when you additionally have to use FieldOffset attributes on the fields to specify their positions; and they can be overlapped for example in EventDescriptor

@txdv Yes:

[StructLayout(LayoutKind.Sequential)]
struct WSABuffer
{
    internal int Length; // Length of Buffer
    internal IntPtr Pointer;// Pointer to Buffer
}

class Program
{
    static unsafe void Main(string[] args)
    {
        var s = new WSABuffer();
        int* pLength = &s.Length;
        IntPtr* pPointer = &s.Pointer;
        IntPtr addrLength = (IntPtr)pLength;
        IntPtr addrPointer = (IntPtr)pPointer;

        Console.WriteLine(addrLength.ToString("x"));
        Console.WriteLine(addrPointer.ToString("x"));
    }
}

Output:

f3c1ffebc8

You are my hero!

Thank you very much.

Was this page helpful?
0 / 5 - 0 ratings