Newsgroup: it.comp.os.linux.development
Titolo: Eterno problema /var/run/pid e crash programma

Salve NG,
la cosa credo sia gia' stata trattata ma io non trovo soluzione:
faccio un programma che deve partire una sola volta. Metto il pid
in /var/run, e poi il programma crasha. Se lo riavvio ovviamente si rifiuta
di partire perche' vede il pid anche se il programma e' morto. Soluzione ?
Ci saranno pure delle librerie (standard se posibile) che si arrangiano a
creare il pidfile, a segarlo e a verificare che ci sia davvero il
programma.
Pensavo anche di fare un 'ps' ma mi pare una toppa.
Grazie, Nicola.
-- 
chi va pian va san e va lontan

 rifiuta di partire perche' vede il pid anche se il programma e' morto.
]zac[
L'oggetto del post è totalmente sballato.
Il programma non deve solo controllare che esista il file di run/lock, ma
che contenga anche un pid che è ancora esistente nella lista dei processi.
Una finezza sarebbe di controllare anche che il nome del programma associato
a quel pid corrisponda al nome del programma voluto e non ad un altro (cosa
possibile se si riavvia il sistema dopo il crash del programma e poi si
rilancia il programma).

 Soluzione ?
Apri il file in scrittura/lettura       
        fd = open( path, O_CREAT|O_RDWR );      
e usa flock in modalità non bloccante per lockarlo 
 
        rc = flock( fd, LOCK_EX|LOCK_NB ).
Se flock ha successo (rc==0), scrivi il pid nel file, chiama fdsync, e 
continua senza chiudere il file. (Eventualmente puoi usare atexit per 
far sparire il file quando il programma esce in modo normale, ma non è 
necessario.)
Se flock non ha successo (rc==-1), il programma è già in esecuzione.
Max

 e poi si rilancia il programma).
Ok, grazie Max mi ha chiarito le idee.


 
Ho trovato anche sta' roba che mi pare carina, mi piace la struct:
struct flock fl;
int fd;
fl.l_type   = F_WRLCK;  /* F_RDLCK, F_WRLCK, F_UNLCK    */
fl.l_whence = SEEK_SET; /* SEEK_SET, SEEK_CUR, SEEK_END */
fl.l_start  = 0;        /* Offset from l_whence         */
fl.l_len    = 0;        /* length, 0 = to EOF           */
fl.l_pid    = getpid(); /* our PID                      */
fd = open("filename", O_WRONLY);
fcntl(fd, F_SETLKW, &fl);  /* F_GETLK, F_SETLK, F_SETLKW */
// Rimozione del lock a fine programma
fl.l_type   = F_UNLCK;  /* tell it to unlock the region */
fcntl(fd, F_SETLK, &fl); /* set the region to unlocked */
Ma non vedo la scrittura del pid nel file. Piu' che altro mi servirebbe per
killare il programma dagli script di avvio. Lo fa da sola la fcntl o
bisogna fare:
char buf[10];  /* qual'e' il numero piu' alto di un pid? */
sprintf(buf, "%d", fl.l_pid);
write(&fl, buf, sizeof(buf));
Che dici ?


 Ho trovato anche sta' roba che mi pare carina, mi piace la struct:
Complicazione inutile. 'flock' è sufficiente. 'fcntl' ti permette di fare 
cose più raffinate, che in questo caso non ti servono.
Per maggiori info: man fsync, man flock, man fcntl.
Max

Max M. wrote:

Ultima domanda:
se ho ben capito lasciando il file aperto e 'lockandolo' quando il programma
viene chiuso (o crasha) ci pensa linux a 'slockare' il file?


 Uh? mi sono spiegato cosi' male?
]zac[
Era riferito l'eterno problema.
Se magari è utile qualche precisazione/pignoleria.
Quel sistema di lock run/pid pubblico permette a qualsiasi programma,
script, umano, ecc. di gestire il lock, in modo semplice, abbastanza
affidabile e richiedendo solo strumenti presenti in ogni linux/unix.
Quel sistema di lock run/pid è quasi sempre usato dagli script di lancio dei
vari programmi che hanno l'esigenza di una sola istanza (per esempio gli
script che lanciano i vari servizi all'avvio (e non)).
P.S. Non è costi molto farsi una funzione e poi riciclarla.
P.P.S.S. Ogni programma è libero di usare altri metodi, anche se,
personalmente, ritengo migliore adattarsi al metodo run/pid.