14

次の 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 行目で終了するため、ロックを解除しません。その場合、オペレーティング システムによってロックが解除されることはありますか? 「ロックを取得したスクリプトがクラッシュしました」と表示され、ロックが解除されますか? ロックをすぐに解除しますか?また、ロックを解除せずにどのスクリプトがクラッシュ/停止したかが明確になるように、スクリプトごとに 1 つの Perl インスタンスが実行されていますか?

4

2 に答える 2

39

その場合、オペレーティング システムによってロックが解除されることはありますか?
「ロックを取得したスクリプトがクラッシュしました」と表示され、ロックが解除されますか?
ロックをすぐに解除しますか?

これらの質問はすべてシステムに依存します。Perl 5 はファイル ロック機能を実装していません。単に、、ロック、または (OS で利用可能なものに応じて) への共通インターフェイスを提供するflock(2)だけfcntl(2)ですlockf(3)。プログラムが終了したとき、segfault が発生したとき、または 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 でロックが解除されていることがわかります。

また、ロックを解除せずにどのスクリプトがクラッシュ/停止したかが明確になるように、スクリプトごとに 1 つの perl インスタンスが実行されていますか?

はい、Perl 5 にはperlスクリプトごとに 1 つのプロセスがあります。フォークしても、子は独自のperlプロセスを取得します。perlスレッド化は、別個のプロセスを提供しません。

注: 親プロセスがロックを取得し、ロックする前にそれを放棄しない場合、親プロセスが終了しても、子プロセスは同じロックを保持します。

于 2012-09-29T12:31:01.837 に答える
4

プログラムが終了すると、OS はプログラムによって取得されたすべてのロックを自動的に解放し、プログラムによって開かれたすべてのファイルを閉じます。

于 2012-09-29T08:49:47.340 に答える