Rimessi insieme i vecchi pezzi.
[gapil.git] / signal.tex
index 966e32a1aa0759a2d1d6b15210171c3f2680d5e7..b60bd7aeeb0c5cab3b9e110fb6a2ce81cbd56da2 100644 (file)
@@ -84,6 +84,20 @@ attivo.
 In questo caso è possibile una situazione in cui i segnali possono essere
 perduti. Si consideri il seguente segmento di codice, in cui la prima
 operazione del manipolatore è quella di reinstallare se stesso: 
 In questo caso è possibile una situazione in cui i segnali possono essere
 perduti. Si consideri il seguente segmento di codice, in cui la prima
 operazione del manipolatore è quella di reinstallare se stesso: 
+\footnotesize
+\begin{lstlisting}[labelstep=0,frame=,indent=1cm]{}
+    int sig_handler();            /* handler function */
+    ...
+    signal(SIGINT, sig_handler);  /* establish handler */
+    ...
+
+int sig_handler() 
+{
+    signal(SIGINT, sig_handler);  /* restablish handler */
+    ...                           /* process signal */
+}
+\end{lstlisting}
+\normalsize
 se un secondo segnale arriva prima che il manipolatore invocato dal primo
 abbia eseguito la reinstallazione di se stesso il segnale può essere perso o
 causare il comportamento originale assegnato al segnale (in genere la
 se un secondo segnale arriva prima che il manipolatore invocato dal primo
 abbia eseguito la reinstallazione di se stesso il segnale può essere perso o
 causare il comportamento originale assegnato al segnale (in genere la
@@ -418,7 +432,7 @@ stato dello stack e delle variabili al momento della ricezione del segnale.
 \end{table}
 
 La descrizione dettagliata del significato dei vari segnali, raggruppati per
 \end{table}
 
 La descrizione dettagliata del significato dei vari segnali, raggruppati per
-tipologia, verrà affrontate nel seguito.
+tipologia, verrà affrontate nei paragrafi successivi.
 
 
 \subsection{Segnali di errore di programma}
 
 
 \subsection{Segnali di errore di programma}
@@ -1621,44 +1635,62 @@ Ma anche questa implementazione comporta dei problemi; in questo caso infatti
 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
 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.  Lo stesso tipo di
+problemi si presenterebbero se si volesse usare \func{alarm} per stabilire un
+timeout su una qualunque system call bloccante.
 
 
-Lo stesso tipo di problema si presenterebbe se si volesse usare \func{alarm}
-per stabilire un timeout su una sistem call bloccante. Un secondo esempio è
-quello in cui si usa il segnale per notificare una quelche forma di evento; in
-genere quello che si fa in questo caso è settare nel manipolatore un opportuno
-flag da controllare nel corpo principale del programma (con un codice del tipo
-di quello riportato in 
+Un secondo esempio è quello in cui si usa il segnale per notificare una
+quelche forma di evento; in genere quello che si fa in questo caso è settare
+nel manipolatore un opportuno flag da controllare nel corpo principale del
+programma (con un codice del tipo di quello riportato in
+\secref{fig:sig_event_wrong}.
 
 \begin{figure}[!htb]
   \footnotesize \centering
   \begin{minipage}[c]{15cm}
     \begin{lstlisting}{}
 sig_atomic_t flag;
 
 \begin{figure}[!htb]
   \footnotesize \centering
   \begin{minipage}[c]{15cm}
     \begin{lstlisting}{}
 sig_atomic_t flag;
-unsigned int control(unsigned int seconds)
+int main()
 {
 {
-    da fare
+    flag = 0;
+    ...
+    if (flag) {         /* test if signal occurred */
+        flag = 0;       /* reset flag */ 
+        do_response();  /* do things */
+    } else {
+        do_other();     /* do other things */
+    }
+    ...
 }
 void alarm_hand(int sig) 
 {
     /* set the flag 
     flag = 1;
 }
 void alarm_hand(int sig) 
 {
     /* set the flag 
     flag = 1;
+    return;
 }      
     \end{lstlisting}
   \end{minipage} 
   \normalsize 
 }      
     \end{lstlisting}
   \end{minipage} 
   \normalsize 
-  \caption{Un esempio non funzionante di restituzione di un evento da parte di
-    un segnale.} 
+  \caption{Un esempio non funzionante del codice per il controllo di un
+    evento generato da un segnale.}
   \label{fig:sig_event_wrong}
 \end{figure}
 
   \label{fig:sig_event_wrong}
 \end{figure}
 
+La logica è quella di far settare al manipolatore (\texttt{\small 14-19}) una
+variabile globale preventivamente inizializzata nel programma principale, il
+quale potrà determinare, osservandone il contenuto, l'occorrenza o meno del
+segnale, e prendere le relative azioni conseguenti (\texttt{\small 6-11}).
 
 
+Questo è il tipico esempio di caso, già citato in \secref{sec:proc_race_cond},
+in cui si genera una race condition; se infatti il segnale arriva
+immediatamente dopo l'esecuzione del controllo (\texttt{\small 6}) ma prima
+della cancellazione del flag (\texttt{\small 7}), la sua occorrenza sarà
+perduta.
 
 
-È per questo motivo che occorrono funzioni più sofisticate della semplice
-\func{signal} che permettano di gestire i segnali in maniera più completa.
-
-
-
+Questi esempi ci mostrano che per una gestione effettiva dei segnali occorrono
+funzioni più sofisticate della semplice interfaccia dei primi sistemi Unix,
+che permettano di gestire tutti i possibili aspetti con cui un processo deve
+reagire alla ricezione di un segnale.
 
 
 
 
 
 
@@ -1873,14 +1905,20 @@ permettono si bloccare temporaneamente (o di eliminare completamente, settando
 \macro{SIG\_IGN} come azione) la consegna dei segnali ad un processo. Questo è
 fatto specificando la cosiddetta \textit{signal mask} del
 processo\footnote{nel caso di Linux essa è mantenuta dal campo \var{blocked}
 \macro{SIG\_IGN} come azione) la consegna dei segnali ad un processo. Questo è
 fatto specificando la cosiddetta \textit{signal mask} del
 processo\footnote{nel caso di Linux essa è mantenuta dal campo \var{blocked}
-  della relativa \var{task\_struct}} che viene espressa come il signal set dei
-segnali la cui consegna è bloccata. Abbiamo accennato in
+  della \var{task\_struct} del processo.} che viene espressa come il signal
+set dei segnali la cui consegna è bloccata. Abbiamo accennato in
 \secref{sec:proc_fork} che la \textit{signal mask} viene ereditata dal padre
 alla creazione di un processo figlio, e abbiamo visto al paragrafo precedente
 che essa può essere specificata, durante l'esecuzione di un manipolatore,
 attraverso l'uso dal campo \var{sa\_mask} di \var{sigaction}.
 
 \secref{sec:proc_fork} che la \textit{signal mask} viene ereditata dal padre
 alla creazione di un processo figlio, e abbiamo visto al paragrafo precedente
 che essa può essere specificata, durante l'esecuzione di un manipolatore,
 attraverso l'uso dal campo \var{sa\_mask} di \var{sigaction}.
 
-Uno dei problemi evidenziatisi con l'esempio di 
+Uno dei problemi evidenziatisi con l'esempio di \secref{fig:sig_event_wrong} è
+che in molti casi è necessario proteggere delle sezioni di codice (nel caso la
+sezione fra il test e la eventuale cancellazione del flag che testimoniava
+l'avvenuta occorrenza del segnale) in modo da essere sicuri che essi siano
+eseguiti senza interruzioni. Le operazioni più semplici, come l'assegnazione o
+il controllo di una variabile di norma (per essere sicuri si può usare il tipo
+\type{sig\_atomic\_t}).