Correzione ai limiti, aggiustate referenze e iniziato le funzioni per
[gapil.git] / signal.tex
index 4055c7a4f8e60d3c0f60134f71b1802c9218cad1..f0565a23a2e305ccbfbe3fa04130cad36872efa8 100644 (file)
@@ -377,7 +377,7 @@ stato dello stack e delle variabili al momento della ricezione del segnale.
     \macro{SIGTTOU}  &PL & D & Output sul terminale per un processo          
                                in background                                 \\
     \macro{SIGBUS}   &SL & C & Errore sul bus (bad memory access)            \\
     \macro{SIGTTOU}  &PL & D & Output sul terminale per un processo          
                                in background                                 \\
     \macro{SIGBUS}   &SL & C & Errore sul bus (bad memory access)            \\
-    \macro{SIGPOLL}  &SL & A & Pollable event (Sys V).                      
+    \macro{SIGPOLL}  &SL & A & \textit{Pollable event} (Sys V).  
                                Sinonimo di \macro{SIGIO}                     \\
     \macro{SIGPROF}  &SL & A & Timer del profiling scaduto                   \\
     \macro{SIGSYS}   &SL & C & Argomento sbagliato per una subroutine (SVID) \\
                                Sinonimo di \macro{SIGIO}                     \\
     \macro{SIGPROF}  &SL & A & Timer del profiling scaduto                   \\
     \macro{SIGSYS}   &SL & C & Argomento sbagliato per una subroutine (SVID) \\
@@ -682,8 +682,8 @@ classificabili in maniera omogenea. Questi segnali sono:
   implementare una comunicazione elementare fra processi diversi, o per
   eseguire a richiesta una operazione utilizzando un manipolatore. L'azione di
   default è terminare il processo.
   implementare una comunicazione elementare fra processi diversi, o per
   eseguire a richiesta una operazione utilizzando un manipolatore. L'azione di
   default è terminare il processo.
-\item[\macro{SIGWINCH}] Il nome sta per \textit{window (size) change} ed è
-  generato da molti sistemi (GNU/Linux compreso) quando le dimensioni (in
+\item[\macro{SIGWINCH}] Il nome sta per \textit{window (size) change} e viene
+  generato in molti sistemi (GNU/Linux compreso) quando le dimensioni (in
   righe e colonne) di un terminale vengono cambiate. Viene usato da alcuni
   programmi testuali per riformattare l'uscita su schermo quando si cambia
   dimensione a quest'ultimo. L'azione di default è di essere ignorato.
   righe e colonne) di un terminale vengono cambiate. Viene usato da alcuni
   programmi testuali per riformattare l'uscita su schermo quando si cambia
   dimensione a quest'ultimo. L'azione di default è di essere ignorato.
@@ -996,6 +996,18 @@ termini di \func{kill}, ed 
 standard ISO C, non esiste in alcune vecchie versioni di Unix, in generale
 l'uso di \func{kill} finisce per essere più portabile.
 
 standard ISO C, non esiste in alcune vecchie versioni di Unix, in generale
 l'uso di \func{kill} finisce per essere più portabile.
 
+Una seconda funzione che può essere definita in termini di \func{kill} è
+\func{killpg}, che è sostanzialmente equivalente a
+\code{kill(-pidgrp, signal)}; il suo prototipo è:
+\begin{prototype}{signal.h}{int killpg(pid\_t pidgrp, int signal)} 
+  
+  Invia il segnale \param{signal} al process group \param{pidgrp}.
+  \bodydesc{La funzione restituisce 0 in caso di successo e -1 in caso di
+    errore, gli errori sono gli stessi di \func{kill}.}
+\end{prototype}
+e che permette di inviare un segnale a tutto un \textit{process group} (vedi
+\secref{sec:sess_xxx}).
+
 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}
 del processo chiamante devono corrispondere al \textit{real user id} o al
 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}
 del processo chiamante devono corrispondere al \textit{real user id} o al
@@ -1403,7 +1415,7 @@ la creazione di zombie.
   \footnotesize \centering
   \begin{minipage}[c]{15cm}
     \begin{lstlisting}{}
   \footnotesize \centering
   \begin{minipage}[c]{15cm}
     \begin{lstlisting}{}
