在发生错误的情况下释放羊群?

想象下面的Perl代码(这里是伪代码):

successfully acquired flock for FILEHANDLER # line 1 some error or maybe simply a call to exit() # line 2 close FILEHANDLER (which also releases the lock) # line 3 

在这种情况下,我不会释放锁,因为Perl脚本在第2行结束。在这种情况下,操作系统是否释放了锁? 它看到“嘿,获得锁的脚本崩溃”,并释放锁? 它是否立即释放locking? 另外,是否有一个Perl实例为每个脚本运行,这样就可以清楚地知道哪个脚本在没有释放锁的情况下崩溃/停止了?

在这种情况下,操作系统是否解锁?
它看到“嘿,获得锁的脚本崩溃”,并释放锁?
它是否立即释放锁定?

所有这些问题都依赖于系统。 Perl 5没有实现文件锁定功能,只是提供了flock(2)fcntl(2)锁定或lockf(3) (取决于OS中可用的)的通用接口。 程序退出,段错误或用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 lock died 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 lock died at -e line 1. 

要获得段错误,我们需要访问C,我正在使用Inline来获取它:

 $ cat segfault.pl #!/usr/bin/perl use 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.pl got lock Segmentation fault $ perl segfault.pl got lock Segmentation fault 

最后,这是发送程序SIGKILL时发生的情况:

 $ cat fork.pl #!/usr/bin/perl use strict; use warnings; $SIG{CHLD} = "IGNORE"; #auto-reap children die "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.pl got lock got lock 

从这些实验中,我们可以看到,在Linux中针对您所关心的每个案例都发布了锁。

另外,每个脚本是否有一个perl实例正在运行,以便清楚哪个脚本在没有释放锁的情况下崩溃/停止?

是的,Perl 5每个脚本都有一个perl进程。 即使你分叉,孩子也会得到自己的perl进程。 线程不提供一个单独的perl进程。

注意:如果一个父进程获得一个锁,并且在锁定之前没有放弃它,那么即使该父进程退出,子进程也将拥有相同的锁。

当程序退出时,操作系统会自动释放程序获取的所有锁,并关闭程序打开的所有文件。