2012-11-23 44 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

>這發生在我身上 是否有可能重現 –