-#include <errno.h>       /* error simbol definitions */
+#include <errno.h>       /* error symbol definitions */
 #include <signal.h>      /* signal handling declarations */
 #include <sys/types.h>
 #include <sys/wait.h>
 #include <signal.h>      /* signal handling declarations */
 #include <sys/types.h>
 #include <sys/wait.h>
@@ -1461,7 +1473,7 @@ 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.
 
 segnali emessi durante il periodo di blocco, una volta che quest'ultimo sarà
 rimosso sarà recapitato un solo segnale.
 
-Allora nel caso della terminazione dei processi figli, se si chiamasse
+Allora, nel caso della terminazione dei processi figli, se si chiamasse
 \func{waitpid} una sola volta, essa leggerebbe lo stato di terminazione 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.
 \func{waitpid} una sola volta, essa leggerebbe lo stato di terminazione 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.
@@ -1501,43 +1513,44 @@ versione di \func{sleep} potrebbe essere quella illustrata in
 
 Dato che è nostra intenzione utilizzare \macro{SIGALRM} il primo passo della
 nostra implementazione di sarà quello di installare il relativo manipolatore
 
 Dato che è nostra intenzione utilizzare \macro{SIGALRM} 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
+salvando il precedente (\texttt{\small 14-17}).  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 17-19}) fino alla sua ricezione.  Al ritorno di \func{pause},
+causato dal ritorno del manipolatore (\texttt{\small 1-9}), si ripristina il
+manipolatore originario (\texttt{\small 20-21}) restituendo l'eventuale tempo
+rimanente (\texttt{\small 22-23}) che potrà essere diverso da zero qualora
 l'interruzione di \func{pause} venisse causata da un altro segnale.
 
 \begin{figure}[!htb]
   \footnotesize \centering
   \begin{minipage}[c]{15cm}
     \begin{lstlisting}{}
 l'interruzione di \func{pause} venisse causata da un altro segnale.
 
 \begin{figure}[!htb]
   \footnotesize \centering
   \begin{minipage}[c]{15cm}
     \begin{lstlisting}{}
+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");
+        exit(1);
+    } else {    /* do nothing, just interrupt pause */
+        return;
+    }
+}
 unsigned int sleep(unsigned int seconds)
 {
 unsigned int sleep(unsigned int seconds)
 {
-    signandler_t prev_handler;
+    sighandler_t prev_handler;
+    /* install and check new handler */
     if ((prev_handler = signal(SIGALRM, alarm_hand)) == SIG_ERR) {
     if ((prev_handler = signal(SIGALRM, alarm_hand)) == SIG_ERR) {
-        printf("Cannot set handler for alarm\n");
-        exit(1);
+        printf("Cannot set handler for alarm\n"); 
+        exit(-1);
     }
     }
-    alarm(second);
+    /* set alarm and go to sleep */
+    alarm(seconds); 
     pause(); 
     /* restore previous signal handler */
     signal(SIGALRM, prev_handler);
     pause(); 
     /* restore previous signal handler */
     signal(SIGALRM, prev_handler);
-    /* remove alarm, return remaining time */
+    /* return remaining time */
     return alarm(0);
 }
     return alarm(0);
 }
-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");
-        exit(1);
-    } else {    /* do nothing, just interrupt pause */
-        return;
-    }
-}      
     \end{lstlisting}
   \end{minipage} 
   \normalsize 
     \end{lstlisting}
   \end{minipage} 
   \normalsize 
@@ -1602,7 +1615,7 @@ void alarm_hand(int sig)
 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
 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
+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.
 
 (\texttt{\small 9-12}) si evita comunque che \func{pause} sia chiamata a
 vuoto.
 
@@ -1618,7 +1631,7 @@ Un secondo esempio 
 qualche 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
 qualche 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}.
+\figref{fig:sig_event_wrong}).
 
 \begin{figure}[!htb]
   \footnotesize \centering
 
 \begin{figure}[!htb]
   \footnotesize \centering
@@ -1663,13 +1676,14 @@ della cancellazione del flag (\texttt{\small 7}), la sua occorrenza sar
 perduta.
 
 Questi esempi ci mostrano che per una gestione effettiva dei segnali occorrono
 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
