Pergunta

Imagine o seguinte código Perl (aqui em pseudocódigo):

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

Nesse caso eu não liberaria o bloqueio, pois o script Perl termina na linha 2.Nesse caso, o bloqueio já foi liberado pelo sistema operacional?Ele vê "ei, o script que adquiriu o bloqueio travou" e libera o bloqueio?Ele libera a trava imediatamente?Além disso, há uma instância Perl em execução para cada script, para que fique claro qual script travou/parou sem liberar o bloqueio?

Foi útil?

Solução

Nesse caso, o bloqueio já foi liberado pelo sistema operacional?
Ele vê "ei, o script que adquiriu o bloqueio travou" e libera o bloqueio?
Ele libera a trava imediatamente?

Todas essas questões dependem do sistema.Perl 5 não implementa uma função de bloqueio de arquivo, apenas fornece uma interface comum para flock(2), fcntl(2) bloqueio, ou lockf(3) (dependendo do que está disponível no sistema operacional).Também pode haver uma diferença entre o que acontece quando um programa é encerrado, falha em segmentos ou é eliminado com um sigkill.

Um teste rápido no Linux mostra que um bloqueio é removido em condições normais de saída:

$ 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

Vamos ver o que acontece quando 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.

Para obter um segfault, precisaremos de acesso a C, estou usando Inline para obtê-la:

$ 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

E finalmente, aqui está o que acontece quando um programa é enviado 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

A partir desses experimentos, podemos ver que o bloqueio é liberado no Linux para cada um dos casos com os quais você estava preocupado.

Além disso, existe uma instância Perl em execução para cada script, para que fique claro qual script travou/parou sem liberar o bloqueio?

Sim, Perl 5 tem um perl processo por script.Mesmo se você desembolsar, a criança ganha o seu próprio perl processo.Threading não fornece um separado perl processo.

Observação:se um processo pai obtiver um bloqueio e não desistir dele antes do bloqueio, o filho terá o mesmo bloqueio mesmo se o pai sair.

Outras dicas

Ao encerrar o programa, o SO libera automaticamente todos os bloqueios adquiridos pelo programa e fecha todos os arquivos abertos pelo programa.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top