2012-11-23 79 views
13

在此之后answer限制只有一个PHP脚本运行的实例:如果过程中的do_something_lengthy(),即之前的中模当进程意外死亡时,会否解锁群集文件?

<?php 

    $fp = fopen("/tmp/one.txt", "r+"); 
    if (flock($fp, LOCK_EX)) { 
    // 
    do_something_lengthy(); 
    // 
    flock($fp, LOCK_UN); 
    } else { 
    echo "Couldn't get the lock!"; 
    } 

    fclose($fp); 

?> 

我的问题是,将flock“ED此时就把one.txt存盘文件进行解锁打电话flock($fp, LOCK_UN)

+0

这应该很容易测试。开始长时间运行,杀死它,并看看会发生什么? – Brad

+0

当然可以。如果任何永久资源超过其主机进程,这将是一个安全漏洞,因为它可能被用来作为非特权用户的系统拒绝服务。 – phihag

回答

10

flock()手册页PHP使用内部,当任flock()被调用LOCK_UN或使用fclose()当描述被关闭的锁被释放。

在脚本终止时,PHP或操作系统将关闭打开的文件描述符,从而释放你可能有锁。

由于上述行为this commit(5.3)和this one(5.2)被制作为不再在PHP中进行解锁。

+0

根据'flock()'手册页'fclose()'(脚本完成时运行)不会解锁文件,因为php 5.3.2 –

+1

并不一定意味着文件在末尾没有解锁过程;我会在这里运行一些测试来看看会发生什么。 –

+0

我并不是说它没有被解锁,只是从手册中拿走了一些零件。我也做了一些测试,实际上它在解析过程结束时解锁并关闭 –

2

当脚本结束时,锁自动释放。但是,您应该手动释放它,而不是依靠自动失败发生。更好地捕捉任何异常,处理它并释放锁定。请参阅官方文档 - http://php.net/manual/en/function.flock.php

+3

+1。我遇到过有时操作系统没有释放锁的情况 –

+0

Timo - 你是否说过你能够创建文件被锁定的情况,即使没有运行的进程对文件有独占锁定?如果是这样,你能否提供一个例子。 –

4

我做了这个小脚本来测试它

header('Content-type:text/plain; charset=utf-8'); 

$dir = dirname(__FILE__); 
$file = $dir.'/testflock.lock'; 
$fh = fopen($file, 'w+'); 

$unlocked = flock($fh, LOCK_EX | LOCK_NB); 
echo 'Locked: '.$file.' ';var_dump(!$unlocked);echo PHP_EOL; 
if($unlocked){ 
    sleep(10); 
    throw new Exception(); 
} 

,对我来说它采取了OS解锁文件约2-5秒后脚本完成,如果它不抛出任何异常执行,并且在脚本由于引发异常而停止后长达2-5秒。

请记住,截至php 5.3.2 fclose($fh)将不会解锁该文件,该文件将保持锁定,除非你用php解锁它,否则你将不得不等待操作系统解锁它,这可能永远不会发生如果有一些bug(这发生在我身上)

要解锁文件:

flock($fh,LOCK_UN); 

要关闭文件句柄(将被调用时自动脚本执行完毕)

fclose($fh); 

锁定不带LOCK_NB的文件将导致脚本等待文件解锁。

+0

>这发生在我身上 是否有可能重现 –