Fork (e la sorella Exec) è una funzione utilizzata sui sistemi basati su Posix per la creazione di un nuovo processo.

Uno dei problemi più grandi di C, è l’assenza di un decente sistema di eccezioni o gestione degli errori. Questo ha col tempo portato alla creazione di un sacco di bug generalmente associati al fatto che, per pigrizia, gli sviluppatori rimandano la gestione degli errori al momento in cui sono riusciti ad avere una “happy path” funzionante.

Quando si richiama una funzione bisognerebbe infatti controllare sempre il valore di ritorno in caso di errore e regaire in maniera adeguata.

La funzione fork è l’unica a ritornare due volte: ritorna il valore 0 al processo figlio e ritorna al padre il pid del figlio appena spawnato.

fork, come ad esempio malloc, è una funzione che spesso è considerata infallibile: la verità è che entrambe possono fallire e bisogna tenere in considerazione questa eventualità.

Se non gestiamo il risultato di errore della fork, finiremo per trattare il valore -1 come pid del figlio. Questo potrebbe portare a spiacevoli conseguenze, sopratutto quando più tardi avremo bisogno di mandare un segnale a questo pid per un qualunque motivo.

Ad esempio, se vogliamo terminare il processo potremmo mandare un segnale SIGKILL. Quindi potremmo voler fare kill(pid, 9).

E cosa succede quando pid equivale a -1?

If pid equals -1, then sig is sent to every process for which the calling process has permission to send signals, except for process 1 (init), …

Pagina di manuale di kill(2)

Quindi eseguire una kill del pid -1, equivale a uccidere ogni processo per cui abbiamo i permessi. Se ad esempio siamo root, questo equivale a mandare una sigkill a tutto il sistema (a parte init col pid 1).

Conclusione

Scrivere in C un codice che funzioni è relativamente facile, scrivere codice corretto è tutta un’altra storia. Visto che scrivere codice sbagliato o insicuro è facile, solitamente lo si dovrebbe scrivere seguendo tecniche di programmazione difensiva e come minimo dovremmo sempre controllare il valore di ritorno delle chiamate a funzioni. O usare un linguaggio di programmazione più safe.