想象一下下面的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行结束。在这种情况下,锁是否曾经被操作系统释放?它是否看到"嘿,获取锁的脚本崩溃了"并释放锁?它会立即释放锁吗?另外,是否有一个Perl实例为每个脚本运行,以便清楚哪个脚本崩溃/停止而不释放锁?

有帮助吗?

解决方案

在这种情况下,锁是否曾经被操作系统释放?
它是否看到"嘿,获取锁的脚本崩溃了"并释放锁?
它会立即释放锁吗?

所有这些问题都取决于系统。Perl5没有实现文件锁定功能,它只是提供了一个通用的接口来 flock(2), fcntl(2) 锁定,或 lockf(3) (取决于操作系统中可用的内容)。当程序退出,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 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.

要获得segfault,我们需要访问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实例为每个脚本运行,以便清楚哪个脚本崩溃/停止而不释放锁?

是的,Perl5有一个 perl 处理每个脚本。即使你分叉,孩子也会得到自己的 perl 过程。线程不提供单独的 perl 过程。

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

其他提示

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

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top