在那种情况下,操作系统是否释放过该锁?
它是否看到“嘿,获取锁的脚本崩溃了”并释放了锁?
它会立即释放锁吗?
所有这些问题都取决于系统。Perl
5并没有实现文件锁定功能,它只是提供了
flock(2),
fcntl(2)锁定或
lockf(3)(取决于OS中可用的功能)的通用接口。程序退出,segfaults或被sigkill杀死时所发生的情况之间也可能存在差异。
在Linux下进行的快速测试表明,在正常退出条件下,锁已被删除:
$ perl -le 'open my $fh, ">", "f" or die $!; print flock($fh, 6) ? "got lock" : "was already locked", "n"'got lock$ perl -le 'open my $fh, ">", "f" or die $!; print flock($fh, 6) ? "got lock" : "was already locked", "n"'got lock
让我们看看当我们
die:
$ perl -le 'open my $fh, ">", "f" or die $!; print flock($fh, 6) ? "got lock" : "was already locked", "n"; die "died"'got lockdied at -e line 1.$ perl -le 'open my $fh, ">", "f" or die $!; print flock($fh, 6) ? "got lock" : "was already locked", "n"; die "died"'got lockdied at -e line 1.
要获得段错误,我们需要访问C,我正在使用
Inline它:
$ cat segfault.pl#!/usr/bin/perluse strict;use warnings;use Inline "C";open my $fh, ">", "f" or die $!;print flock($fh, 6) ? "got lock" : "was already locked", "n";crash();__DATA____C__void crash() { int* ptr = NULL; *ptr = 5;}$ perl segfault.plgot lockSegmentation fault$ perl segfault.plgot lockSegmentation fault最后,这是发送程序时发生的情况
SIGKILL:
$ cat fork.pl#!/usr/bin/perluse strict;use warnings;$SIG{CHLD} = "IGNORE"; #auto-reap childrendie "could not fork: $!" unless defined(my $pid = fork);unless ($pid) { #child open my $fh, ">", "f" or die $!; print flock($fh, 6) ? "got lock" : "was already locked", "n"; sleep(100); exit;}kill 9, $pid;die "could not fork: $!" unless defined($pid = fork);unless ($pid) { #child open my $fh, ">", "f" or die $!; print flock($fh, 6) ? "got lock" : "was already locked", "n"; exit;}$ perl fork.plgot lockgot lock从这些实验中,我们可以看到,您所关心的每种情况都在Linux中释放了该锁。
另外,是否为每个脚本运行一个perl实例,以便清楚地知道哪个脚本崩溃/停止而没有释放锁?
是的,Perl 5
perl每个脚本只有一个进程。即使您分叉,孩子也会有自己的
perl过程。线程不提供单独的
perl过程。
注意:如果父进程获得了锁并且在锁之前没有放弃,那么即使父进程退出,子进程也将拥有相同的锁。



