Rimesso pezzo perso.
[gapil.git] / signal.tex
index be01dc4ec8304c0b992281a202f3c5aa056a6633..1a2f3d08f8a43bfcfbf66b482d00f2c210d98c90 100644 (file)
@@ -84,7 +84,6 @@ 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 */
 \footnotesize
 \begin{lstlisting}[labelstep=0,frame=,indent=1cm]{}
     int sig_handler();            /* handler function */
@@ -322,7 +321,6 @@ In \tabref{tab:sig_signal_list} si 
 definiti in Linux (estratto dalle man page), comparati con quelli definiti in
 vari standard.
 
 definiti in Linux (estratto dalle man page), comparati con quelli definiti in
 vari standard.
 
-
 \begin{table}[htb]
   \footnotesize
   \centering
 \begin{table}[htb]
   \footnotesize
   \centering
@@ -898,11 +896,11 @@ con il precedente prototipo si pu
 \begin{verbatim}
     typedef void (* sighandler_t)(int) 
 \end{verbatim}
 \begin{verbatim}
     typedef void (* sighandler_t)(int) 
 \end{verbatim}
-e cioè un puntatore ad una funzione \type{void} (cioè senza valore di ritorno)
-e che prende un argomento di tipo \type{int}.\footnote{si devono usare le
+e cioè un puntatore ad una funzione \ctyp{void} (cioè senza valore di ritorno)
+e che prende un argomento di tipo \ctyp{int}.\footnote{si devono usare le
   parentesi intorno al nome della funzione per via delle precedenze degli
   operatori del C, senza di esse si sarebbe definita una funzione che ritorna
   parentesi intorno al nome della funzione per via delle precedenze degli
   operatori del C, senza di esse si sarebbe definita una funzione che ritorna
-  un puntatore a \type{void} e non un puntatore ad una funzione \type{void}.}
+  un puntatore a \ctyp{void} e non un puntatore ad una funzione \ctyp{void}.}
 La funzione \func{signal} quindi restituisce e prende come secondo argomento
 un puntatore a una funzione di questo tipo, che è appunto il manipolatore del
 segnale.
 La funzione \func{signal} quindi restituisce e prende come secondo argomento
 un puntatore a una funzione di questo tipo, che è appunto il manipolatore del
 segnale.
@@ -966,43 +964,37 @@ manipolatore potr
 \func{raise}.
 
 Se invece si vuole inviare un segnale ad un altro processo occorre utilizzare
 \func{raise}.
 
 Se invece si vuole inviare un segnale ad un altro processo occorre utilizzare
-la funzione \func{kill}; il suo prototipo è:
+la funzione \func{kill}; il cui prototipo è:
 \begin{functions}
   \headdecl{sys/types.h}
   \headdecl{signal.h}
   \funcdecl{int kill(pid\_t pid, int sig)} Invia il segnale \param{sig} al
   processo specificato con \param{pid}.
 \begin{functions}
   \headdecl{sys/types.h}
   \headdecl{signal.h}
   \funcdecl{int kill(pid\_t pid, int sig)} Invia il segnale \param{sig} al
   processo specificato con \param{pid}.
-
-  \bodydesc{La funzione restituisce zero in caso di successo e -1 per un
-    errore, nel qual caso \var{errno} assumerà i valori:
-  \begin{errlist}
-  \item[\macro{EINVAL}] Si è specificato un numero di segnale invalido.
-  \item[\macro{EPERM}] Il processo non ha il permesso di inviare il segnale
-  alla destinazione specificata.
-  \item[\macro{ESRCH}] Il \acr{pid} o il process group indicati non
-  esistono. Gli zombie (vedi \ref{sec:proc_termination}) sono considerati come
-  processi esistenti.
-  \end{errlist}}
+  
+  \bodydesc{ La funzione restituisce 0 in caso di successo e -1 in caso di
+    errore nel qual caso \var{errno} può assumere i valori:
+    \begin{errlist}
+    \item[\macro{EINVAL}] Il segnale specificato non esiste.
+    \item[\macro{ESRCH}] Il processo selezionato non esiste.
+    \item[\macro{EPERM}] Non si hanno privilegi sufficienti ad inviare il
+      segnale.
+    \end{errlist}}
 \end{functions}
 
 \end{functions}
 
