d-_-b
d-_-b

Reputation: 23151

Obtain exclusive read/write lock on a file for atomic updates

I want to have a PHP file that is used as a counter. It will a) echo the current value of a txt file, and b) increment that file using an exclusive lock so no other scripts can read or write to it while it's being used.

User A will write and increment this number, while User B requests to read the file. Is it possible that User A can lock this file so no one can read or write to it until User A's write is finished?

I've used flock in the past, but I'm not sure how to get the file to wait until it is available, rather than quitting if it's already been locked

My goal is:

LOCK counter.txt; write to counter.txt;

while at the same time

Read counter.txt; realize it's locked so wait until that lock is finished.

//

$fp = fopen("counter.txt", 'w+');
if(flock($fp, LOCK_EX)) {
    fwrite($fp, $counter + 1);
    flock($fp, LOCK_UN);
} else {
    // try again??
}

fclose($fp);

Upvotes: 4

Views: 2461

Answers (1)

Kamil Dziedzic
Kamil Dziedzic

Reputation: 5012

From documentation: By default, this function will block until the requested lock is acquired

So simply use flock in your reader (LOCK_SH) and writer (LOCK_EX), and it is going to work. However I highly discourage use of blocking flock without timeout as this means that if something goes wrong then your program is going to hang forever. To avoid this use non-blocking request like this (again, it is in doc):

/* Activate the LOCK_NB option on an LOCK_EX operation */
if(!flock($fp, LOCK_EX | LOCK_NB)) {
    echo 'Unable to obtain lock';
}

And wrap it in a for loop, with sleep and break after failed n-tries (or total wait time).

EDIT: You can also look for some examples of usage here. This class is a part of ninja-mutex library in which you may be interested too.

Upvotes: 4

Related Questions