L'uso di \param{sigmask} è stato introdotto allo scopo di prevenire possibili
race condition\footnote{in Linux però, non esistendo una system call apposita,
la funzione è implementata nelle \acr{glibc} usando \func{select}, e la
- possibilità di una race condition resta.} quando si deve eseguire un test su
-una variabile assegnata da un gestore sulla base dell'occorrenza di un
-segnale per decidere se lanciare \func{select}. Fra il test e l'esecuzione è
-presente una finestra in cui potrebbe arrivare il segnale che non sarebbe
-rilevato; la race condition diventa superabile disabilitando il segnale prima
-del test e riabilitandolo poi grazie all'uso di \param{sigmask}.
+ possibilità di una race condition\index{race condition} resta.} quando si
+deve eseguire un test su una variabile assegnata da un gestore sulla base
+dell'occorrenza di un segnale per decidere se lanciare \func{select}. Fra il
+test e l'esecuzione è presente una finestra in cui potrebbe arrivare il
+segnale che non sarebbe rilevato; la race condition\index{race condition}
+diventa superabile disabilitando il segnale prima del test e riabilitandolo
+poi grazie all'uso di \param{sigmask}.
file.
In tutti questi casi il \textit{file locking} è la tecnica che permette di
-evitare le race condition, attraverso una serie di funzioni che permettono di
-bloccare l'accesso al file da parte di altri processi, così da evitare le
-sovrapposizioni, e garantire la atomicità delle operazioni di scrittura.
+evitare le race condition\index{race condition}, attraverso una serie di
+funzioni che permettono di bloccare l'accesso al file da parte di altri
+processi, così da evitare le sovrapposizioni, e garantire la atomicità delle
+operazioni di scrittura.
prima vista. Infatti anche se sembrerebbe banale generare un nome a caso e
creare il file dopo aver controllato che questo non esista, nel momento fra il
controllo e la creazione si ha giusto lo spazio per una possibile \textit{race
- condition} (si ricordi quanto visto in \secref{sec:proc_race_cond}).
+ condition}\index{race condition} (si ricordi quanto visto in
+\secref{sec:proc_race_cond}).
Le \acr{glibc} provvedono varie funzioni per generare nomi di file temporanei,
di cui si abbia certezza di unicità (al momento della generazione); la prima
...
nread = getline(&ptr, &n, file);
\end{lstlisting}
-e per evitare memory leak occorre ricordarsi di liberare \var{ptr} con
-una \func{free}.
+e per evitare memory leak\index{memory leak} occorre ricordarsi di liberare
+\var{ptr} con una \func{free}.
Il valore di ritorno della funzione indica il numero di caratteri letti
dallo stream (quindi compreso il newline, ma non lo zero di
proposito dei \textit{value result argument}) l'indirizzo della stringa
allocata automaticamente dalle funzioni. Occorre inoltre ricordarsi di
invocare \func{free} per liberare detto puntatore quando la stringa non serve
-più, onde evitare memory leak.
+più, onde evitare memory leak\index{memory leak}.
Infine una ulteriore estensione GNU definisce le due funzioni \func{dprintf} e
\func{vdprintf}, che prendono un file descriptor al posto dello stream. Altre
\secref{sec:file_open}) che prevede\footnote{questo è quanto dettato dallo
standard POSIX.1, ciò non toglie che in alcune implementazioni questa
tecnica possa non funzionare; in particolare per Linux, nel caso di NFS, si
- è comunque soggetti alla possibilità di una race condition.} che essa
-ritorni un errore quando usata con i flag di \const{O\_CREAT} e
-\const{O\_EXCL}. In tal modo la creazione di un \textsl{file di lock} può
-essere eseguita atomicamente, il processo che crea il file con successo si può
-considerare come titolare del lock (e della risorsa ad esso associata) mentre
-il rilascio si può eseguire con una chiamata ad \func{unlink}.
+ è comunque soggetti alla possibilità di una race
+ condition\index{race condition}.} che essa ritorni un errore quando usata
+con i flag di \const{O\_CREAT} e \const{O\_EXCL}. In tal modo la creazione di
+un \textsl{file di lock} può essere eseguita atomicamente, il processo che
+crea il file con successo si può considerare come titolare del lock (e della
+risorsa ad esso associata) mentre il rilascio si può eseguire con una chiamata
+ad \func{unlink}.
Un esempio dell'uso di questa funzione è mostrato dalle funzioni
\func{LockFile} ed \func{UnlockFile} riportate in \figref{fig:ipc_file_lock}
Il problema più comune e più difficile da risolvere che si incontra con le
routine di allocazione è quando non viene opportunamente liberata la memoria
-non più utilizzata, quello che in inglese viene chiamato \textit{memory-leak},
-cioè una \textsl{perdita di memoria}.
+non più utilizzata, quello che in inglese viene chiamato \textit{memory
+ leak}\index{memory leak}, cioè una \textsl{perdita di memoria}.
Un caso tipico che illustra il problema è quello in cui in una subroutine si
alloca della memoria per uso locale senza liberarla prima di uscire. La
momento, in corrispondenza ad una qualunque chiamata di \func{malloc}, che può
essere in una sezione del codice che non ha alcuna relazione con la subroutine
che contiene l'errore. Per questo motivo è sempre molto difficile trovare un
-\textit{memory leak}.
+\textit{memory leak}\index{memory leak}.
In C e C++ il problema è particolarmente sentito. In C++, per mezzo della
programmazione ad oggetti, il problema dei \textit{memory leak} è notevolmente
\label{sec:proc_mem_alloca}
Una possibile alternativa all'uso di \func{malloc}, che non soffre dei
-problemi di \textit{memory leak} descritti in precedenza, è la funzione
-\funcd{alloca}, che invece di allocare la memoria nello heap usa il segmento
-di stack della funzione corrente. La sintassi è identica a quella di
-\func{malloc}, il suo prototipo è:
+problemi di \textit{memory leak}\index{memory leak} descritti in precedenza, è
+la funzione \funcd{alloca}, che invece di allocare la memoria nello heap usa
+il segmento di stack della funzione corrente. La sintassi è identica a quella
+di \func{malloc}, il suo prototipo è:
\begin{prototype}{stdlib.h}{void *alloca(size\_t size)}
Alloca \param{size} byte nello stack.
rilasciata automaticamente al ritorno della funzione.
Come è evidente questa funzione ha molti vantaggi, anzitutto permette di
-evitare alla radice i problemi di memory leak, dato che non serve più la
-deallocazione esplicita; inoltre la deallocazione automatica funziona anche
-quando si usa \func{longjmp} per uscire da una subroutine con un salto non
-locale da una funzione (vedi \secref{sec:proc_longjmp}).
+evitare alla radice i problemi di memory leak\index{memory leak}, dato che non
+serve più la deallocazione esplicita; inoltre la deallocazione automatica
+funziona anche quando si usa \func{longjmp} per uscire da una subroutine con
+un salto non locale da una funzione (vedi \secref{sec:proc_longjmp}).
Un altro vantaggio è che in Linux la funzione è molto più veloce di
\func{malloc} e non viene sprecato spazio, infatti non è necessario gestire un
\textit{deadlock}\index{deadlock}}
\label{sec:proc_race_cond}
-Si definiscono \textit{race condition} tutte quelle situazioni in cui processi
-diversi operano su una risorsa comune, ed in cui il risultato viene a
-dipendere dall'ordine in cui essi effettuano le loro operazioni. Il caso
-tipico è quello di un'operazione che viene eseguita da un processo in più
-passi, e può essere compromessa dall'intervento di un altro processo che
-accede alla stessa risorsa quando ancora non tutti i passi sono stati
-completati.
+Si definiscono \textit{race condition}\index{race condition} tutte quelle
+situazioni in cui processi diversi operano su una risorsa comune, ed in cui il
+risultato viene a dipendere dall'ordine in cui essi effettuano le loro
+operazioni. Il caso tipico è quello di un'operazione che viene eseguita da un
+processo in più passi, e può essere compromessa dall'intervento di un altro
+processo che accede alla stessa risorsa quando ancora non tutti i passi sono
+stati completati.
Dato che in un sistema multitasking ogni processo può essere interrotto in
qualunque momento per farne subentrare un'altro in esecuzione, niente può
Per questo occorre essere ben consapevoli di queste problematiche, e del fatto
che l'unico modo per evitarle è quello di riconoscerle come tali e prendere
gli adeguati provvedimenti per far sì che non si verifichino. Casi tipici di
-\textit{race condition} si hanno quando diversi processi accedono allo stesso
-file, o nell'accesso a meccanismi di intercomunicazione come la memoria
-condivisa. In questi casi, se non si dispone della possibilità di eseguire
-atomicamente le operazioni necessarie, occorre che quelle parti di codice in
-cui si compiono le operazioni sulle risorse condivise (le cosiddette
+\textit{race condition}\index{race condition} si hanno quando diversi processi
+accedono allo stesso file, o nell'accesso a meccanismi di intercomunicazione
+come la memoria condivisa. In questi casi, se non si dispone della possibilità
+di eseguire atomicamente le operazioni necessarie, occorre che quelle parti di
+codice in cui si compiono le operazioni sulle risorse condivise (le cosiddette
\textsl{sezioni critiche}\index{sezioni critiche}) del programma, siano
opportunamente protette da meccanismi di sincronizzazione (torneremo su queste
problematiche di questo tipo in \capref{cha:IPC}).
-Un caso particolare di \textit{race condition} sono poi i cosiddetti
-\textit{deadlock}\index{deadlock}, particolarmente gravi in quanto comportano
-spesso il blocco completo di un servizio, e non il fallimento di una singola
-operazione. Per definizione un \textit{deadlock}\index{deadlock} è una
-situazione in cui due o più processi non sono più in grado di proseguire
-perché ciascuno aspetta il risultato di una operazione che dovrebbe essere
-eseguita dall'altro.
+Un caso particolare di \textit{race condition}\index{race condition} sono poi
+i cosiddetti \textit{deadlock}\index{deadlock}, particolarmente gravi in
+quanto comportano spesso il blocco completo di un servizio, e non il
+fallimento di una singola operazione. Per definizione un
+\textit{deadlock}\index{deadlock} è una situazione in cui due o più processi
+non sono più in grado di proseguire perché ciascuno aspetta il risultato di
+una operazione che dovrebbe essere eseguita dall'altro.
L'esempio tipico di una situazione che può condurre ad un
sé stesso, in modo che il cambiamento di \textit{process group} sia immediato
per entrambi; una delle due chiamate sarà ridondante, ma non potendo
determinare quale dei due processi viene eseguito per primo, occorre eseguirle
-comunque entrambe per evitare di esporsi ad una race condition.
+comunque entrambe per evitare di esporsi ad una race
+condition\index{race condition}.
Si noti come nessuna delle funzioni esaminate finora permetta di spostare un
processo da una sessione ad un altra; infatti l'unico modo di far cambiare