-La funzione \code{raise(sig)} è sostanzialmente equivalente ad una
-\code{kill(getpid(), sig)}. Siccome \func{raise}, che è definita nello
-standard ISO C, non esiste in alcune vecchie versioni di Unix, in generale
-l'uso di \func{kill} finisce per essere più portabile.
-
-Lo standard POSIX poi prevede che il valore 0 sia usato per specificare il
-segnale nullo.  Se le funzioni vengono chiamate con questo valore non viene
-inviato nessun segnale, ma viene eseguito il controllo degli errori, in tal
-caso si otterrà un errore \macro{EPERM} se non si hanno i permessi necessari
-ed un errore \macro{ESRCH} se il processo specificato non esiste. Si tenga
-conto però che il sistema ricicla i \acr{pid} (come accennato in
-\secref{sec:proc_pid}) per cui l'esistenza di un processo non significa che
+Lo standard POSIX prevede che il valore 0 per \param{sig} sia usato per
+specificare il segnale nullo.  Se le funzioni vengono chiamate con questo
+valore non viene inviato nessun segnale, ma viene eseguito il controllo degli
+errori, in tal caso si otterrà un errore \macro{EPERM} se non si hanno i
+permessi necessari ed un errore \macro{ESRCH} se il processo specificato non
+esiste. Si tenga conto però che il sistema ricicla i \acr{pid} (come accennato
+in \secref{sec:proc_pid}) per cui l'esistenza di un processo non significa che
 esso sia realmente quello a cui si intendeva mandare il segnale.
 
 Il valore dell'argomento \param{pid} specifica il processo (o i processi) di
 destinazione a cui il segnale deve essere inviato e può assumere i valori
 riportati in \tabref{tab:sig_kill_values}.
 \begin{table}[htb]
 esso sia realmente quello a cui si intendeva mandare il segnale.
 
 Il valore dell'argomento \param{pid} specifica il processo (o i processi) di
 destinazione a cui il segnale deve essere inviato e può assumere i valori
 riportati in \tabref{tab:sig_kill_values}.
 \begin{table}[htb]
+  \footnotesize
   \centering
   \begin{tabular}[c]{|r|l|}
     \hline
   \centering
   \begin{tabular}[c]{|r|l|}
     \hline
@@ -1022,6 +1014,11 @@ riportati in \tabref{tab:sig_kill_values}.
   \label{tab:sig_kill_values}
 \end{table}
 
   \label{tab:sig_kill_values}
 \end{table}
 
+Si noti pertanto che la funzione \code{raise(sig)} può essere definita in
+termini di \func{kill}, ed è sostanzialmente equivalente ad una
+\code{kill(getpid(), sig)}. Siccome \func{raise}, che è definita nello
+standard ISO C, non esiste in alcune vecchie versioni di Unix, in generale
+l'uso di \func{kill} finisce per essere più portabile.
 
 Solo l'amministratore può inviare un segnale ad un processo qualunque, in
 tutti gli altri casi il \textit{real user id} o l'\textit{effective user id}
 
 Solo l'amministratore può inviare un segnale ad un processo qualunque, in
 tutti gli altri casi il \textit{real user id} o l'\textit{effective user id}
@@ -1045,9 +1042,10 @@ segnale al processo che ha effettuato la chiamata.
 \label{sec:sig_alarm_abort}
 
 Un caso particolare di segnali generati a richiesta è quello che riguarda i
 \label{sec:sig_alarm_abort}
 
 Un caso particolare di segnali generati a richiesta è quello che riguarda i
-segnali di temporizzazione e \macro{SIGABORT}, per i quali sono previste
-funzioni specifiche che ne effettuino l'invio. La prima di queste è
-\func{alarm} il cui prototipo è:
+vari segnali di temporizzazione e \macro{SIGABORT}, per ciascuno di questi
+segnali sono previste funzioni specifiche che ne effettuino l'invio. La più
+comune delle funzioni usate per la temporizzazione è \func{alarm} il cui
+prototipo è:
 \begin{prototype}{unistd.h}{unsigned int alarm(unsigned int seconds)}
   Predispone l'invio di \macro{SIGALARM} dopo \param{seconds} secondi.
   
 \begin{prototype}{unistd.h}{unsigned int alarm(unsigned int seconds)}
   Predispone l'invio di \macro{SIGALARM} dopo \param{seconds} secondi.
   
@@ -1055,22 +1053,25 @@ funzioni specifiche che ne effettuino l'invio. La prima di queste 
     precedente allarme, o zero se non c'erano allarmi pendenti.}
 \end{prototype}
 
     precedente allarme, o zero se non c'erano allarmi pendenti.}
 \end{prototype}
 
-La funzione provvede un meccanismo che consente ad un processo di predisporre
+La funzione fornisce un meccanismo che consente ad un processo di predisporre
 un'interruzione nel futuro, (ad esempio per effettuare una qualche operazione
 un'interruzione nel futuro, (ad esempio per effettuare una qualche operazione
