PHP Exclusive Single Process Mutex
When running php via cron, there are certainly situations where you only want a single instance of the php file to be running at the same time. Multiple processes shouldn’t be allowed. For example, every 5 minutes, a process is launched to poll for weather updates, and publish them to Twitter. If, for some reason, this process takes more than 15m–because Twitter is very slow–I don’t want more to buildup. At a rate of 12/hr, I would exhaust the number of MySQL connection on my box in a couple hours.
So, here’s the solution I used:
<?php
class pid {
protected $filename;
protected $fp;
public $already_running = false;
function __construct() {
$this->filename = dirname(__FILE__).'/'.basename($_SERVER['PHP_SELF']) . '.pid';
$this->fp = fopen( $this->filename, 'w+ );
if ( !flock( $this->fp, LOCK_EX + LOCK_NB ) )
{
echo "FAILED lock $this->filename\n";
$this->already_running = true;
fclose($this->fp);
} else {
echo "Acquired lock $this->filename\n";
}
}
public function __destruct() {
if( !$this->already_running )
{
echo "Releasing lock $this->filename\n";
flock($this->fp, LOCK_UN);
fclose($this->fp);
}
}
}
?>
It works fine from command line, but for some reason, doesn’t work when invoked via Apache over the web. But since I’m just using it for cron jobs, this is good enough for now. If you know why FLOCK( LOCK_EX + LOCK_NB ) won’t work when invoked through Apache, let me know!! I’m running PHP 5.2.6 (cli) and Apache/2.2.9 (Unix).
| This entry was posted on Sunday, May 31st, 2009 at 2:35 pm and is tagged with cron jobs, weather updates, php class, server php, couple hours, mutex, php file, apache 2, 15m, cli, flock, twitter, nb, lt, poll, unix. You can follow any responses to this entry through the RSS 2.0 feed. You can leave a response, or trackback. |
3 Responses to “PHP Exclusive Single Process Mutex”
Leave a Reply

Could it be a permissions issue? Usually when running a php file on the command line, you are running as root, but via the web, you might be running as Apache or as nobody.
Yeah, my web runs via apache. But the lockfile is owned as apache. Interestingly, I just tried it again and it worked on the web (because another was running via cron). Hmm…
I use this for some time now
function mutex($mtx, $i) { switch($i){ case 0: @unlink($mtx); return; case 1: while(!($fp = @fopen($mtx,'x'))){ } fclose($fp); return; case 2: $fp=@fopen($mtx,'x'); if($fp){ fclose($fp); return 1; } return 0; } }