Block function in php for one user only
Hi I have a php function, it takes about 20 minutes (or more) to run and complete.
but if someone else runs it during the last run ... The function is aborted with unwanted result.
these are structures:
function myfunc()
{
foreach()
{
//do somthing
}
}
I think I can do it via a file like this:
I created a text file ... if the content of this text was "1", the function is blocked. 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 should be true ... but doesn't work! after the first run, the contents of the lock.txt file remains at 1. (does not change to 0 after the end)
I think maybe the function breaks during the process due to the long time! because I handle all the break state in the function. can you call me how to deal with this problem? how can I be sure that lock.txt will be "0" after the terminate or interrupt function?
source to share
Well, there is already a function to implement lock. Flock () is called
<?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);
?>
with the LOCK_SH flag you can lock it
source to share
Fortunately, the best way in my experience is like 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 stale
if (is_link(LOCK_FILE) && !is_dir(LOCK_FILE))
{
unlink(LOCK_FILE);
# try to lock again
return tryLock();
}
return false;
}
?>
Taken from comments
http://php.net/manual/en/function.getmypid.php
This blocks the process, so if the process fails, you can remove the lock
source to share
Thanks to my friends for the answer.
I couldn't run your code ... maybe because I can't set them up correctly ...
but I solved the problem of inserting the insile code function 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 someone else ...
source to share
I use these functions (for example, I call them my_lock and my_unlock):
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);
}
source to share