-dopo un certo periodo di tempo), programmando l'emissione di un segnale (in
-genere \macro{SIGALARM}) dopo il numero di secondi specificato da
+dopo un certo periodo di tempo), programmando l'emissione di un segnale (nel
+caso in questione \macro{SIGALARM}) dopo il numero di secondi specificato da
 \param{seconds}.
 
 Se si specifica per \param{seconds} un valore nullo non verrà inviato nessun
 segnale; siccome alla chiamata viene cancellato ogni precedente allarme,
 \param{seconds}.
 
 Se si specifica per \param{seconds} un valore nullo non verrà inviato nessun
 segnale; siccome alla chiamata viene cancellato ogni precedente allarme,
-questo può essere usato per cancellare una programmazione precedente. La
-funzione inoltre ritorna il numero di secondi rimanenti all'invio dell'allarme
-precedentemente programmato, in modo che sia eventualmente possibile
-effettuare delle scelte in caso di necessità di più interruzioni.
+questo può essere usato per cancellare una programmazione precedente. 
+
+La funzione inoltre ritorna il numero di secondi rimanenti all'invio
+dell'allarme precedentemente programmato, in modo che sia possibile
+controllare se non si cancella un precedente allarme ed eventualmente
+predisporre le opportune misure per gestire il caso di necessità di più
+interruzioni.
 
 In \secref{sec:sys_unix_time} abbiamo visto che ad ogni processo sono
 
 In \secref{sec:sys_unix_time} abbiamo visto che ad ogni processo sono
