Risistemati gli esempi per sleep e fissata una referenza
[gapil.git] / signal.tex
index 1fb456973a7ce88513f71146e5eaa9be970cb2ef..be01dc4ec8304c0b992281a202f3c5aa056a6633 100644 (file)
@@ -1443,42 +1443,41 @@ void Hand_CHLD(int sig)
 \end{figure}
 
 Il codice del manipolatore è di lettura immediata; come buona norma di
-programmazione (si ricordi quanto accennato \secref{sec:sys_errno}) si comincia
-(\texttt{\small 13}) con il salvare lo stato corrente di \var{errno}, in modo
-da poterla ripristinare prima del ritorno del manipolatore (\texttt{\small
-  23}). In questo modo si preserva il valore della variabile visto dal corso
-di esecuzione principale del processo, che sarebbe altrimenti sarebbe
-sovrascritto dal valore restituito nella successiva chiamata di \func{wait}.
+programmazione (si ricordi quanto accennato \secref{sec:sys_errno}) si
+comincia (\texttt{\small 12-13}) con il salvare lo stato corrente di
+\var{errno}, in modo da poterlo ripristinare prima del ritorno del
+manipolatore (\texttt{\small 22-23}). In questo modo si preserva il valore
+della variabile visto dal corso di esecuzione principale del processo, che
+sarebbe altrimenti sarebbe sovrascritto dal valore restituito nella successiva
+chiamata di \func{wait}.
 
 Il compito principale del manipolatore è quello di ricevere lo stato di
 terminazione del processo, cosa che viene eseguita nel ciclo in
-(\texttt{\small 15--21}).  Il ciclo è necessario a causa di una caratteristica
+(\texttt{\small 15-21}).  Il ciclo è necessario a causa di una caratteristica
 fondamentale della gestione dei segnali: abbiamo già accennato come fra la
 generazione di un segnale e l'esecuzione del manipolatore possa passare un
-certo lasso di tempo; dato che questo lasso di tempo può dipendere da parecchi
-fattori esterni, niente ci assicura che il manipolatore venga eseguito prima
-della generazione di altri segnali dello stesso tipo. In questo caso
-normalmente i segnali vengono ``fusi'' insieme ed al processo ne viene
-recapitato soltanto uno.
+certo lasso di tempo e niente ci assicura che il manipolatore venga eseguito
+prima della generazione di ulteriori segnali dello stesso tipo. In questo caso
+normalmente i segnali segnali successivi vengono ``fusi'' col primo ed al
+processo ne viene recapitato soltanto uno.
 
-Questo può essere un caso comune proprio con \macro{SIGCHLD}, quando molti
-processi figli terminano in rapida successione. Esso comunque si presenta
-tutte le volte che un segnale viene bloccato: per quanti siano i segnali
-emessi durante il periodo di blocco, una volta che esso viene rimosso ne sarà
-recapitato uno solo.
+Questo può essere un caso comune proprio con \macro{SIGCHLD}, qualora capiti
+che molti processi figli terminino in rapida successione. Esso inoltre si
+presenta tutte le volte che un segnale viene bloccato: per quanti siano i
+segnali emessi durante il periodo di blocco, una volta che quest'ultimo sarà
+rimosso sarà recapitato un solo segnale.
 
-Nel caso della terminazione dei processi figli, se si chiamasse \func{waitpid}
-una sola volta, essa leggerebbe un solo stato di teminazione, anche se i
-processi terminati sono più di uno, con relativa possibilità di avere zombie
-che non vengono eliminati. 
+Allora nel caso della terminazione dei processi figli, se si chiamasse
+\func{waitpid} una sola volta, essa leggerebbe lo stato di teminazione per un
+solo processo, anche se i processi terminati sono più di uno, e gli altri
+resterebbero in stato di zombie per un tempo indefinito.
 
-Per questo si esegue un ciclo (\texttt{\small 15--21}) in cui ripete la
-lettura fintanto che essa non restituisce un valore nullo (si veda
-\secref{sec:proc_wait} per la sintassi della funzione) segno che non resta
-nessun processo di cui si debba ancora ricevere lo stato di terminazione. Si
-noti come la funzione viene invocata con il parametro \macro{WNOHANG} che
-permette di evitare che essa si blocchi quando tutti gli stati di terminazione
-sono stati ricevuti.
+Per questo occorre ripetere la chiamata di \func{waitpid} fino a che essa non
+ritorni un valore nullo, segno che non resta nessun processo di cui si debba
+ancora ricevere lo stato di terminazione (si veda \secref{sec:proc_wait} per
+la sintassi della funzione). Si noti anche come la funzione venga invocata con
+il parametro \macro{WNOHANG} che permette di evitare il suo blocco quando
+tutti gli stati di terminazione sono stati ricevuti.
 
 
 
@@ -1503,15 +1502,20 @@ casistica ordinaria.
 Come accennato in \secref{sec:sig_pause_sleep} è possibile implementare
 \func{sleep} a partire da dall'uso di \func{pause} e \func{alarm}. A prima
 vista questo può sembrare di implementazione immediata; ad esempio una
-semplice versione di \func{sleep} potrebbe essere la seguente quella
-illustrata in \ref{fig:sig_sleep_wrong}.
+semplice versione di \func{sleep} potrebbe essere quella illustrata in
+\figref{fig:sig_sleep_wrong}.
 
