note - the hung was only because thread_1 and thread_2 use the same synchronous file handle. because synchronous io is sequential per file file object. if threads will be use separate file handles(not duplicated) - will be no hang. because separate file object locks we can change demo code in next way - not pass handle to second thread but let it open file himself.
ULONG WINAPI thread_proc(HANDLE hFile)
{
hFile = CreateFileW(L"*", FILE_GENERIC_WRITE,
FILE_SHARE_WRITE|FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0);
if (hFile != INVALID_HANDLE_VALUE)
{
OVERLAPPED ov = {};
if (LockFileEx(hFile, LOCKFILE_EXCLUSIVE_LOCK, 0, 1, 0, &ov))
{
MessageBoxW(0, L"inside lock", L"thread_proc", MB_ICONINFORMATION);
UnlockFile(hFile, 0, 0, 1, 0);
}
CloseHandle(hFile);
}
return GetLastError();
}
HANDLE hFile = CreateFileW(L"*", FILE_GENERIC_WRITE,
FILE_SHARE_WRITE|FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0);
if (hFile != INVALID_HANDLE_VALUE)
{
HANDLE hThread = 0;
OVERLAPPED ov = {};
if (LockFileEx(hFile, LOCKFILE_EXCLUSIVE_LOCK, 0, 1, 0, &ov))
{
if (hThread = CreateThread(0, 0, thread_proc, 0, 0, 0))
{
// give time to thread_proc call LockFileEx
MessageBoxW(0, 0, L"Now thread Not Hung!", MB_ICONINFORMATION);
ULONG NumberOfBytesWritten;
if (!WriteFile(hFile, “*”, 1, &NumberOfBytesWritten, 0))
{
GetLastError();
}
}
UnlockFile(hFile, 0, 0, 1, 0);
}
if (hThread)
{
WaitForSingleObject(hThread, INFINITE);
CloseHandle(hThread);
}
CloseHandle(hFile);
}
this show that this is not a problem in case 2 separate applications, which used separate file handle.
code:
- thread_1:LockFileEx(h1)
- thread_2:LockFileEx(h2)
- thread_1:WriteFile(h1)
- thread_1:UnlockFile(h1)
assume that h1 -> FileObject1 != FileObject2 <- h2
will be executed without problems. thread_2 will be wait until thread_1 not call UnlockFile(h1), but this not prevent thread_1 from complete call WriteFile(h1), because FileObject1->Busy == FALSE.
call LockFileEx(h2) set FileObject2->Busy = TRUE. so we not hung in IopAcquireFileObjectLock
- not hold 3.
but next code always hung (in all windows versions):
- thread_1:LockFileEx(h1)
- thread_2:LockFileEx(h1)
- thread_1:WriteFile(h1)
- thread_1:UnlockFile(h1)
thread_1 will be wait inside WriteFile - IopAcquireFileObjectLock on FileObject->Lock
so:
3. finished only only after 2.
2. finished only after 4.
4. finished (even begin) only after 3.