+funzioni più sofisticate di quelle illustrate finora, che hanno origine dalla
+interfaccia semplice, ma poco sofisticata, dei primi sistemi Unix, in modo da
+consentire la gestione di tutti i possibili aspetti con cui un processo deve
 reagire alla ricezione di un segnale.
 
 
 
 reagire alla ricezione di un segnale.
 
 
 
-\subsection{I \textit{signal set}}
+\subsection{Gli \textsl{insiemi di segnali} o \textit{signal set}}
 \label{sec:sig_sigset}
 
 Come evidenziato nel paragrafo precedente, le funzioni di gestione dei segnali
 \label{sec:sig_sigset}
 
 Come evidenziato nel paragrafo precedente, le funzioni di gestione dei segnali
@@ -1741,13 +1755,13 @@ insieme.
 \label{sec:sig_sigaction}
 
 La funzione principale dell'interfaccia standard POSIX.1 per i segnali è
 \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
+\func{sigaction}, essa ha sostanzialemente lo stesso uso di \func{signal},
+permette cioè di specificare le modalità con cui 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)} 
   
 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}.
+  Installa una nuova azione 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:
   
   \bodydesc{La funzione restituisce zero in caso di successo e -1 per un
     errore, nel qual caso \var{errno} assumerà i valori:
@@ -1762,11 +1776,12 @@ da un processo. Il suo prototipo 
 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
 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.
+le varie caratteristiche della risposta al segnale, non solo la funzione che
+verrà eseguita alla sua occorrenza.  Per questo lo standard raccomanda di
+usare sempre questa funzione al posto di \func{signal} (che in genere viene
+definita tramite essa), in quanto permette 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
 
 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
@@ -1813,19 +1828,21 @@ 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
 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. 
+sia specificato con \var{sa\_flag} un comportamento diverso. Quando il
+manipolatore ritorna comunque la maschera dei segnali bloccati (vedi
+\secref{sec:sig_sigmask}) viene ripristinata al valore precedente
+l'invocazione.
 
 L'uso di questo campo permette ad esempio di risolvere il problema residuo
 dell'implementazione di \code{sleep} mostrata in
 
 L'uso di questo campo permette ad esempio di risolvere il problema residuo
 dell'implementazione di \code{sleep} mostrata in
-\secref{fig:sig_sleep_incomplete}: in quel caso infatti se il segnale di
-allarme interrompe un altro manipolatore questo non sarà eseguito
-correttamente, la cosa può essere prevenuta installando quest'ultimo usando
-\var{sa\_mask} per bloccare \macro{SIGALRM} durante la sua esecuzione.
-
-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}. 
+\secref{fig:sig_sleep_incomplete}. In quel caso infatti se il segnale di
+allarme avesse interrotto un altro manipolatore questo non sarebbe stato
+eseguito correttamente; la cosa poteva essere prevenuta installando gli altri
+manipolatori usando \var{sa\_mask} per bloccare \macro{SIGALRM} durante la
+loro esecuzione.  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
 
 \begin{table}[htb]
   \footnotesize
@@ -1857,7 +1874,7 @@ segnali; i valori possibili ed il relativo significato sono riportati in
                            \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
                            \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_xxx}).\\ 
+                           \secref{sec:sig_specific_features}).\\ 
     \hline
   \end{tabular}
   \caption{Valori del campo \var{sa\_flag} della struttura \var{sigaction}.}
     \hline
   \end{tabular}
   \caption{Valori del campo \var{sa\_flag} della struttura \var{sigaction}.}
@@ -1881,18 +1898,54 @@ 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}.
 
 che non si sia vincolati allo standard ISO C, è sempre il caso di evitare
 l'uso di \func{signal} a favore di \func{sigaction}.
 
