如果出现错误,会发布鸡群?

ste*_*wpf 13 linux perl locking flock

想象一下下面的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
Run Code Online (Sandbox Code Playgroud)

在这种情况下,我不会释放锁,因为Perl脚本在第2行结束.在这种情况下,操作系统是否发布了锁?是否看到"嘿,获得锁定的脚本崩溃了"并释放锁定?它会立即释放锁吗?此外,是否有一个Perl实例为每个脚本运行,以便明确哪个脚本在没有释放锁的情况下崩溃/停止?

Cha*_*ens 35

在这种情况下,操作系统是否已发布锁定?
是否看到"嘿,获得锁定的脚本崩溃了"并释放锁定?
它会立即释放锁吗?

所有这些问题都取决于系统.Perl 5没有实现文件锁定功能,它只提供一个公共接口flock(2),fcntl(2)锁定或lockf(3)(取决于操作系统中可用的内容).当程序退出,段错误或被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
Run Code Online (Sandbox Code Playgroud)

让我们看看当我们发生时会发生什么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.
Run Code Online (Sandbox Code Playgroud)

要获得段错误,我们需要访问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
Run Code Online (Sandbox Code Playgroud)

最后,这是发送程序时会发生的事情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
Run Code Online (Sandbox Code Playgroud)

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

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

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

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

  • 很棒的详细解答,非常感谢!还要感谢soulSurfer2010的简短,但仍然是正确和翔实的回复! (6认同)

sno*_*kin 6

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

  • 如果没有任何证据表明您是对的,这个答案就没有用。 (2认同)