En ese caso, ¿la cerradura se ha liberado alguna vez por el sistema operativo?
¿Ve "hey, el guión que adquirió el bloqueo se colgó" y suelta el bloqueo?
¿Libera la cerradura de inmediato?
Todas estas preguntas dependen del sistema. Perl 5 no implementa una función de bloqueo de archivos, solo proporciona una interfaz común para flock(2)
, fcntl(2)
de bloqueo, o lockf(3)
(dependiendo de lo que está disponible en el sistema operativo). También puede haber una diferencia entre lo que sucede cuando un programa sale, segfaults o se mata con un sigkill.
Una prueba rápida en Linux muestra que un bloqueo se elimina bajo condiciones de salida normales:
$ 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 a ver lo que sucede cuando 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 obtener una violación de segmento, necesitaremos acceso a C, estoy usando Inline
para obtenerlo:
$ 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
Y, por último, aquí es lo que sucede cuando un programa se envía 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 de estos experimentos, se puede ver que el bloqueo se libera en Linux para cada uno de los casos que se referían a.
Además, ¿hay una instancia de Perl ejecutándose para cada script, para que quede claro qué script se bloqueó/detuvo sin soltar el bloqueo?
Sí, Perl 5 tiene una perl
proceso por guión. Incluso si te bifurcas, el niño obtiene su propio proceso perl
. Enhebrar no proporciona un proceso perl
por separado.
Nota: si un proceso padre consigue un bloqueo y no renunciar a ella antes de bloquear, entonces el niño tendrá la misma cerradura incluso si las salidas de los padres.
impresionante respuesta detallada, ¡muchas gracias! ¡también gracias a soulSurfer2010 por la respuesta breve, pero aún correcta e informativa! –