Frage

Stellen Sie sich den folgenden Perl-Code vor (hier im Pseudocode):

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

In diesem Fall würde ich die Sperre nicht aufheben, da das Perl-Skript in Zeile 2 endet.Wird die Sperre in diesem Fall jemals vom Betriebssystem freigegeben?Sieht es "Hey, das Skript, das die Sperre erworben hat, ist abgestürzt" und gibt die Sperre auf?Gibt es die Sperre sofort frei?Wird für jedes Skript auch eine Perl-Instanz ausgeführt, damit klar ist, welches Skript abgestürzt / gestoppt wurde, ohne die Sperre aufzuheben?

War es hilfreich?

Lösung

Wird die Sperre in diesem Fall jemals vom Betriebssystem freigegeben?
Sieht es "Hey, das Skript, das die Sperre erworben hat, ist abgestürzt" und gibt die Sperre auf?
Gibt es die Sperre sofort frei?

All diese Fragen sind systemabhängig.Perl 5 implementiert keine Dateisperrfunktion, sondern bietet lediglich eine gemeinsame Schnittstelle zu flock(2), fcntl(2) verriegelung oder lockf(3) (abhängig davon, was im Betriebssystem verfügbar ist).Es kann auch einen Unterschied geben, was passiert, wenn ein Programm beendet wird, segfault oder mit einem Sigkill beendet wird.

Ein schneller Test unter Linux zeigt, dass eine Sperre unter normalen Exit-Bedingungen entfernt wird:

$ 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

Mal sehen, was passiert, wenn wir 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.

Um einen Segfault zu erhalten, benötigen wir Zugriff auf C, das ich benutze Inline um es zu bekommen:

$ 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

Und schließlich passiert Folgendes, wenn ein Programm gesendet wird 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

Aus diesen Experimenten können wir ersehen, dass die Sperre in Linux für jeden der Fälle aufgehoben wird, mit denen Sie sich befasst haben.

Wird für jedes Skript auch eine Perl-Instanz ausgeführt, damit klar ist, welches Skript abgestürzt / gestoppt wurde, ohne die Sperre aufzuheben?

Ja, Perl 5 hat einen perl prozess pro Skript.Auch wenn Sie gabeln, bekommt das Kind seine eigene perl Prozess.Threading bietet keine separate perl Prozess.

Beachten:wenn ein übergeordneter Prozess eine Sperre erhält und diese vor dem Sperren nicht aufgibt, hat das Kind dieselbe Sperre, auch wenn der übergeordnete Prozess beendet wird.

Andere Tipps

Wenn das Programm ausgeht, veröffentlicht das Betriebssystem automatisch alle vom Programm erworbenen Schlösser und schließt alle vom Programm geöffneten Dateien.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top