Rilascio di gregge in caso di errori?
Domanda
Immagina il seguente codice perl (qui in codice pseudo):
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 questo caso non rilascerò il blocco, poiché lo script perl termina in linea 2. In tal caso, è il blocco mai rilasciato dal sistema operativo?Vedi "Ehi, lo script che ha acquisito il blocco si è schiantato" e rilascia il blocco?Rilascia immediatamente il blocco?Inoltre, esiste un'istanza perl in esecuzione per ogni script, in modo che sia chiaro quale script si è schiantato / arresto senza rilasciare il blocco?
Soluzione
.In tal caso, è il lucchetto mai rilasciato dal sistema operativo?
Vedi "Ehi, lo script che ha acquisito il blocco si è schiantato" e rilascia il blocco?
Rilascia immediatamente il blocco?Tutte queste domande sono dipendenti dal sistema. Perl 5 non implementa una funzione di blocco del file, fornisce solo un'interfaccia comune a
flock(2)
, bloccaggiofcntl(2)
olockf(3)
(a seconda di ciò che è disponibile nel sistema operativo). Potrebbe anche esserci una differenza tra ciò che accade quando un programma uscita, segfault o viene ucciso con un sigkill.Un test rapido sotto Linux mostra che un blocco viene rimosso in condizioni di uscita normali:
.$ 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
Vediamo cosa succede 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.
Per ottenere un Segfault, avremo bisogno di accedere a c, sto usando
Inline
per ottenerlo:.$ 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 infine, ecco cosa succede quando un programma viene inviato
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
Da questi esperimenti, possiamo vedere che il blocco viene rilasciato in Linux per ciascuno dei casi con cui sei interessato.
.Inoltre, esiste un'istanza perl in esecuzione per ogni script, in modo che sia chiaro quale script si è schiantato / interrotto senza rilasciare il blocco?
Sì, Perl 5 ha un processo
perl
per script. Anche se si è forcella, il bambino ottiene il proprio processoperl
. La filettatura non fornisce un processo di generazione diperl
separato.Nota: se un processo genitore ottiene un blocco e non si arrende prima di bloccare, allora il bambino avrà lo stesso blocco anche se il genitore esce.
Altri suggerimenti
Quando il programma esce, il sistema operativo rilascia automaticamente tutte le serrature acquisite dal programma e chiude tutti i file aperti dal programma.