3

How can I block a file on Windows using C++ in a blocking fashion? By blocking I mean... a lock is requested and if the file is locked it will wait until it is unlocked, once the file is unlocked by another system process than the execution resumes.

P.S.: If there's some kind of cross platform solution I'd prefer it.

petersaints
  • 1,899
  • 3
  • 18
  • 25
  • 1
    Do you really want to lock a file, or are you simply trying to synchronize the processes? If latter, then you can use a global mutex (i.e. use the same `lpName` parameter when calling `CreateMutex` in different processes). – Branko Dimitrijevic Feb 08 '12 at 03:19

1 Answers1

4

By default, LockFileEx blocks until the lock can be acquired (although you can tell it not to with LOCKFILE_FAIL_IMMEDIATELY).

Clearly this isn't cross-platform.

Update

This horrible code sample illustrates that it works (you'll probably need to change the filename in CreateFile from "lockBlock.cpp"). Run one instance of the program and it will acquire the lock. Run a second instance and it will block. Press <enter> in the first instance to release the lock, and the second instance will unblock and acquire the lock.

int _tmain(int argc, _TCHAR* argv[])
{
    HANDLE hFile = ::CreateFileA("lockBlock.cpp", GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0);
    OVERLAPPED overlapped;
    memset(&overlapped, 0, sizeof(overlapped));
    const int lockSize = 10000;
    printf("Taking lock\n");
    if (!LockFileEx(hFile, LOCKFILE_EXCLUSIVE_LOCK, 0, lockSize, 0, &overlapped))
    {
        DWORD err = GetLastError();
        printf("Error %i\n", err);
    }
    else
    {
        printf("Acquired lock\n");
        getchar();
        UnlockFileEx(hFile, 0, lockSize, 0, &overlapped);
        printf("Released lock\n");
    }
    return 0;
}
arx
  • 16,686
  • 2
  • 44
  • 61
  • I have made a "toy example" already using LockFileEx and it seems to not block, even though I don't LOCKFILE_FAIL_IMMEDIATELY. Which is strange... if it worked I'd mark your answer as correct. – petersaints Feb 08 '12 at 01:21
  • @petersaints: Are you using asynchronous I/O? – arx Feb 08 '12 at 01:22
  • No. Do I have to? It seems a bit confusing from what I read on the documentation. And it seems to be different from what I'd expect from async I/O (from the description). – petersaints Feb 08 '12 at 01:34
  • No. Asynchronous I/O will cause it to not block - you get notified later when the lock is free. But if you're not using asynchronous I/O it should work fine. I'll try it. – arx Feb 08 '12 at 01:44
  • It's working. The only difference I spot from what I've done is the use of overlapped. What exactly does it mean? Now I'll test if this works, for example, when a file is being copied to a directory. – petersaints Feb 08 '12 at 10:13
  • On the case of a file being copied it gets a File Lock error number 6. But well... at least I can detect that kind of error. – petersaints Feb 08 '12 at 10:23
  • @petersaints: You don't normally need overlapped for non-asynchronous I/O, but for LockFileEx it defines the start of the range of bytes you want to lock. Error 6 is "invalid file handle", it's not an error with the locking as such. It probably means CreateFile failed; use GetLastError to determine why. – arx Feb 08 '12 at 12:16
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/7458/discussion-between-petersaints-and-arx) – petersaints Feb 08 '12 at 13:12