-In questo caso si salva il precedente manipolatore in (\texttt{\small 15--21})
-per poi chiamare in sequenza \func{alarm} per specificare l'attesa e
-\func{pause} per fermare il programma. Al ritorno di pause, causato dal
-ritorno del manipolatore (\texttt{\small 15--21}) si ripristina il
-manipolatore (\texttt{\small 15--21}) restituendo l'eventuale tempo rimanente
-(\texttt{\small 15--21}).
+
+Dato che è nostra intenzione utilizzare \macro{SIGALARM} il primo passo della
+nostra implementazione di sarà quello di installare il relativo manipolatore
+salvando il precedente (\texttt{\small 4-7}).  Si effettuerà poi una chiamata
+ad \func{alarm} per specificare il tempo d'attesa per l'invio del segnale a
+cui segue la chiamata a \func{pause} per fermare il programma (\texttt{\small
+  8-9}) fino alla sua ricezione.  Al ritorno di \func{pause}, causato dal
+ritorno del manipolatore (\texttt{\small 15-23}), si ripristina il
+manipolatore originario (\texttt{\small 10-11}) restituendo l'eventuale tempo
+rimanente (\texttt{\small 12-13}) che potrà essere diverso da zero qualora
+l'interruzione di \func{pause} venisse causata da un altro segnale.
 
 \begin{figure}[!htb]
   \footnotesize \centering
@@ -1543,23 +1547,25 @@ void alarm_hand(int sig) {
     \end{lstlisting}
   \end{minipage} 
   \normalsize 
-  \caption{Una implementazione pericolosamente sbagliata di \func{sleep}.} 
+  \caption{Una implementazione pericolosa di \func{sleep}.} 
   \label{fig:sig_sleep_wrong}
 \end{figure}
 
-Ma questo codice, a parte il non gestire il caso in cui si è avuta una
-precedente chiamata a \func{alarm}, presenta una pericolosa race condition.
-Infatti se il processo viene interrotto fra la chiamata di \func{alarm} e
-\func{pause} può capitare (ad esempio se il sistema è molto carico) che
-quest'ultima possa essere eseguita dopo l'arrivo di \macro{SIGALRM}. In questo
-caso ci si troverebbe di fronte ad un deadlock, in cui \func{pause} non
-verrebbe mai più interrotta (se non in caso di un altro segnale).
+Questo codice però, a parte il non gestire il caso in cui si è avuta una
+precedente chiamata a \func{alarm} (che si è tralasciato per brevità),
+presenta una pericolosa race condition.  Infatti se il processo viene
+interrotto fra la chiamata di \func{alarm} e \func{pause} può capitare (ad
+esempio se il sistema è molto carico) che il tempo di attesa scada prima
+dell'esecuzione quest'ultima, cosicchè essa sarebbe eseguita dopo l'arrivo di
+\macro{SIGALRM}. In questo caso ci si troverebbe di fronte ad un deadlock, in
+quanto \func{pause} non verrebbe mai più interrotta (se non in caso di un
+altro segnale).
 
 Questo problema può essere risolto (ed è la modalità con cui veniva fatto in
 SVr2) usando la funzione \func{longjump} (vedi \secref{sec:proc_longjmp}) per
-uscire dal manipolatore; in questo modo, usando lo stato di uscita di
-quest'ultima, si può evitare la chiamata a \func{pause}, con un codice come
-quello riportato in \ref{fig:sig_sleep_incomplete}.
+uscire dal manipolatore; in questo modo, con una condizione sullo stato di
+uscita di quest'ultima, si può evitare la chiamata a \func{pause}, usando un
+codice del tipo di quello riportato in \figref{fig:sig_sleep_incomplete}.
 
 \begin{figure}[!htb]
   \footnotesize \centering
@@ -1598,17 +1604,20 @@ void alarm_hand(int sig) {
   \label{fig:sig_sleep_incomplete}
 \end{figure}
 
-In questo caso il manipolatore non ritorna come in \ref{fig:sig_sleep_wrong},
-ma usa \func{longjmp} (\texttt{\small 15--21}) per rientrare nel corpo
-principale del programma; dato che in questo caso il valore di uscita di
-\func{setjmp} è 1 grazie alla condizione in (\texttt{\small 15--21}) si evita
-in ogni caso che \func{pause} sia chiamata a vuoto.
+In questo caso il manipolatore (\texttt{\small 18-26}) non ritorna come in
+\figref{fig:sig_sleep_wrong}, ma usa \func{longjmp} (\texttt{\small 24}) per
+rientrare nel corpo principale del programma; dato che in questo caso il
+valore di uscita di \func{setjmp} è 1 grazie alla condizione in
+(\texttt{\small 9-12}) si evita comunque che \func{pause} sia chiamata a
+vuoto.
 
 Ma anche questa implementazione comporta dei problemi; in questo caso infatti
-non viene gestita correttamente l'interazione con altri segnali; se infatti il
-segnale di allarme interrompe un altro manipolatore, in questo caso
+non viene gestita correttamente l'interazione con gli altri segnali; se
+infatti il segnale di allarme interrompe un altro manipolatore, in questo caso
 l'esecuzione non riprenderà nel manipolatore in questione, ma nel ciclo
-principale, interrompendone inopportunamente l'esecuzione.
+principale, interrompendone inopportunamente l'esecuzione.  È per questo
+motivo che occorrono funzioni più sofisticate della semplice \func{signal} che
+permettano di gestire in maniera più completa