-associati tre tempi diversi: \textit{clock time}, \textit{user time} e
-\textit{system time}.  Per poterli calcolare il kernel mantiene per ciascun
+associati tre tempi diversi: il \textit{clock time}, l'\textit{user time} ed
+il \textit{system time}.  Per poterli calcolare il kernel mantiene per ciascun
 processo tre diversi timer:
 \begin{itemize}
 \item un \textit{real-time timer} che calcola il tempo reale trascorso (che
 processo tre diversi timer:
 \begin{itemize}
 \item un \textit{real-time timer} che calcola il tempo reale trascorso (che
@@ -1111,6 +1112,7 @@ Il valore di \param{which} permette di specificare quale dei tre timer
 illustrati in precedenza usare; i possibili valori sono riportati in
 \tabref{tab:sig_setitimer_values}.
 \begin{table}[htb]
 illustrati in precedenza usare; i possibili valori sono riportati in
 \tabref{tab:sig_setitimer_values}.
 \begin{table}[htb]
+  \footnotesize
   \centering
   \begin{tabular}[c]{|l|l|}
     \hline
   \centering
   \begin{tabular}[c]{|l|l|}
     \hline
@@ -1130,7 +1132,7 @@ illustrati in precedenza usare; i possibili valori sono riportati in
 Il valore della struttura specificata \param{value} viene usato per settare il
 timer, se il puntatore \param{ovalue} non è nullo il precedente valore viene
 salvato qui. I valori dei timer devono essere indicati attraverso una
 Il valore della struttura specificata \param{value} viene usato per settare il
 timer, se il puntatore \param{ovalue} non è nullo il precedente valore viene
 salvato qui. I valori dei timer devono essere indicati attraverso una
-struttura \var{itimerval}, definita in \ref{fig:file_stat_struct}.
+struttura \var{itimerval}, definita in \figref{fig:file_stat_struct}.
 
 La struttura è composta da due membri, il primo, \var{it\_interval} definisce
 il periodo del timer; il secondo, \var{it\_value} il tempo mancante alla
 
 La struttura è composta da due membri, il primo, \var{it\_interval} definisce
 il periodo del timer; il secondo, \var{it\_value} il tempo mancante alla
@@ -1138,18 +1140,22 @@ scadenza. Entrambi esprimono i tempi tramite una struttura \var{timeval} che
 permette una precisione fino al microsecondo.
 
 Ciascun timer decrementa il valore di \var{it\_value} fino a zero, poi invia
 permette una precisione fino al microsecondo.
 
 Ciascun timer decrementa il valore di \var{it\_value} fino a zero, poi invia
-il segnale e resetta \var{it\_value} al valore di \var{it\_interval},
-ripetendo il ciclo; se \var{it\_interval} è nullo il timer si ferma.
+il segnale e resetta \var{it\_value} al valore di \var{it\_interval}, in
+questo modo il ciclo verrà ripetuto; se invece il valore di \var{it\_interval}
+è nullo il timer si ferma.
 
 \begin{figure}[!htb]
   \footnotesize \centering
   \begin{minipage}[c]{15cm}
 
 \begin{figure}[!htb]
   \footnotesize \centering
   \begin{minipage}[c]{15cm}
-    \begin{lstlisting}[labelstep=0,frame=,indent=1cm]{}
-struct itimerval {
+    \begin{lstlisting}[labelstep=0]{}%,frame=,indent=1cm]{}
+struct itimerval 
+{
     struct timeval it_interval; /* next value */
     struct timeval it_value;    /* current value */
 };
     struct timeval it_interval; /* next value */
     struct timeval it_value;    /* current value */
 };
-struct timeval {
+
+struct timeval 
+{
     long tv_sec;                /* seconds */
     long tv_usec;               /* microseconds */
 };
     long tv_sec;                /* seconds */
     long tv_usec;               /* microseconds */
 };
@@ -1165,12 +1171,13 @@ L'uso di \func{setitimer} consente dunque un controllo completo di tutte le
 caratteristiche dei timer, ed in effetti la stessa \func{alarm}, benché
 definita direttamente nello standard POSIX.1, può a sua volta essere espressa
 in termini di \func{setitimer}, come evidenziato dal manuale delle \acr{glibc}
 caratteristiche dei timer, ed in effetti la stessa \func{alarm}, benché
 definita direttamente nello standard POSIX.1, può a sua volta essere espressa
 in termini di \func{setitimer}, come evidenziato dal manuale delle \acr{glibc}
-\cite{glibc} che ne riporta la definizione in \figref{fig:sig_alarm_def}.
+\cite{glibc} che ne riporta la definizione mostrata in
+\figref{fig:sig_alarm_def}.
 
 \begin{figure}[!htb]
   \footnotesize \centering
   \begin{minipage}[c]{15cm}
 
 \begin{figure}[!htb]
   \footnotesize \centering
   \begin{minipage}[c]{15cm}
-    \begin{lstlisting}[labelstep=0,frame=,indent=1cm]{}
+    \begin{lstlisting}[labelstep=0]{}%,frame=,indent=1cm]{}
 unsigned int alarm(unsigned int seconds)
 {
     struct itimerval old, new;
 unsigned int alarm(unsigned int seconds)
 {
     struct itimerval old, new;
@@ -1178,10 +1185,12 @@ unsigned int alarm(unsigned int seconds)
     new.it_interval.tv_sec = 0;
     new.it_value.tv_usec = 0;
     new.it_value.tv_sec = (long int) seconds;
     new.it_interval.tv_sec = 0;
     new.it_value.tv_usec = 0;
     new.it_value.tv_sec = (long int) seconds;
-    if (setitimer(ITIMER_REAL, &new, &old) < 0)
+    if (setitimer(ITIMER_REAL, &new, &old) < 0) {
         return 0;
         return 0;
-    else
+    }
+    else {
         return old.it_value.tv_sec;
         return old.it_value.tv_sec;
+    }
 }
     \end{lstlisting}
   \end{minipage} 
 }
     \end{lstlisting}
   \end{minipage} 
@@ -1191,13 +1200,23 @@ unsigned int alarm(unsigned int seconds)
 \end{figure}
 
 Si deve comunque tenere presente che la precisione di queste funzioni è
 \end{figure}
 
 Si deve comunque tenere presente che la precisione di queste funzioni è