+Per questo motivo si è provveduto, per mantenere un'interfaccia semplificata
+che abbia le stesse caratteristiche di \func{signal}, a definire una funzione
+equivalente attraverso \func{sigaction}; la funzione è \code{Signal}, e si
+trova definita come \code{inline} nel file \file{wrapper.h} (nei sorgenti
+allegati), riportata in \figref{fig:sig_Signal_code}. La riutilizzeremo spesso
+in seguito. 
 
 
+\begin{figure}[!htb]
+  \footnotesize \centering
+  \begin{minipage}[c]{15cm}
+    \begin{lstlisting}{}
+typedef void SigFunc(int);
+inline SigFunc * Signal(int signo, SigFunc *func) 
+{
+    struct sigaction new_handl, old_handl;
+    new_handl.sa_handler=func;
+    /* clear signal mask: no signal blocked during execution of func */
+    if (sigemptyset(&new_handl.sa_mask)!=0){  /* initialize signal set */
+        perror("cannot initializes the signal set to empty"); /* see mess. */
+        exit(1);
+    }
+    new_handl.sa_flags=0;                  /* init to 0 all flags */
+    /* change action for signo signal */
+    if (sigaction(signo,&new_handl,&old_handl)){ 
+        perror("sigaction failed on signal action setting");
+        exit(1);
+    }
+    return (old_handl.sa_handler);
+}
+    \end{lstlisting}
+  \end{minipage} 
+  \normalsize 
+  \caption{Una funzione equivalente a \func{signal} definita attraverso
+    \func{sigaction}.} 
+  \label{fig:sig_Signal_code}
+\end{figure}
 
 
-\subsection{La gestione del blocco dei segnali}
+\subsection{La gestione della \textsl{maschera dei segnali} o 
+  \textit{signal mask}}
 \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 è
 \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 \textsl{maschera dei segnali} (o \textit{signal mask})
-del processo\footnote{nel caso di Linux essa è mantenuta dal campo
-  \var{blocked} della \var{task\_struct} del processo.} cioè l'insieme dei
-segnali la cui consegna è bloccata. Abbiamo accennato in
+fatto specificando la cosiddetta \textsl{maschera dei segnali} (o
+\textit{signal mask}) del processo\footnote{nel caso di Linux essa è mantenuta
+  dal campo \var{blocked} della \var{task\_struct} del processo.} cioè
+l'insieme 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 modificata, durante l'esecuzione di un manipolatore,
 \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 modificata, durante l'esecuzione di un manipolatore,
@@ -1900,7 +1953,7 @@ 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 in
 
 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 in
-questoine la sezione fra il controllo e la eventuale cancellazione del flag
+questione la sezione fra il controllo e la eventuale cancellazione del flag
 che testimoniava l'avvenuta occorrenza del segnale) in modo da essere sicuri
 che essi siano eseguiti senza interruzioni.
 
 che testimoniava l'avvenuta occorrenza del segnale) in modo da essere sicuri
 che essi siano eseguiti senza interruzioni.
 
@@ -1924,9 +1977,9 @@ segnali; il suo prototipo 
 
 La funzione usa l'insieme di segnali dato all'indirizzo \param{set} per
 modificare la maschera dei segnali del processo corrente. La modifica viene
 
 La funzione usa l'insieme di segnali dato all'indirizzo \param{set} per
 modificare la maschera dei segnali del processo corrente. La modifica viene
-effettuta a seconda del valore dell'argomento \param{how}, secondo le modalità
+effettuata a seconda del valore dell'argomento \param{how}, secondo le modalità
 specificate in \tabref{tab:sig_procmask_how}. Qualora si specifichi un valore
 specificate in \tabref{tab:sig_procmask_how}. Qualora si specifichi un valore
-non nullo per \param{oldset} la mashera dei segnali corrente viene salvata a
+non nullo per \param{oldset} la maschera dei segnali corrente viene salvata a
 quell'indirizzo.
 
 \begin{table}[htb]
 quell'indirizzo.
 
 \begin{table}[htb]
@@ -1957,9 +2010,21 @@ critica. La funzione permette di risolvere problemi come quelli mostrati in
 \secref{fig:sig_event_wrong}, proteggendo la sezione fra il controllo del flag
 e la sua cancellazione. 
 
 \secref{fig:sig_event_wrong}, proteggendo la sezione fra il controllo del flag
 e la sua cancellazione. 
 
