Leo Galleguillos
Leo Galleguillos

Reputation: 2720

Does flock() only apply to the current method?

Does the flock() function only work if it is used within the same method that the code is executed?

For example, in the following code, the lock is successful:

public function run()
{
    $filePointerResource = fopen('/tmp/lock.txt', 'w');
    if (flock($filePointerResource, LOCK_EX)) {
        sleep(10);
    } else {
        exit('Could not get lock!');
    }
}

However, in the following code, the lock is unsuccessful:

public function run()
{
    if ($this->lockFile()) {
        sleep(10);
    } else {
        exit('Could not get lock!');
    }
}

private function lockFile()
{
    $filePointerResource = fopen('/tmp/lock.txt', 'w');
    return flock($filePointerResource, LOCK_EX);
}

I haven't seen any documentation on this, so I am puzzled by this behavior. I am using php version 5.5.35.

Upvotes: 2

Views: 321

Answers (1)

RiggsFolly
RiggsFolly

Reputation: 94642

I think the issue with your class based attempt is that when the lockFile method finishes the $filePointerResource goes out of scope and that is probably what is releasing the lock

This works which sort of supports that theory

<?php

class test {
    public function run()
    {
        $fp = fopen('lock.txt', 'w');
        if ($this->lockFile($fp)) {
            echo 'got a lock'.PHP_EOL;
            sleep(5);
        } 
        /*
         * Not going to do anything as the attempt to lock EX will
         * block until a lock can be gained 

        else {
            exit('Could not get lock!'.PHP_EOL);
        }
        */
    }

    private function lockFile($fp)
    {
        return flock($fp, LOCK_EX);
    }
}

$t = new test();
$t->run();

So if you want to lock the file over more than one call to a class method it might be better to keep the filehandle as a class property, then it will remain in scope as long as the class is instantiated and in scope.

<?php

class test {
    private $fp;

    public function run()
    {
        $this->fp = fopen('lock.txt', 'w');
        if ($this->lockFile()) {
            echo 'got a lock'.PHP_EOL;
            sleep(5);
        } 
        /*
         * Not going to do anything as the attempt to lock EX will
         * block until a lock can be gained 

        else {
            exit('Could not get lock!'.PHP_EOL);
        }
        */
    }

    private function lockFile()
    {
        return flock($this->fp, LOCK_EX);
    }
}

$t = new test();
$t->run();

Upvotes: 4

Related Questions