为什么我的互斥类有时不会删除互斥锁文件?

时间:2014-09-30 23:28:14

标签: php wordpress mutex

我创建了一个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.");
    }                                                                                           
  }
}

Mutex本身的使用方式如下:

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();

知道为什么会这样吗?我认为类的析构函数会确保它被删除,即使代码要中途停止?

1 个答案:

答案 0 :(得分:0)

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

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

  1. 共享锁可以同时由多个进程保存(因此名称)。
  2. 同一进程获取的独占锁不会阻止共享锁。
  3. 我不确定您使用isLocked()的内容,但由于上述2条规则,无论目的如何,您都可能会误报。我可以告诉你的是:

    • 不要混合锁类型。
    • 请小心锁定检查,因为 自行获取锁定。
    • 在此特定情况下,仅使用LOCK_EX

    还有:https://bugs.php.net/bug.php?id=53769