2012-09-29 9 views
8

Immaginate il seguente codice Perl (qui in pseudo codice):Rilascio di gregge in caso di errori?

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 vorrei rilasciare il blocco, come lo script Perl finisce in linea 2. In tal caso, è il blocco mai rilasciato dal sistema operativo? Si vede "hey, lo script che ha acquisito il blocco si è bloccato" e rilasciare il blocco? Rilascia immediatamente il lucchetto? Inoltre, esiste un'istanza Perl in esecuzione per ogni script, in modo che sia chiaro quale script si è arrestato/arrestato senza rilasciare il blocco?

risposta

24

In tal caso, la serratura è stata rilasciata dal sistema operativo?
Si vede "hey, lo script che ha acquisito il blocco si è bloccato" e rilascia il blocco?
Rilascia immediatamente il blocco?

Tutte queste domande dipendono dal sistema. Perl 5 non implementa una funzione di blocco dei file, ma fornisce un'interfaccia comune al blocco flock(2), fcntl(2) o lockf(3) (a seconda di ciò che è disponibile nel sistema operativo). Potrebbe anche esserci una differenza tra ciò che accade quando un programma esce, segfaults o viene ucciso con un sigkill.

Un test rapido sotto Linux dimostra che un blocco è stato 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 accesso 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 ognuno dei casi riguardavano.

Inoltre, c'è un caso perl esecuzione per ogni script, in modo che sia chiaro che lo script è schiantato/fermato senza rilasciare la serratura?

Sì, Perl 5 ha un perl processo per ogni script. Anche se si forchetta, il bambino ottiene il proprio processo perl. Threading non fornisce un processo separato perl.

Nota: se un processo genitore ottiene un blocco e non lo arresta prima del blocco, il bambino avrà lo stesso blocco anche se il genitore esce.

+3

risposta dettagliata impressionante, grazie mille! anche grazie a soulSurfer2010 per la risposta breve, ma comunque corretta e informativa! –

1

Quando il programma termina, il sistema operativo rilascia automaticamente tutti i blocchi acquisiti dal programma e chiude tutti i file aperti dal programma.

+0

Questa risposta non è utile senza alcuna prova che tu abbia ragione. –

Problemi correlati