2

What I want to achieve is this:

  1. if some other process is holding the lock, quit
  2. otherwise acquire the lock for writing

The Ruby code I am trying to modify is.

File.open(filename, "wb") { |inf|
  if inf.flock(File::LOCK_EX|File::LOCK_NB) == 0
    ...
  end
}

The codes I can find are usually using "rb". If I change to "wb", there is a problem: because if some other process is working on the file (which I cannot know until attempting the lock), the file will be wiped out by File.open(..., "wb").

Is there a way? Thanks.

New Info

I think one way is to use "File::RDWR|File::CREAT", so that you can open file first and it won't wipe out its content, then try the lock. Not sure if there is other way, but "wb" probably will not work. I guess this is an awkwardness of Ruby: you have to open file first before acquiring the lock. I think these two steps should be made atomic.

JasonMArcher
  • 14,195
  • 22
  • 56
  • 52
user180574
  • 5,681
  • 13
  • 53
  • 94

1 Answers1

2

Create a lock file and lock that instead. If your filename is say "path/to/file.txt" then create a lock on "path/to/file.txt.lock". Once you've acquired your lock on the lock file, edit the real file as normal.

Steve Folly
  • 8,327
  • 9
  • 52
  • 63
Philip Hallstrom
  • 19,673
  • 2
  • 42
  • 46
  • Phillip, I am thinking about how to do that without running into timing issues. For example, one would not just confirm `"path/to/file.txt.lock"` does not exist before creating it in write mode, as the file could be created between the execution of the two operations. One possibility is to use a database to get the lock, as they are built to do that. Is there a safe, easy way to do this with just `IO` methods? – Cary Swoveland Dec 05 '14 at 00:29
  • Open the lock file for writing. Then try to acquire a lock. Doesn't matter how many processes open the lock file. Just that only one of them can acquire an exclusive lock. – Philip Hallstrom Dec 05 '14 at 04:27