-limitata da quella del timer di sistema (in genere 10~ms). Il sistema assicura
-comunque che il segnale non sarà mai generato prima della scadenza programmata
-(l'arrotondamento cioè è sempre effettuato per eccesso). Una seconda causa di
-potenziali ritardi è che il segnale viene generato alla scadenza del timer,
-ma poi deve essere consegnato; se il processo è attivo (questo è sempre vero
-per \macro{ITIMER\_VIRT}) la consegna è immediata, altrimenti può esserci un
-ulteriore ritardo che può variare a seconda del carico del sistema.
+limitata da quella della frequenza del timer di sistema (che nel caso dei PC
+significa circa 10~ms). Il sistema assicura comunque che il segnale non sarà
+mai generato prima della scadenza programmata (l'arrotondamento cioè è sempre
+effettuato per eccesso).  
+
+Una seconda causa di potenziali ritardi è che il segnale viene generato alla
+scadenza del timer, ma poi deve essere consegnato al processo; se quest'ultimo
+è attivo (questo è sempre vero per \macro{ITIMER\_VIRT}) la consegna è
+immediata, altrimenti può esserci un ulteriore ritardo che può variare a
+seconda del carico del sistema.
+
+Questo ha una conseguenza che può indurre ad errori molto subdoli, si tenga
+conto poi che in caso di sistema molto carico, si può avere il caso patologico
+in cui un timer scade prima che il segnale di una precedente scadenza sia
+stato consegnato; in questo caso, per il comportamento dei segnali descritto
+in \secref{sec:sig_sigchld}, un solo segnale sarà consegnato.
+
 
 Dato che sia \func{alarm} che \func{setitimer} non consentono di leggere il
 valore corrente di un timer senza modificarlo, è possibile usare la funzione
 
 Dato che sia \func{alarm} che \func{setitimer} non consentono di leggere il
 valore corrente di un timer senza modificarlo, è possibile usare la funzione
@@ -1333,22 +1352,6 @@ delle strutture di tipo \var{timespec}, la cui definizione 
 \figref{fig:sig_timespec_def}, che permettono di specificare un tempo con una
 precisione (teorica) fino al nanosecondo. 
 
 \figref{fig:sig_timespec_def}, che permettono di specificare un tempo con una
 precisione (teorica) fino al nanosecondo. 
 
-\begin{figure}[!htb]
-  \footnotesize \centering
-  \begin{minipage}[c]{15cm}
-    \begin{lstlisting}[labelstep=0,frame=,indent=1cm]{}
-struct timespec
-{
-    time_t  tv_sec;         /* seconds */
-    long    tv_nsec;        /* nanoseconds */
-};
-    \end{lstlisting}
-  \end{minipage} 
-  \normalsize 
-  \caption{La struttura \var{timespec} di \func{nanosleep}.} 
-  \label{fig:sig_timespec_def}
-\end{figure}
-
 La funzione risolve anche il problema di proseguire l'attesa dopo
 l'interruzione dovuta ad un segnale; infatti in tal caso in \param{rem} viene
 restituito il tempo rimanente rispetto a quanto richiesto inizialmente, e
 La funzione risolve anche il problema di proseguire l'attesa dopo
 l'interruzione dovuta ad un segnale; infatti in tal caso in \param{rem} viene
 restituito il tempo rimanente rispetto a quanto richiesto inizialmente, e
@@ -1364,6 +1367,21 @@ sia scarico ed il processa venga immediatamente rimesso in esecuzione); per
 questo motivo il valore restituito in \param{rem} è sempre arrotondato al
 multiplo successivo di 1/\macro{HZ}.
 
 questo motivo il valore restituito in \param{rem} è sempre arrotondato al
 multiplo successivo di 1/\macro{HZ}.
 
+\begin{figure}[!htb]
+  \footnotesize \centering
+  \begin{minipage}[c]{15cm}
+    \begin{lstlisting}[labelstep=0]{}%,frame=,indent=1cm]{}
+struct timespec {
+    time_t  tv_sec;         /* seconds */
+    long    tv_nsec;        /* nanoseconds */
+};
+    \end{lstlisting}
+  \end{minipage} 
+  \normalsize 
+  \caption{La struttura \var{timespec} di \func{nanosleep}.} 
+  \label{fig:sig_timespec_def}
+\end{figure}
+
 In realtà è possibile ottenere anche pause più precise del centesimo di
 secondo usando politiche di scheduling real time come \macro{SCHED\_FIFO} o
 \macro{SCHED\_RR}; in tal caso infatti il meccanismo di scheduling ordinario
 In realtà è possibile ottenere anche pause più precise del centesimo di
 secondo usando politiche di scheduling real time come \macro{SCHED\_FIFO} o
 \macro{SCHED\_RR}; in tal caso infatti il meccanismo di scheduling ordinario
@@ -1496,7 +1514,7 @@ fino a trattare le caratteristiche generali della gestione dei medesimi nella
 casistica ordinaria.
 
 
 casistica ordinaria.
 
 
-\subsection{Un esempio di problema}
+\subsection{Alcune problematiche aperte}
 \label{sec:sig_example}
 
 Come accennato in \secref{sec:sig_pause_sleep} è possibile implementare
 \label{sec:sig_example}
 
 Come accennato in \secref{sec:sig_pause_sleep} è possibile implementare
@@ -1535,7 +1553,8 @@ unsigned int sleep(unsigned int seconds)
     /* remove alarm, return remaining time */
     return alarm(0);
 }
     /* remove alarm, return remaining time */
     return alarm(0);
 }
