Marcus MacWilliam
Marcus MacWilliam

Reputation: 612

Interogate which process has locked a file in Windows C ++

I have 2 applications sharing the same lock file, and I need to know when the the other application has either locked/unlocked the file. The code below was originally implemented on a Linux machine, and is being ported to Window 8, VS12.

I have ported all other code in the class successfully and am locking files with LockFile(handle, 0, 0, sizeof(int), 0) and the equivalent UnlockFile(...). However, I am having trouble with the following wait() command.

bool devices::comms::CDeviceFileLock::wait(bool locked,
                                           int  timeout)
{
   // Retrieve the current pid of the process.
   pid_t pid = getpid();

   // Determine if we are tracking time.
   bool tracking = (timeout > 0);

   // Retrieve the lock information.
   struct flock lock;
   if (fcntl(m_iLockFile, F_GETLK, &lock) != 0)
      raiseException("Failed to retrieve lock file information");

   // Loop until the state changes.
   time_t timeNow  = time(NULL);
   while ((pid == lock.l_pid) 
          &&
          (lock.l_type != (locked ? F_WRLCK : F_UNLCK)))
   {
      // Retrieve the lock information.
      if (fcntl(m_iLockFile, F_GETLK, &lock) != 0)
         raiseException("Failed to retrieve lock file information");

      // Check for timeout, if we are tracking.
      if (tracking)
      {
         time_t timeCheck = time(NULL);
         if (difftime(timeNow, timeCheck) > timeout)
            return false;
      }
   }

   // Return success.
   return true;
}

Note: m_iLockFile used to be a file descriptor from open(), it is now called m_hLockFile and is a HANDLE from CreateFile().

I cannot seem to find the Windows equivalent of the fcntl F_GETLK command. Does anyone know if I can either: a) use an fcntl equivalent to interrogate locking information, to find out which process has obtained the lock b) suggest how the above can be re-written for Windows C++.

Note: The server application using the lock file is a standalone C++ executable, however the client using the lock file is a WinRT Windows Application. So any suggested solution cannot break the sandboxing of the client.

Thanks.

Upvotes: 3

Views: 959

Answers (2)

Hans Passant
Hans Passant

Reputation: 941665

You are not going to find this in Windows, it is fundamentally unsound on a multi-tasking operating system. The value you'd get from an IsFileLocked() api function is meaningless, another process or thread could still lock the file a microsecond later.

The workaround is simple, if you need to lock then just try to acquire one. If the file is already locked then LockFile() will simply return FALSE, GetLastError() tells you why. Now it is atomic, an essential property of a lock. If you can afford to wait for the lock then use LockFileEx() without the LOCKFILE_FAIL_IMMEDIATELY option.

Upvotes: 4

doctorlove
doctorlove

Reputation: 19262

I am just googling for you, but I found this

"Various C language run-time systems use the IOCTLs for purposes unrelated to Windows Sockets. As a consequence, the ioctlsocket function and the WSAIoctl function were defined to handle socket functions that were performed by IOCTL and fcntl in the Berkeley Software Distribution."

There is also a brief discussion here - it is python based but has some clues.

Upvotes: 0

Related Questions