锁定 Perl 子例程
Lock Perl sub routine
我写了一个CGI脚本。它的子程序之一不能同时执行。即同一用户(或黑客)运行 完全相同的两个实例)。我怎样才能避免这种情况?
我使用锁定文件进行了以下变通,但我不确定它是否安全:
unless (-e $filelock) {
sub_that_should_be_locked();
}
sub sub_that_should_be_locked {
open FILE, ">", $filelock;
flock DATAFILE, LOCK_EX;
close FILE;
...Code that cannot be executed at the same time...
...Code that cannot be executed at the same time...
unlink $filelock;
}
不应该有 waiting/queue,并发进程不应该调用 sub_that_should_be_locked
您要同步的线程不应创建和删除锁文件。
你应该确保文件存在 before 线程被启动,然后子例程应该使用 lexical 文件句柄来打开input.
的锁定文件
像这样
open my $lock_fh, '<', $lockfile or die $!;
flock $lock_fh, LOCK_EX;
作为它的第一个动作。这将挂起线程,直到它在队列中被连接,之后文件将在子例程结束时隐式关闭(并因此释放其锁),因为 $lock_fh
超出范围
不安全。您的代码中存在竞争条件,因为 -e
和 open
之间存在时间。永远不要将 -e
与锁定文件一起使用。
不检查文件是否存在,而是检查文件是否已经被锁定。这是使用非阻塞 flock
完成的。如果文件尚未锁定,它将 return 成功,如果文件已被锁定,它将 return 错误 EWOULDBLOCK
。
请注意,要使其正常工作,您必须在 sub_that_should_be_locked
执行的整个过程中一直持有锁。 (您的代码一获取就释放。)
use Fcntl qw( LOCK_EX LOCK_NB );
sub get_lock_nb {
my ($qfn) = @_;
open(my $fh, '+>:raw', $qfn)
or die("Unable to open file \"$qfn\": $!\n");
if (!flock($fh, LOCK_EX | LOCK_NB)) {
return undef if $!{EWOULDBLOCK};
die("Unable to lock file \"$qfn\": $!\n");
}
return $fh;
}
sub sub_that_should_be_locked {
... Mutually exclusive code ...
}
{
my $lock = get_lock_nb("file.lock");
sub_that_should_be_locked() if $lock;
}
我写了一个CGI脚本。它的子程序之一不能同时执行。即同一用户(或黑客)运行 完全相同的两个实例)。我怎样才能避免这种情况?
我使用锁定文件进行了以下变通,但我不确定它是否安全:
unless (-e $filelock) {
sub_that_should_be_locked();
}
sub sub_that_should_be_locked {
open FILE, ">", $filelock;
flock DATAFILE, LOCK_EX;
close FILE;
...Code that cannot be executed at the same time...
...Code that cannot be executed at the same time...
unlink $filelock;
}
不应该有 waiting/queue,并发进程不应该调用 sub_that_should_be_locked
您要同步的线程不应创建和删除锁文件。
你应该确保文件存在 before 线程被启动,然后子例程应该使用 lexical 文件句柄来打开input.
的锁定文件像这样
open my $lock_fh, '<', $lockfile or die $!;
flock $lock_fh, LOCK_EX;
作为它的第一个动作。这将挂起线程,直到它在队列中被连接,之后文件将在子例程结束时隐式关闭(并因此释放其锁),因为 $lock_fh
超出范围
不安全。您的代码中存在竞争条件,因为 -e
和 open
之间存在时间。永远不要将 -e
与锁定文件一起使用。
不检查文件是否存在,而是检查文件是否已经被锁定。这是使用非阻塞 flock
完成的。如果文件尚未锁定,它将 return 成功,如果文件已被锁定,它将 return 错误 EWOULDBLOCK
。
请注意,要使其正常工作,您必须在 sub_that_should_be_locked
执行的整个过程中一直持有锁。 (您的代码一获取就释放。)
use Fcntl qw( LOCK_EX LOCK_NB );
sub get_lock_nb {
my ($qfn) = @_;
open(my $fh, '+>:raw', $qfn)
or die("Unable to open file \"$qfn\": $!\n");
if (!flock($fh, LOCK_EX | LOCK_NB)) {
return undef if $!{EWOULDBLOCK};
die("Unable to lock file \"$qfn\": $!\n");
}
return $fh;
}
sub sub_that_should_be_locked {
... Mutually exclusive code ...
}
{
my $lock = get_lock_nb("file.lock");
sub_that_should_be_locked() if $lock;
}