-void alarm_hand(int sig) {
+void alarm_hand(int sig) 
+{
     /* check if the signal is the right one */
     if (sig != SIGALRM) { /* if not exit with error */
         printf("Something wrong, handler for SIGALRM\n");
     /* check if the signal is the right one */
     if (sig != SIGALRM) { /* if not exit with error */
         printf("Something wrong, handler for SIGALRM\n");
@@ -1588,7 +1607,8 @@ unsigned int sleep(unsigned int seconds)
     /* remove alarm, return remaining time */
     return alarm(0);
 }
     /* remove alarm, return remaining time */
     return alarm(0);
 }
-void alarm_hand(int sig) {
+void alarm_hand(int sig) 
+{
     /* check if the signal is the right one */
     if (sig != SIGALRM) { /* if not exit with error */
         printf("Something wrong, handler for SIGALRM\n");
     /* check if the signal is the right one */
     if (sig != SIGALRM) { /* if not exit with error */
         printf("Something wrong, handler for SIGALRM\n");
@@ -1615,29 +1635,302 @@ 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.  È per questo
-motivo che occorrono funzioni più sofisticate della semplice \func{signal} che
-permettano di gestire in maniera più completa
+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.
+
+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;
+int main()
+{
+    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;
+    return;
+}      
+    \end{lstlisting}
+  \end{minipage} 
+  \normalsize 
+  \caption{Un esempio non funzionante del codice per il controllo di un
+    evento generato da un segnale.}
+  \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.
+
+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.
+
+
+
+\subsection{I \textit{signal set}}
+\label{sec:sig_sigset}
+
+Come evidenziato nel paragrafo precedente, le funzioni di gestione dei segnali
+dei primi Unix, nate con la semantica inaffidabile, hanno dei limiti non
+superabili; in particolare non è prevista nessuna funzione che permetta di
+gestire gestire il blocco dei segnali o di verificare lo stato dei segnali
+pendenti.
+
+Per questo motivo lo standard POSIX.1, insieme alla nuova semantica dei
+segnali ha introdotto una interfaccia di gestione completamente nuova, che
+permette di ottenete un controllo molto più dettagliato. In particolare lo
+standard ha introdotto un nuovo tipo di dato \type{sigset\_t}, che permette di
+rappresentare un insieme di segnali (un \textit{signal set}, come viene
+usualmente chiamato), che è il tipo di dato che viene usato per gestire il
+blocco dei segnali.
+
+In genere un \textit{signal set} è rappresentato da un intero di dimensione
+opportuna, di solito si pari al numero di bit dell'architettura della
+macchina\footnote{nel caso dei PC questo comporta un massimo di 32 segnali
+  distinti, dato che in Linux questi sono sufficienti non c'è necessità di
+  nessuna struttura più complicata.}, ciascun bit del quale è associato ad uno
+specifico segnale; in questo modo è di solito possibile implementare le
+operazioni direttamente con istruzioni elementari del processore; lo standard
+POSIX.1 definisce cinque funzioni per la manipolazione dei \textit{signal set},
+\func{sigemptyset}, \func{sigfillset}, \func{sigaddset}, \func{sigdelset} e
+\func{sigismember}, i cui prototipi sono:
+\begin{functions}
+  \headdecl{signal.h} 
 
 
-\subsection{Le funzioni \func{sigprocmask} e \func{sigpending}}
-\label{sec:sig_sigpending}
+  \funcdecl{int sigemptyset(sigset\_t *set)} Inizializza un \textit{signal set}
+  vuoto.
+  \funcdecl{int sigfillset(sigset\_t *set)} Inizializza un \textit{signal set}
+  pieno (con tutti i segnali).
+  
+  \funcdecl{int sigaddset(sigset\_t *set, int signum)} Aggiunge il segnale
+  \param{signum} al  \textit{signal set} \param{set}.
+
+  \funcdecl{int sigdelset(sigset\_t *set, int signum)} Toglie il segnale
+  \param{signum} dal \textit{signal set} \param{set}.
+  
+  \funcdecl{int sigismember(const sigset\_t *set, int signum)} Controlla se il
+  segnale \param{signum} è nel \textit{signal set} \param{set}
+  
+  \bodydesc{Le prime quattro funzioni ritornano 0 in caso di successo, mentre
+    \func{sigismember} ritorna 1 se \param{signum} è in \param{set} e 0
+    altrimenti. In caso di errore tutte ritornano -1, con \var{errno} settata a
+    \macro{EINVAL} (il solo errore possibile è che \param{signum} non sia un
+    segnale valido).}
+\end{functions}
 
 
+Dato che in generale non si può fare conto sulle caratteristiche di una
+implementazione (non è detto che si disponga di un numero di bit sufficienti
+per mettere tutti i segnali in un intero, o in \type{sigset\_t} possono essere
+immagazzinate ulteriori informazioni) tutte le operazioni devono essere
+comunque eseguite attraverso queste funzioni.
 
 
+In genere si usa un \textit{signal set} per specificare quali segnali si vuole
+bloccare, o per riottenere dalle varie funzioni di gestione la maschera dei
+segnali attivi. Essi possono essere definiti in due diverse maniere,
+aggiungendo i segnali voluti ad un insieme vuoto ottenuto con
+\func{sigemptyset} o togliendo quelli che non servono da un insieme completo
+ottenuto con \func{sigfillset}. Infine \func{sigismember} permette di vericare
+la presenza di uno specifico segnale in un \textit{signal set}.
 
 
 \subsection{La funzione \func{sigaction}}
 \label{sec:sig_sigaction}
 
 
 
 \subsection{La funzione \func{sigaction}}
 \label{sec:sig_sigaction}
 
+La funzione principale dell'interfaccia standard POSIX.1 per i segnali è
+\func{sigaction}, essa ha sostanzialemente le stesse funzioni di
+\func{signal}, permette cioè di specificare come un segnale può essere gestito
+da un processo. Il suo prototipo è:
+
+\begin{prototype}{signal.h}{int sigaction(int signum, const struct sigaction
+    *act, struct sigaction *oldact)} 
+  
+  Installa un nuovo manipolatore per il segnale \param{signum}.
+  
+  \bodydesc{La funzione restituisce zero in caso di successo e -1 per un
+    errore, nel qual caso \var{errno} assumerà i valori:
+  \begin{errlist}
+  \item[\macro{EINVAL}] Si è specificato un numero di segnale invalido o si è
+    cercato di installare il manipolatore per \macro{SIGKILL} o
+    \macro{SIGSTOP}.
+  \item[\macro{EFAULT}] Si sono specificati indirizzi non validi.
+  \end{errlist}}
+\end{prototype}
+
+La funzione serve ad installare una nuova \textsl{azione} per il segnale
+\param{signum}; si parla di \textsl{azione} e non di \textsl{manipolatore}
+come nel caso di \func{signal}, in quanto la funzione consente di specificare
+le varie caratteristiche della risposta al segnale, non solo la funzione del
+manipolatore.  Per questo lo standard raccomanda di usare sempre questa
+funzione al posto di \func{signal} (che in genere viene definita tramite
+essa), in quanto offre un controllo completo su tutti gli aspetti della
+gestione di un segnale, sia pure al prezzo di una maggiore complessità d'uso.
+
+Se il puntatore \param{act} non è nullo, la funzione installa la nuova azione
+da esso specificata, se \param{oldact} non è nullo il valore dell'azione
+corrente viene restituito indietro.  Questo permette (specificando \param{act}
+nullo e \param{oldact} non nullo) di superare uno dei limiti di \func{signal},
+che non consente di ottenere l'azione corrente senza installarne una nuova.
+
+Entrambi i puntatori fanno riferimento alla struttura \var{sigaction}, tramite
+la quale si specificano tutte le caratteristiche dell'azione associata ad un
+segnale.  Anch'essa è descritta dallo standard POSIX.1 ed in Linux è definita
+secondo quanto riportato in \figref{fig:sig_sigaction}. Il campo
+\var{sa\_restorer}, non previsto dallo standard, è obsoleto e non deve essere
+più usato.
+
+\begin{figure}[!htb]
+  \footnotesize \centering
+  \begin{minipage}[c]{15cm}
+    \begin{lstlisting}[labelstep=0]{}%,frame=,indent=1cm]{}
+struct sigaction 
+{
+    void (*sa_handler)(int);
+    void (*sa_sigaction)(int, siginfo_t *, void *);
+    sigset_t sa_mask;
+    int sa_flags;
+    void (*sa_restorer)(void);
+}
+    \end{lstlisting}
+  \end{minipage} 
+  \normalsize 
+  \caption{La struttura \var{sigaction}.} 
+  \label{fig:sig_sigaction}
+\end{figure}
+
+Come si può notare da quanto riportato in \figref{fig:sig_sigaction} in Linux
+\func{sigaction} permette di specificare il manipolatore in due forme diverse,
+indicate dai campi \var{sa\_handler} e \var{sa\_sigaction}; esse devono essere
+usate in maniera alternativa (in certe implementazioni questi vengono
+specificati come \ctyp{union}): la prima è quella classica usata anche con
+\func{signal}, la seconda permette invece di usare un manipolatore in grado di
+ricevere informazioni più dettagliate dal sistema (ad esempio il tipo di
+errore in caso di \macro{SIGFPE}), attraverso dei parametri aggiuntivi; per i
+dettagli si consulti la man page di \func{sigaction}).
+
+Il campo \var{sa\_mask} serve ad indicare l'insieme dei segnali che devono
+essere bloccati durante l'esecuzione del manipolatore, ad essi viene comunque
+sempre aggiunto il segnale che ne ha causato la chiamata, a meno che non si
+sia specificato con \var{sa\_flag} un comportamento diverso.
+
+Il valore di \var{sa\_flag} permette di specificare vari aspetti del
+comportamento di \func{sigaction}, e della reazione del processo ai vari
+segnali; i valori possibili ed il relativo significato sono riportati in
+\tabref{tab:sig_sa_flag}. 
+
+\begin{table}[htb]
+  \footnotesize
+  \centering
+  \begin{tabular}[c]{|l|p{8cm}|}
+    \hline
+    \textbf{Valore} & \textbf{Timer} \\
+    \hline
+    \hline
+    \macro{SA\_NOCLDSTOP}& Se il segnale è \macro{SIGCHLD} allora non deve
+    essere notificato quando il processo figlio viene fermato da uno dei
+    segnali \macro{SIGSTOP}, \macro{SIGTSTP}, \macro{SIGTTIN} or 
+    \macro{SIGTTOU}.\\
+    \macro{SA\_ONESHOT}  & Ristabilisce l'azione per il segnale al valore di
+    default una volta che il manipolatore è stato lanciato, riproduce cioè il
+    comportamento della semantica inaffidabile.\\
+    \macro{SA\_RESETHAND}& Sinonimo di \macro{SA\_ONESHOT}. \\
+    \macro{SA\_RESTART}  & Riavvia automaticamente le \textit{slow system
+    call} quando vengono interrotte dal suddetto segnale; riproduce cioè il
+    comportamento standard di BSD.\\
+    \macro{SA\_NOMASK}   & Evita che il segnale corrente sia bloccato durante
+    l'esecuzione del manipolatore.\\
+    \macro{SA\_NODEFER}  & Sinonimo di  \macro{SA\_NOMASK}.\\
+    \macro{SA\_SIGINFO}  & Deve essere specificato quando si vuole usare un
+    manipolatore in forma estesa usando \var{sa\_sigaction} al posto di
+    \var{sa\_handler}. \\
+    \macro{SA\_ONSTACK}   & Stabilisce l'uso di uno stack alternativo per
+    l'esecuzione del manipolatore (vedi \secref{sec:sig_altstack}).\\
+    \hline
+  \end{tabular}
+  \caption{Valori del campo \var{sa\_flag} della struttura \var{sigaction}.}
+  \label{tab:sig_sa_flag}
+\end{table}
+
+Benché sia possibile usare nello stesso programma sia \func{sigaction} che
+\func{signal} occorre molta attenzione, in quanto le due funzioni possono
+interagire in maniera anomala. Infatti l'azione specificata con
+\var{sigaction} contiene un maggior numero di informazioni rispetto al
+semplice indirizzo del manipolatore restituito da \func{signal}.  Per questo
+motivo se si usa quest'ultima per installare un manipolatore sostituendone uno
+precedentemente installato con \func{sigaction}, non sarà possibile effettuare
+un ripristino corretto dello stesso.
+
+Per questo è sempre opportuno usare \func{sigaction}, che è in grado di
+ripristinare correttamente un manipolatore precedente, anche se questo è stato
+installato con \func{signal}. In generale poi non è il caso di usare il valore
+di ritorno di \func{signal} come campo \var{sa\_handler}, o viceversa, dato
+che in certi sistemi questi possono essere diversi. In generale dunque, a meno
+che non si sia vincolati allo standard ISO C, è sempre il caso di evitare
+l'uso di \func{signal} a favore di \func{sigaction}.
+
+
+
+\subsection{La gestione del blocco dei segnali}
+\label{sec:sig_sigmask}
+
+Come spiegato in \secref{sec:sig_semantics} tutti i moderni sistemi unix-like
+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}
+  della relativa \var{task\_struct}} 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}.
+
+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.
+
+
+
+\subsection{Le funzioni \func{sigpending} e \func{sigsuspend}}
+\label{sec:sig_sigpending}
+
+
+
 
 
 \subsection{Funzioni rientranti e default dei segnali}
 \label{sec:sig_reentrant}
 
 
 
 
 \subsection{Funzioni rientranti e default dei segnali}
 \label{sec:sig_reentrant}
 
 
-, affrontando inoltre le varie problematiche di programmazione che si devono
-tenere presenti quando si ha a che fare con essi.