2014-09-30 102 views
0

我有一个WordPress插件,我只是将订单导出到第三方系统。为了防止插件同时运行多次,我使用下面的互斥体代码,但有时互斥体文件不会删除阻止我的插件运行,直到我手动删除文件。为什么我的互斥体类有时不会删除互斥体文件?

<?php 

class System_Mutex 
{       
    var $lockName = ""; 
    var $fileName = null; 
    var $file = null; 

    public function __construct($lockName) { 
    $this->lockName = preg_replace('/[^a-z0-9]/', '', $lockName); 
    $this->getFileName();       
    } 

    public function __destruct() { 
    $this->releaseLock(); 
    } 

    public function isLocked() { 
    return ! flock($this->file, LOCK_SH | LOCK_NB); 
    } 

    public function getLock() {                                                               
    return flock($this->file, LOCK_EX | LOCK_NB);  
    } 

    public function releaseLock() { 
    if (! is_resource($this->file)) return true;   
    $success = flock($this->file, LOCK_UN); 
    fclose($this->file); 
    return $success; 
    } 

    public function getFileName() { 
    $this->fileName = dirname(__FILE__) . "/../Locks/" . $this->lockName . ".lock"; 

    if (! $this->file = fopen($this->fileName, "c")) { 
     throw new Exception("Cannot create temporary lock file."); 
    }                       
    } 
} 

互斥本身使用这样的:

try { 
    $mutex_id = "ef_stock_sync";                
    $mutex = new System_Mutex($mutex_id); 
    //mutex is locked- exit process 
    if ($mutex->isLocked() || ! $mutex->getLock()) { 
    // 
    return; 
    }   
} catch (Exception $e) { 
    // 
    return; 
} 
$this->_syncStock(); 
$mutex->releaseLock(); 

任何想法,为什么会是这样吗?我认为即使代码中途停止,类的析构函数也会确保它被删除?

回答

0

太宽泛以肯定地回答,并且该块很有可能是从您的插件代码触发。但是,您的System_Mutex课程中确实存在逻辑错误。

您正在获取排除锁getLock(),但isLocked()尝试获取共享锁作为支票。您不应该这样做,原因有两个:

  1. 共享锁可能由多个进程同时持有(因此它的名称)。
  2. 共享锁不会被同一进程获取的独占锁阻止。

我不确定你在用什么isLocked(),但是由于上面的2条规则,不管目的如何,你都可能得到误报。我可以告诉你的是:

  • 不要混合锁类型。
  • 小心你的锁定检查,因为确实是自己获取锁定。
  • 在这种特殊情况下,只能使用LOCK_EX

而且也是这样的:https://bugs.php.net/bug.php?id=53769

+0

@ Narf-看到我的编辑。我已经添加了它的调用方式。那么你是否暗示我根本不需要'isLocked'函数,因为如果无法获取锁,我的'getLocked'函数将返回'FALSE'?因为从这个角度来看,无论如何,'getLocked'在这种情况下似乎是多余的? – Lock 2014-10-01 01:04:31

+0

是的,如果另一个进程有锁,'getLock()'将失败。 – Narf 2014-10-01 08:17:15