Skip to content

Wishlist: unlink lock file if created by lock() #1

Closed
perlancar opened this Issue Dec 21, 2012 · 13 comments

3 participants

@perlancar

This is a feature of File::Flock. Would be nice if File::Flock::Tiny has it too.

@trinitum
Owner

I thought about it before actually, but decided to not complicate things. On the other hand, yes, it would be nice. I will look at it. Thanks for suggestion.

@trinitum
Owner

So I thought about it, and looked onto File::Flock, and came to conclusion that it is not possible to do with flock. It would be possible with sysopen and O_EXCL, but it has nothing to do with flock(2). The problem is that I have first to open the file and then flock it, and there's a possibility that between these two operations another process will release the lock and unlink the file.

@trinitum trinitum closed this Dec 24, 2012
@perlancar

Sorry for replying, I hope this does not reopen the issue unwantedly (haven't familiarized with how GH issues work).

I'm not sure about your statement "not possible to do with flock". Of course opening and/or creating the file is done via some variant of open/sysopen, not with flock directly.

You just need to check whether the file exists (step 1, save result in $exists), before opening/creating the file (step 2). Then during unlocking, only unlink the file if $exists is false.

Race condition between step 1 and step 2 might cause double unlinking. But that's not something fatal/dangerous.

@trinitum
Owner

Imagine three processes A, B, and C start all (almost) at the same time.

  • A creates and locks /test.lock
  • B opens existing /test.lock
  • A unlocks and unlinks /test.lock
  • B locks unlinked file
  • C creates and locks /test.lock

And we have B and C running critical section both at the same time. So B had also to check after locking that the file still exists and that it is the same file it has locked, maybe stat both files and compare inode numbers, but not all filesystems support inode numbers.

@perlancar

You're right, of course. Somehow I completely forgot that we are dealing with a lock file and not the data file itself (if we're locking the data file itself, it does not matter if another process links and creates a new data file, as we're still locking the handle to the correct data).

But I still like the convenience of autounlinking of lock file. Maybe I'll write my own module :)

Thanks for this conversation.

@trinitum
Owner

I think it would be easier to do without flock, just sysopen with O_EXCL to lock and unlink to unlock. The only problem is that if process was killed it may leave lock file.

@perlancar

To clean a stale lock file, how about: open if exists, flock with LOCK_EX, and unlink if we succeed (meaning no one else is holding the lock on the file). After that we proceed with the normal flock LOCK_EX (sysopen O_EXCL can't be used here because we need to hold the lock to prevent it being considered stale).

@trinitum
Owner

Same problem A and B, existing /test.lock

  • A opens /test.lock and flocks it
  • B opens /test.lock
  • A unlinks /test.lock and unlocks it. Then creates a new /test.lock with O_EXCL
  • B locks unlinked file and unlinks /test.lock that A created, Then creates a new /test.lock with O_EXCL

A and B running critical section both at the same time ;)

@trinitum
Owner

Sorry, I misunderstood, your comment. After rereading I don't really understand your proposal. Can you show it as code?

@perlancar

Here's my stab at it:

https://github.com/sharyanto/perl-SHARYANTO-Utils/blob/master/lib/SHARYANTO/File/Flock.pm

There's no stale lock cleaning. A simple unlink=>1 option is provided to unlink the lock file at the end of object's life. The key is, as you said, rechecking after flock() whether the lock file is still the same file.

@trinitum
Owner

I would suggest to put @st1 computation after open, and pass filehandle to stat:

my @st1 = stat($self->{_fh});
@perlancar

Good idea. Thanks, applied.

@andersk
andersk commented Jun 1, 2013

@sharyanto’s code has some additional bugs that I’ve documented at perlancar/perl-SHARYANTO-Utils#1.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.