Skip to content
Advertisement

Delphi 10.3 Linux exclusive file access

How can I lock a file in Linux with a filestream?

Creating a filestream like in the example below works perfectly in Windows, the file is locked and cannot be deleted or written to in other sessions until the stream is freed. Under Linux I can delete the file or write to it in an other session without any problems.

var f: TFileStream;
...
f := TFileStream.Create(TPath.Combine(FTemp, lowerCase(Name)), fmOpenReadWrite + fmCreate);
...

NEW FINDINGS 1.1.2020

Linux does not automatically apply an atomic lock on files like Windows does. So I tried applying a lock after creating the file:

function flock(handle, operation: integer): integer; cdecl; external libc name _PU + 'flock';

const
  LOCK_EX = 2;

...

f := TFileStream.Create(fn, fmCreate, fmShareExclusive);
flock(f.handle, LOCK_EX);

There is a small race condition as creating the file and locking it is not one single step but for my application this is not a problem. When looking at the created lock file on the linux console the difference is obvious:

Wihout flock():

mint@minti:/tmp/itclock$ lsof wirsing
COMMAND    PID USER   FD   TYPE DEVICE SIZE/OFF    NODE NAME
_TestLibB 5417 mint   14u   REG    8,1        8 2755101 wirsing

With flock():

mint@minti:/tmp/itclock$ lsof wirsing
COMMAND    PID USER   FD   TYPE DEVICE SIZE/OFF    NODE NAME
_TestLibB 6365 mint   14uW  REG    8,1        0 2755117 wirsing

The difference is the big W that indicates an exclusive lock.

Unfortunately this does not solve the problem as creating a second filestream just creates a second exclusive lock in the same process and deleting the file from an other process is still possible. If there was a way to read the extended attributes of lsof <file> from within delphi …

An other finding (new year, new ideas)

As I run my tests as unit tests and create several objects in the same process to test the locks this might be the cause as Windows does not allow accessing the locked file even from within the same process. This seems to be different in Linux. I need something that behaves like in Windows – it should be no difference if it is locked in a different process or a thread of the same process. Perhaps Linux offers a totally different way to accomplish such a locking mechanism?

And still: Any help is very appreciated!

Advertisement

Answer

Finally I found a usable solution that at least serves my requirements:

In Windows I continue using the simple approach with fmShareExclusive. In Linux I apply a FileLock as described above in the question. For checking the exclusive lock I run a command line via popen and capture the result prior to deleting the lock file and then creating/locking it.

lsof -Fl <my flock file name>

This outputs three lines if a Lock exists:

p7590
f14
lW

I look for lW in the result that indicates an exclusive lock on the file and I can react on that as required.

This solution still works if a process crashes as then the file lock will be gone too.

I am aware of the fact that this is not a very elegant solution but it seems to be rubust and reliable enough.

Comments and suggestions are very welcome!

User contributions licensed under: CC BY-SA
6 People found this is helpful
Advertisement