lock function in php only for one user

2.6k Views Asked by At

Hi I have a php function it takes about 20 min (or more) to run and finish.

but if somebody else run it during last run...The function break with unwanted result.

this is the structures:

function myfunc()
{
   foreach()
   {
      //do somthing
   }
}

I think I can do it via a file like this:

I created a text file ... if content of that text was '1',the function is lock. if not the function is free.

function myfunc()
{
    $file = "lock.txt";
    $f = fopen($file, 'r');
    $line = fgets($f); 
    fclose($f);
    if($line == 0)
        file_put_contents($file, "1");
    else 
        return false;

    foreach()
    {
    }

    //after finish for each
    file_put_contents($file, "0"); // free function for other user 
}

I think logically it must be true ...but do not work! after first run, the content of lock.txt file remain 1. (not change to 0 after finish)

I think maybe the function breaks during process becuase of long times! because I handle all break state in function. can tel me how can handle this problem? how can I be sure that lock.txt will be '0' after finish or break function?

4

There are 4 best solutions below

0
On

Thanks my friends for the answer..

I couldn't run your code...maybe bcause I can not config them well...

but I solved my problem with insert function insile code like this:

$file = "lock.txt";
$f = fopen($file, 'r');
$line = fgets($f); 
fclose($f);
if($line == 0)
{
    file_put_contents($file, "1");
    myfunction();
    file_put_contents($file, "0");
}
else
{
    echo "Already running.";
}

hope help sombody else...

0
On

Well there is already a function to implement lock Called flock()

<?php

$file = fopen("test.txt","w+");

// exclusive lock
if (flock($file,LOCK_EX))
  {
  fwrite($file,"Write something");
  // release lock
  flock($file,LOCK_UN);
  }
else
  {
  echo "Error locking file!";
  }

fclose($file);
?> 

using a flag LOCK_SH you can lock it

0
On

By far the best way in my experience is similar to this

<?php

define('LOCK_FILE', "/var/run/" . basename($argv[0], ".php") . ".lock");

if (!tryLock())
    die("Already running.\n");

 # remove the lock on exit (Control+C doesn't count as 'exit'?)
register_shutdown_function('unlink', LOCK_FILE);

# The rest of your script goes here....
echo "Hello world!\n";
sleep(30);

exit(0);

 function tryLock()
{
     # If lock file exists, check if stale.  If exists and is not stale, return TRUE
     # Else, create lock file and return FALSE.

    if (@symlink("/proc/" . getmypid(), LOCK_FILE) !== FALSE) # the @ in front of 'symlink' is to suppress the NOTICE you get if the LOCK_FILE exists
        return true;

    # link already exists
    # check if it's stale
    if (is_link(LOCK_FILE) && !is_dir(LOCK_FILE))
    {
        unlink(LOCK_FILE);
        # try to lock again
        return tryLock();
    }

    return false;
}
?>

Taken from comments of

http://php.net/manual/en/function.getmypid.php

This locks to the process so if the process fails you can remove the lock

1
On

I use these functions (I call them my_lock and my_unlock for example):

function my_lock($name) {
    $lockFile = 'myfolder/' . $name . '.lck';
    $lock = fopen($lockFile, 'w');
    if (!$lock) {
        return false;
    }
    if (flock($lock, LOCK_EX)) {
        return $lock;
    } else {
        fclose($lock);
        return false;
    }
}

function my_unlock($lock) {
    if ($lock !== false) {
        flock($lock, LOCK_UN);
        fclose($lock);
    }
}

example of use:

    $lock = my_lock('hello_world');
    if ($lock === false) {
      throw new Exception('Lock error');
    }
    try {
      //... your locked code here ...
    } finally {
      my_unlock($lock);
    }