• `usleep(((rand() % 401) + 100) * 1000); // tra 100 e 500 millisecondi

FORK, PIPE, DUP

  • ogni processo deve chiudere sempre i file descriptor non usati
  • processo scrittore chiude fd[0]
  • processo lettore chiude fd[1]
  • pipe() va controllato se ritorna -1 (error)
  • fork() va controllare se ritorna -1 (error)
  • la read su pipe termina solo quando tutti gli scrittori sono chiusi
  • se anche un solo fd[1] resta aperto la read può bloccarsi
  • dopo dup2() bisogna sempre chiudere il descrittore originale
  • fork() va sempre controllato: <0 errore, =0 figlio, >0 padre
  • ogni processo figlio deve essere sempre terminato con exit o return corretto
  • ogni processo figlio deve essere sempre aspettato dal padre con wait o waitpid(pid, <NULL o &statuspid>,0)
  • exec sostituisce il processo e non ritorna se ha successo
  • dopo exec si deve gestire solo il caso di errore
  • le pipe non si riutilizzano dopo la chiusura, vanno ricreate
  • se una read si blocca, il problema è quasi sempre un fd di scrittura ancora aperto

SIGNAL

  • per disabilitare segnali signal(<segnale>, SIG_IGN)
  • segnale Cltr+C : SIGINT
  • registrare handler : signal(<segnale>, <handler>)
  • segnali user defined : SIGUSR1, SIGUSR2
  • per fare attesa passiva : pause();
  • QUANDO MANDIAMO IN UN CICLO DEI SEGNALI AD UN PROCESSO, E DOPO TERMINIAMO SUBITO, DOBBIAMO ATTENDERE ALMENO UN PO PER FAR ARRIVARE I SEGNALI E FARLI GESTIRE

FILE

  • L’overlap corretto è sempre len_word - 1 (RICERCA PAROLA)
  • Per fare overlap con file descriptor usare sempre lseek(fd, -overlap, SEEK_CUR) e non SEEK_SET
  • quando scrivi una stringa su un file/pipe devi usare come dimensione strlen(buffer) oppure se hai già letto la stringa con n = read usa n (# byte letti) :luc_alert_triangle:
  • controlli errori su read e write
    • read <= 0 error
    • write == -1 error

STAT

  • stat ha bisogno di snprintf(filepath, sizeof(filepath), "%s/%s", dirname, filename)
  • controllare se stat(...) < 0

DIRECTORY

  • aprire directory : dirp = opendir(<nomedir>) dove DIR* dirp
    • controllare se != NULL
  • leggere una entry : dirent = readdir(dirp) dove struct dirent* dirent e DIR* dirp
    • controllare se != NULL
  • chiudere directory : closedir(dirp)

PTHREADS

  1. controllo di pthread_create che ritorna 0 (successo) oppure in caso di errore
  2. per passare un parametro :luc_alert_triangle: :
    • pthread_create(x, x, x , (void *)(long) <integer> )
    • per leggerlo : int tid = (int) (long) i
    • oppure : pthread_create(x, x, x , (void *) &<variabile> ) (LA VARIABILE DEVE RIMANERE VIVA)
    • per leggerlo : int x = *((int*)arg)
      • parametri : pthread_create(x, x, x, (void*) &mystruct)
    • per leggerli : mystruct_t *s = (mystruct_t*) arg e s->parm1 etc etc
  3. leggere ritorno thread :luc_alert_triangle: :
    • allocare risultato : ris* = malloc e inizializzarlo con risultato
    • return (void*) ris
    • per leggerlo dal processo padre :
      • void* ret
      • pthread_join(thread, &ret)
      • int val = *((int*)ret)
    • rilasciare ris : free(ret)
  4. ogni lock deve avere sempre il suo unlock (anche in caso di errori)
  5. non tenere un mutex bloccato troppo a lungo
  6. quando tutti i thread leggono NON c’è bisogno di mutex
  7. srand va inizializzato una sola volta nel processo, non in più thread :luc_alert_triangle: