linux – 发生错误时发布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

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

解决方法:

In that case, is the lock ever released by the operating system?
Does it see “hey, the script that acquired the lock crashed” and release the lock?
Does it release the lock immediately?

所有这些问题都取决于系统. 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

让我们看看我们死后会发生什么:

$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中针对您关注的每个案例发布了锁定.

Also, is there one perl instance running for each script, so that it’s clear which script crashed/stopped without releasing the lock?

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

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

上一篇:PHP下载会阻止其他请求


下一篇:python – Lock和RLock有什么区别