Why .Net code version hangs, but C++ not?

1

Why does the same code in .Net (C#) hangs, but in C++ it isn't? The really problem is in System.IO.FileStream, but I reduced it down to CreateFile, nevertheless it still hangs in .Net (while being almost 100% analogue to C++ code):

using System;
using System.Runtime.InteropServices;
using System.Threading;

namespace ConsoleApplication1
{
    class Program
    {
        static IntPtr _handle;

        static void Main()
        {
            _handle = CreateFile("test.txt", GENERIC_READ | GENERIC_WRITE,
                FILE_SHARE_READ | FILE_SHARE_WRITE, IntPtr.Zero,
                OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, IntPtr.Zero);

            new Thread(MyProc) { IsBackground = true }.Start();
            new Thread(MyProc) { IsBackground = true }.Start();

            Console.ReadKey();
        }

        static void MyProc()
        {
            for (int i = 0; i < int.MaxValue; i++)
            {
                Console.WriteLine(i);

                var _overlapped = new NativeOverlapped();

                LockFileEx(_handle, LOCKFILE_EXCLUSIVE_LOCK, 0, int.MaxValue, int.MaxValue, ref _overlapped);

                Thread.Sleep(50);

                UnlockFileEx(_handle, 0, int.MaxValue, int.MaxValue, ref _overlapped);
            }
        }

        public const int LOCKFILE_EXCLUSIVE_LOCK = 0x00000002;

        [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)]
        public static extern bool LockFileEx(IntPtr hFile, int flags, int reserved, int numberOfBytesToLockLow, int numberOfBytesToLockHigh,
            ref NativeOverlapped overlapped);

        [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)]
        public static extern bool UnlockFileEx(IntPtr hFile, int reserved, int numberOfBytesToUnlockLow, int numberOfBytesToUnlockHigh,
            ref NativeOverlapped overlapped);

        public const int GENERIC_READ = unchecked((int)0x80000000L);
        public const int GENERIC_WRITE = (int)0x40000000L;

        public const int OPEN_ALWAYS = 4;

        public const int FILE_SHARE_READ = 0x00000001;
        public const int FILE_SHARE_WRITE = 0x00000002;
        public const int FILE_SHARE_DELETE = 0x00000004;

        public const int FILE_ATTRIBUTE_NORMAL = 0x00000080;

        [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)]
        public static extern IntPtr CreateFile(string fileName, int desiredAccess, int shareMode,
            IntPtr pSecurityAttributes, int creationDisposition, int flagsAndAttributes, IntPtr hTemplateFile);
    }
}

And here is C++ version which do not hang:

#include "stdafx.h"

#include <thread>
#include <Windows.h>

HANDLE hFile;

DWORD WINAPI MyProc(LPVOID lpParam);

int _tmain(int argc, _TCHAR* argv[])
{
    hFile = CreateFile(L"test.txt", GENERIC_READ | GENERIC_WRITE,
        FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
        OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);  

    HANDLE hThread1 = CreateThread(NULL, 0, MyProc, NULL, 0, NULL);
    HANDLE hThread2 = CreateThread(NULL, 0, MyProc, NULL, 0, NULL);

    int ch = getchar();

    return 0;
}

DWORD WINAPI MyProc(LPVOID lpParam)
{
    for(int i = 0; i < INT_MAX; i++)
    {
        printf("%d\r\n", i);

        OVERLAPPED overlapped = {0};

        LockFileEx(hFile, LOCKFILE_EXCLUSIVE_LOCK, 0, INT_MAX, INT_MAX, &overlapped);

        Sleep(50);

        UnlockFileEx(hFile, 0, INT_MAX, INT_MAX, &overlapped);
    }

    return 0;
}
c#
deadlock
hang
createfile
lockfile
asked on Stack Overflow May 17, 2015 by frtnum • edited May 17, 2015 by frtnum

1 Answer

-1

It looks like it's invalid to call LockFileEx with LOCKFILE_EXCLUSIVE_LOCK on the same file handle twice. It have to be different file handles or some kind of in-process synchronization for the handle.

The disturbing thing is that there is no unambiguity for the question in MSDN documentation. And there is no clear message of error at runtime. Even more, it seems to me that the problem reproduced only on my computer. This is ugly some kind.

answered on Stack Overflow May 17, 2015 by frtnum • edited May 17, 2015 by frtnum

User contributions licensed under CC BY-SA 3.0