-Un altro problema che abbiamo visto presentarsi con l'uso di \func{pause} è
-quello relativo 
-
+La funzione può essere usata anche all'interno di un manipolatore, ad esempio
+per riabilitare la consegna del segnale che l'ha invocato, in questo caso però
+occorre ricordare che qualunque modifica alla maschera dei segnali viene
+perduta alla conclusione del terminatore. 
+
+Benché con l'uso di \func{sigprocmask} si possano risolvere la maggior parte
+dei casi di race condition restano aperte alcune possibilità legate all'uso di
+\func{pause}; il caso è simile a quello del problema illustrato nell'esempio
+di \secref{fig:sig_sleep_incomplete}, e cioè la possibilità che il processo
+riceva il segnale che si intende usare per uscire dallo stato di attesa
+invocato con \func{pause} immediatamente prima dell'esecuzione di
+quest'ultima. Per poter effettuare atomicamente la modifica della maschera dei
+segnali (di solito attivandone uno specifico) insieme alla sospensione del
+processo lo standard POSIX ha previsto la funzione \func{sigsuspend}, il cui
+prototipo è:
 \begin{prototype}{signal.h}
 {int sigsuspend(const sigset\_t *mask)} 
   
 \begin{prototype}{signal.h}
 {int sigsuspend(const sigset\_t *mask)} 
   
@@ -1973,8 +2038,285 @@ quello relativo
   \end{errlist}}
 \end{prototype}
 
   \end{errlist}}
 \end{prototype}
 
