#include #include #include #include #include #include #include "tool.h" /* D‚termine si un process existe. Retourne != 0 si oui. */ export int process_isalive (int proc) { return kill(proc,0)!=-1; } static int lock_putpid (const char *fname) { int fid = open(fname,O_EXCL|O_CREAT|O_WRONLY|O_RDONLY,0444); if (fid != -1){ char buf[20]; int len = sprintf (buf,"%d\n",getpid()); write (fid,buf,len); close (fid); } return fid; } /* Cr‚ation d'un fichier lock avec le pid du process cr‚ateur. Retourne -1 si ne peut pas fichier (existe d‚j…). */ export int lock_set ( const char *fname, // Nom du fichier lock. int retry) // Nom d'essai … faire avant d'abandonner. // 0 = essai une fois. // -1 = attend tant que le lock ne r‚ussit pas. { int ret = -1; while (1){ if (lock_putpid (fname)!=-1){ ret = 0; break; }else{ /* #Sp‚cification: tool / format d'un fichier lock Un fichier lock contient le pid en ascii du processus qui la cr‚‚. Lorsqu'un deuxiŠme process tente de cr‚er le lock et qu'il echoue, il tente de lire le contenu du lock et d‚termine si le process existe toujours. Si ce n'est pas le cas, il ‚crit son propre pid dedans et retourne. */ int ok = 0; { FILE *fin = fopen(fname,"r"); if (fin != NULL){ int pid; if (fscanf(fin,"%d",&pid)==1){ ok = !process_isalive(pid); }else{ /* Pas de process valide dans ce fichier */ ok = 1; } fclose (fin); } } if (ok == 1){ file_unlink (fname); if (lock_putpid (fname)!=-1){ ret = 0; break; } }else if (retry == 0){ break; }else{ if (retry > 0) retry--; sleep (4); } } } return ret; } /* Elimine un fichier lock. Retourne -1 si ne peut pas d‚truire. */ export int lock_unset (const char *fname) { return file_unlink (fname); } #ifdef TEST int main(int, char *[]) { int pid1 = process_fork(); if (pid1 == 0){ lock_set ("toto.1.lck",0); sleep(20); lock_unset ("toto.1.lck"); }else{ int pid2 = process_fork(); if (pid2 ==0){ lock_set ("toto.2.lck",0); _exit(0); }else{ process_waitpid(pid2); printf ("lock pid2 -> %d\n",lock_set("toto.2.lck",0)); printf ("lock pid1 -> %d\n",lock_set("toto.1.lck",1)); lock_unset ("toto.1.lck"); lock_unset ("toto.2.lck"); } } return 0; } #endif