+Come esempio dell'uso di queste funzioni proviamo a riscrivere un'altra volta
+l'esempio di implementazione di \code{sleep}. Abbiamo accennato in
+\secref{sec:sig_sigaction} come con \func{sigaction} sia possibile bloccare
+\macro{SIGALRM} nell'installazione dei manipolatori degli altri segnali, per
+poter usare l'implementazione vista in \secref{fig:sig_sleep_incomplete} senza
+interferenze.  Questo però comporta una precauzione ulteriore al semplice uso
+della funzione, vediamo allora come usando la nuova interfaccia è possibile
+ottenere un'implementazione, riportata in \figref{fig:sig_sleep_ok} che non
+presenta neanche questa necessità.
 
 
+\begin{figure}[!htb]
+  \footnotesize \centering
+  \begin{minipage}[c]{15cm}
+    \begin{lstlisting}{}
+#include <unistd.h>      /* unix standard library */
+#include <signal.h>      /* POSIX signal library */
+void alarm_hand(int);
+unsigned int sleep(unsigned int seconds)
+{
+/* 
+ * Variables definition  
+ */
+    struct sigaction new_action, old_action;
+    sigset_t old_mask, stop_mask, sleep_mask;
+    /* set the signal handler */
+    sigemptyset(&new_action.sa_mask);              /* no signal blocked */
+    new_action.sa_handler = alarm_hand;            /* set handler */
+    new_action.sa_flags = 0;                       /* no flags */
+    sigaction(SIGALRM, &new_action, &old_action);  /* install action */
+    /* block SIGALRM to avoid race conditions */
+    sigemptyset(&stop_mask);                       /* init mask to empty */
+    sigaddset(&stop_mask, SIGALRM);                /* add SIGALRM */
+    sigprocmask(SIG_BLOCK, &stop_mask, &old_mask); /* add SIGALRM to blocked */
+    /* send the alarm */
+    alarm(seconds); 
+    /* going to sleep enabling SIGALRM */
+    sleep_mask = old_mask;                         /* take mask */
+    sigdelset(&sleep_mask, SIGALRM);               /* remove SIGALRM */
+    sigsuspend(&sleep_mask);                       /* go to sleep */
+    /* restore previous settings */
+    sigprocmask(SIG_SETMASK, &old_mask, NULL);     /* reset signal mask */    
+    sigaction(SIGALRM, &old_action, NULL);         /* reset signal action */
+    /* return remaining time */
+    return alarm(0);
+}
+/*
+ * Signal Handler for SIGALRM
+ */
+void alarm_hand(int sig) 
+{
+    return;     /* just return to interrupt sigsuspend */
+}
+    \end{lstlisting}
+  \end{minipage} 
+  \normalsize 
+  \caption{Una implementazione completa di \func{sleep}.} 
+  \label{fig:sig_sleep_ok}
+\end{figure}
+
+Per evitare i problemi di interferenza con gli altri segnali in questo caso
+non si è usato l'approccio di \figref{fig:sig_sleep_incomplete} evitando l'uso
+di \func{longjmp}. Come in precedenza il manipolatore (\texttt{\small 35-37})
+non esegue nessuna operazione, limitandosi a ritornare per interrompere il
+programma messo in attesa.
+
+La prima parte della funzione (\texttt{\small 11-15}) provvede ad installare
+l'opportuno manipolatore per \macro{SIGALRM}, salvando quello originario, che
+sarà ripristinato alla conclusione della stessa (\texttt{\small 28}); il passo
+successivo è quello di bloccare \macro{SIGALRM} (\texttt{\small 17-19}) per
+evitare che esso possa essere ricevuto dal processo fra l'esecuzione di
+\func{alarm} (\texttt{\small 21}) e la sospensione dello stesso. Nel fare
+questo si salva la maschera corrente dei segnali, che sarà ripristinata alla
+fine (\texttt{\small 27}), e al contempo si prepara la maschera dei segnali
+\var{sleep\_mask} per riattivare \macro{SIGALRM} all'esecuzione di
+\func{sigsuspend}.  
+
+In questo modo non sono più possibili race condition dato che \macro{SIGALRM}
+viene disabilitato con \func{sigprocmask} fino alla chiamata di
+\func{sigsuspend}. Questo metodo è assolutamente generale e può essere
+applicato a qualunque altra situazione in cui si deve attendere per un
+segnale, i passi sono sempre i seguenti:
+\begin{enumerate}
+\item Leggere la maschera dei segnali corrente e bloccare il segnale voluto
+  con \func{sigprocmask}. 
+\item Mandare il processo in attesa con \func{sigsuspend} abilitando la
+  ricezione del segnale voluto.
+\item Ripristinare la maschera dei segnali originaria.
+\end{enumerate}
+Per quanto possa sembrare strano bloccare la ricezione di un segnale per poi
+riabilitarla immediatamente dopo, in questo modo si evita il deadlock dovuto
+all'arrivo del segnale prima dell'esecuzione di \func{sigsuspend}.
+
+
+\subsection{Ulteriori funzioni di gestione}
+\label{sec:sig_specific_features}
+
+In questa ultimo paragrafo esamineremo varie funzioni di gestione dei segnali
+non descritte finora, relative agli aspetti meno utilizzati. La prima di esse
+è \func{sigpending},  anch'essa introdotta dallo standard POSIX.1; il suo
+prototipo è:
+\begin{prototype}{signal.h}
+{int sigpending(sigset\_t *set)} 
+  
+Scrive in \param{set} l'insieme dei segnali pendenti.
+  
+  \bodydesc{La funzione restituisce zero in caso di successo e -1 per un
+    errore.}
+\end{prototype}
 
 
+La funzione permette di ricavare quali sono i segnali pendenti per il processo
+in corso, cioè i segnali che sono stato inviati dal kernel ma non sono stati
+ancora ricevuti dal processo in quanto bloccati. Non esiste una funzione
+equivalente nella vecchia interfaccia, ma essa è tutto sommato poco utile,
+dato che essa può solo assicurare che un segnale è stato inviato, dato che
+escluderne l'avvenuto invio al momento della chiamata non significa nulla
+rispetto a quanto potrebbe essere in un qualunque momento successivo.
+
+Una delle caratteristiche di BSD, disponibile anche in Linux, è la possibilità
+di usare uno stack alternativo per i segnali; è cioè possibile fare usare al
+sistema un altro stack (invece di quello relativo al processo, vedi
+\secref{sec:proc_mem_layout}) solo durante l'esecuzione di un
+manipolatore. L'uso di uno stack alternativo è del tutto trasparente ai
+manipolatori, occorre però seguire una certa procedura:
+\begin{enumerate}
+\item Allocare un'area di memoria di dimensione sufficiente da usare come
+  stack alternativo.
+\item Usare la funzione \func{sigaltstack} per rendere noto al sistema
+  l'esistenza e la locazione dello stack alternativo.
+\item Quando si installa un manipolatore occorre usare \func{sigaction}
+  specificando il flag \macro{SA\_ONSTACK} (vedi \tabref{tab:sig_sa_flag}) per
+  dire al sistema di usare lo stack alternativo durante l'esecuzione del
+  manipolatore. 
+\end{enumerate}
+
+In genere il primo passo viene effettuato allocando un'opportuna area di
+memoria con \code{malloc}; in \file{signal.h} sono definite due costanti,
+\macro{SIGSTKSZ} e \macro{MINSIGSTKSZ}, che possono essere utilizzate per
+allocare una quantità di spazio opportuna, in modo da evitare overflow. La
+prima delle due è la dimensione canonica per uno stack di segnali e di norma è
+sufficiente per tutti gli usi normali. La seconda è lo spazio che occorre al
+sistema per essere in grado di lanciare il manipolatore e la dimensione di uno
+stack alternativo deve essere sempre maggiore di questo valore. Quando si
+conosce esattamente quanto è lo spazio necessario al manipolatore gli si può
+aggiungere questo valore per allocare uno stack di dimensione sufficiente.
+
+Come accennato per poter essere usato lo stack per i segnali deve essere
+indicato al sistema attraverso la funzione \func{sigaltstack}; il suo
+prototipo è:
+\begin{prototype}{signal.h}
+{int sigaltstack(const stack\_t *ss, stack\_t *oss)}
+  
+Installa un nuovo stack per i segnali.
+  
+  \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{ENOMEM}] La dimensione specificata per il nuovo stack è minore
+  di \macro{MINSIGSTKSZ}.
+  \item[\macro{EPERM}] Uno degli indirizzi non è valido.
+  \item[\macro{EFAULT}] Si è cercato di cambiare lo stack alternativo mentre
+  questo è attivo (cioè il processo è in esecuzione su di esso).
+  \item[\macro{EINVAL}] \param{ss} non è nullo e \var{ss\_flags} contiene un
+  valore diverso da zero che non è \macro{SS\_DISABLE}.
+  \end{errlist}}
+\end{prototype}
+
+La funzione prende come argomenti puntatori ad una struttura di tipo
+\var{stack\_t}, definita in \figref{fig:sig_stack_t}. I due valori \param{ss}
+e \param{oss}, se non nulli, indicano rispettivamente il nuovo stack da
+installare e quello corrente (che viene restituito dalla funzione per un
+successivo ripristino).
+
+\begin{figure}[!htb]
+  \footnotesize \centering
+  \begin{minipage}[c]{15cm}
+    \begin{lstlisting}[labelstep=0]{}%,frame=,indent=1cm]{}
+typedef struct {
+    void  *ss_sp;     /* Base address of stack */
+    int    ss_flags;  /* Flags */
+    size_t ss_size;   /* Number of bytes in stack */
+} stack_t;
+    \end{lstlisting}
+  \end{minipage} 
+  \normalsize 
+  \caption{La struttura \var{stack\_t}.} 
+  \label{fig:sig_stack_t}
+\end{figure}
+
+Il campo \var{ss\_sp} di \var{stack\_t} indica l'indirizzo base dello stack,
+mentre \var{ss\_size} ne indica la dimensione; il campo \var{ss\_flags} invece
+indica lo stato dello stack. Nell'indicare un nuovo stack occorre
+inizializzare \var{ss\_sp} e \var{ss\_size} rispettivamente al puntatore e
+alla dimensione della memoria allocata, mentre \var{ss\_flags} deve essere
+nullo.  Se invece si vuole disabilitare uno stack occorre indicare
+\macro{SS\_DISABLE} come valore di \var{ss\_flags} e gli altri valori saranno
+ignorati.
+
+Se \param{oss} non è nullo verrà restituito dalla funzione indirizzo e
+dimensione dello stack corrente nei relativi campi, mentre \var{ss\_flags}
+potrà assumere il valore \macro{SS\_ONSTACK} se il processo è in esecuzione
+sullo stack alternativo (nel qual caso non è possibile cambiarlo) e
+\macro{SS\_DISABLE} se questo non è abilitato.
+
+In genere si installa uno stack alternativo per i segnali quando si teme di
+avere problemi di esaurimento dello stack standard o di superamento di un
+limite imposto con chiamata de tipo \code{setrlimit(RLIMIT\_STACK, \&rlim)}.
+In tal caso infatti si avrebbe un segnale di \macro{SIGSEGV}, che potrebbe
+essere gestito soltanto avendo abilitato uno stack alternativo. 
+
+Si tenga presente che le funzioni chiamate durante l'esecuzione sullo stack
+alternativo continueranno ad usare quest'ultimo, che, al contrario di quanto
+avviene per lo stack ordinario dei processi, non si accresce automaticamente
+(ed infatti eccederne le dimensioni può portare a conseguenze imprevedibili).
+Si ricordi infine che una chiamata ad una funzione della famiglia
+\func{exec} cancella ogni stack alternativo.
+
+Abbiamo visto in \secref{fig:sig_sleep_incomplete} come si possa usare
+\func{longjmp} per uscire da un manipolatore rientrando direttamente nel corpo
+del programma; sappiamo però che nell'esecuzione di un manipolatore il segnale
+che l'ha invocato viene bloccato, e abbiamo detto che possiamo ulteriormente
+modificarlo con \func{sigprocmask}. 
+
+Resta quindi il problema di cosa succede alla maschera dei segnali quando si
+esce da un manipolatore usando questa funzione. Il comportamento dipende
+dall'implementazione; in particolare BSD ripristina la maschera dei segnali
+precedente l'invocazione, come per un normale ritorno, mentre System V no. Lo
+standard POSIX.1 non specifica questo comportamento per \func{setjmp} e
+\func{longjmp}, ed il comportamento delle \acr{glibc} dipende da quale delle
+caratteristiche si sono abilitate con le macro viste in
+\secref{sec:intro_gcc_glibc_std}.
+
+Lo standard POSIX però prevede anche la presenza di altre due funzioni
+\func{sigsetjmp} e \func{siglongjmp}, che permettono di decidere quale dei due
+comportamenti il programma deve assumere; i loro prototipi sono:
+\begin{functions}
+  \headdecl{setjmp.h} 
+  
+  \funcdecl{int sigsetjmp(sigjmp\_buf env, int savesigs)} Salva il contesto
+  dello stack per un salto non locale.
+  \funcdecl{void siglongjmp(sigjmp\_buf env, int val)} Esegue un salto non
+  locale su un precedente contesto.
+
+  \bodydesc{Le due funzioni sono identiche alle analoghe \func{setjmp} e
+    \func{longjmp} di \secref{sec:proc_longjmp}, ma consentono di specificare
+    il comportamento sul ripristino o meno della maschera dei segnali.}
+\end{functions}
+
+Le due funzioni prendono come primo argomento la variabile su cui viene
+salvato il contesto dello stack per permettere il salto non locale; nel caso
+specifico essa è di tipo \type{sigjmp\_buf}, e non \type{jmp\_buf} come per le
+analoghe di \secref{sec:proc_longjmp} in quanto in questo caso viene salvata
+anche la maschera dei segnali.
+
+Nel caso di \func{sigsetjmp} se si specifica un valore di \param{savesigs}
+diverso da zero la maschera dei valori sarà salvata in \param{env} e
+ripristinata in un successivo \func{siglongjmp}; quest'ultima funzione, a
+parte l'uso di \type{sigjmp\_buf} per \param{env}, è assolutamente identica a
+\func{longjmp}.
+
+\begin{prototype}{signal.h}
+{int sigaltstack(const stack\_t *ss, stack\_t *oss)}
+  
+Installa un nuovo stack per i segnali.
+  
+  \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{ENOMEM}] La dimensione specificata per il nuovo stack è minore
+  di \macro{MINSIGSTKSZ}.
+  \item[\macro{EPERM}] Uno degli indirizzi non è valido.
+  \item[\macro{EFAULT}] Si è cercato di cambiare lo stack alternativo mentre
+  questo è attivo (cioè il processo è in esecuzione su di esso).
+  \item[\macro{EINVAL}] \param{ss} non è nullo e \var{ss\_flags} contiene un
+  valore diverso da zero che non è \macro{SS\_DISABLE}.
+  \end{errlist}}
+\end{prototype}