Lavoro in treno per webbit
[gapil.git] / signal.tex
index 540f0e27601886fa18d1922c5f0c3da28b3fb45a..246c308c1f36bb0ab62cfe6ca999cdd6fdd5ed10 100644 (file)
@@ -16,7 +16,7 @@ In questo capitolo esamineremo i vari aspetti della gestione dei segnali,
 partendo da una introduzione relativa ai concetti base con cui essi vengono
 realizzati, per poi affrontarne la classificazione a secondo di uso e modalità
 di generazione fino ad esaminare in dettaglio funzioni e le metodologie di
-gestione.
+gestione. 
 
 
 \section{Introduzione}
@@ -662,11 +662,11 @@ segnali sono:
   situazione precedente.
 \item[\macro{SIGXCPU}] Sta per \textit{CPU time limit exceeded}. Questo
   segnale è generato quando un processo eccede il limite impostato per il
-  tempo di CPU disponibile, vedi \secref{sec:sys_xxx}. 
+  tempo di CPU disponibile, vedi \secref{sec:sys_resource_limit}. 
 \item[\macro{SIGXFSZ}] Sta per \textit{File size limit exceeded}. Questo
   segnale è generato quando un processo tenta di estendere un file oltre le
   dimensioni specificate dal limite impostato per le dimensioni massime di un
-  file, vedi \secref{sec:sys_xxx}. 
+  file, vedi \secref{sec:sys_resource_limit}. 
 \end{basedescript}
 
 
@@ -714,7 +714,7 @@ di \func{strsignal}. Nel caso si debba mantenere traccia del messaggio sar
 necessario copiarlo.
 
 La seconda funzione deriva da BSD ed è analoga alla funzione \func{perror}
-descritta in \secref{sec:sys_strerror}; il suo prototipo è:
+descritta sempre in \secref{sec:sys_strerror}; il suo prototipo è:
 \begin{prototype}{signal.h}{void psignal(int sig, const char *s)} 
   Stampa sullo standard error un messaggio costituito dalla stringa \param{s},
   seguita da due punti ed una descrizione del segnale indicato da \param{sig}.
@@ -750,7 +750,7 @@ processo alla loro occorrenza.
 
 
 \subsection{Il comportamento generale del sistema.}
-  \label{sec:sig_gen_beha}
+\label{sec:sig_gen_beha}
 
 Abbiamo già trattato in \secref{sec:sig_intro} le modalità con cui il sistema
 gestisce l'interazione fra segnali e processi, ci resta da esaminare però il
@@ -778,28 +778,29 @@ manipolatore; viene mantenuto invece ogni eventuale settaggio dell'azione a
 programmi eseguiti in background, che altrimenti sarebbero interrotti da una
 successiva pressione di \texttt{C-c} o \texttt{C-y}.
 
-Per quanto riguarda tutte le altre system call esse vengono tradizionalmente
-classificate, proprio in base al loro comportamento nei confronti dei segnali,
-in \textsl{lente} (\textit{slow}) e \textsl{veloci} (\textit{fast}). La gran
-parte appartiene a quest'ultima categoria che non è influenzata dall'arrivo di
-un segnale. In tal caso un eventuale manipolatore viene sempre eseguito dopo
-che la system call è stata completata. Esse sono dette \textsl{veloci} proprio
-in quanto la loro esecuzione è sostanzialmente immediata e attendere per
-eseguire un manipolatore non comporta nessun inconveniente.
-
-Esistono però dei casi in cui questo non è possibile perché renderebbe
-impossibile una risposta pronta al segnale. In generale questo avviene tutte
-le volte che si ha a che fare con system call che possono bloccarsi
-indefinitamente, (quelle che, per questo, vengono chiamate \textsl{lente}). Un
-elenco dei casi in cui si presenta questa situazione è il seguente:
+Per quanto riguarda il comportamento di tutte le altre system call si danno
+sostanzialmente due casi, a seconda che esse siano \textsl{lente}
+(\textit{slow}) o \textsl{veloci} (\textit{fast}). La gran parte di esse
+appartiene a quest'ultima categoria, che non è influenzata dall'arrivo di un
+segnale. Esse sono dette \textsl{veloci} in quanto la loro esecuzione è
+sostanzialmente immediata; la risposta al segnale viene sempre data dopo che
+la system call è stata completata, in quanto attendere per eseguire un
+manipolatore non comporta nessun inconveniente.
+
+In alcuni casi però alcune system call (che per questo motivo vengono chiamate
+\textsl{lente}) possono bloccarsi indefinitamente. In questo caso non si può
+attendere la conclusione della sistem call, perché questo renderebbe
+impossibile una risposta pronta al segnale, per cui il manipolatore viene
+eseguito prima che la system call sia ritornata.  Un elenco dei casi in cui si
+presenta questa situazione è il seguente:
 \begin{itemize}
-\item lettura da file che possono bloccarsi in attesa di dati non ancora
-  presenti (come per certi file di dispositivo, la rete o le pipe).
-\item scrittura sugli stessi file, nel caso in cui dati non possano essere
+\item la lettura da file che possono bloccarsi in attesa di dati non ancora
+  presenti (come per certi file di dispositivo, i socket o le pipe).
+\item la scrittura sugli stessi file, nel caso in cui dati non possano essere
   accettati immediatamente.
-\item apertura di un file di dispositivo che richiede operazioni non immediate
-  per una una risposta. 
-\item operazioni eseguite con \func{ioctl} che non è detto possano essere
+\item l'apertura di un file di dispositivo che richiede operazioni non
+  immediate per una una risposta.
+\item le operazioni eseguite con \func{ioctl} che non è detto possano essere
   eseguite immediatamente.
 \item le funzioni di intercomunicazione che si bloccano in attesa di risposte
   da altri processi.
@@ -1141,12 +1142,6 @@ struct itimerval
     struct timeval it_interval; /* next value */
     struct timeval it_value;    /* current value */
 };
-
-struct timeval 
-{
-    long tv_sec;                /* seconds */
-    long tv_usec;               /* microseconds */
-};
     \end{lstlisting}
   \end{minipage} 
   \normalsize 
@@ -1336,9 +1331,9 @@ Lo standard richiede che la funzione sia implementata in maniera del tutto
 indipendente da \func{alarm}\footnote{nel caso di Linux questo è fatto
   utilizzando direttamente il timer del kernel.} e sia utilizzabile senza
 interferenze con l'uso di \macro{SIGALRM}. La funzione prende come parametri
-delle strutture di tipo \var{timespec}, la cui definizione è riportata in 
-\figref{fig:sig_timespec_def}, che permettono di specificare un tempo con una
-precisione (teorica) fino al nanosecondo. 
+delle strutture di tipo \var{timespec}, la cui definizione è riportata in
+\figref{fig:sys_timeval_struct}, che permettono di specificare un tempo con
+una precisione (teorica) fino al nanosecondo.
 
 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
@@ -1355,21 +1350,6 @@ 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}.
 
-\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
@@ -1421,7 +1401,7 @@ la creazione di zombie.
 #include <sys/wait.h>
 #include "macro.h"
 
-void Hand_CHLD(int sig)
+void sigchld_hand(int sig)
 {
     int errno_save;
     int status;
@@ -1513,43 +1493,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
-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}{}
+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)
 {
-    signandler_t prev_handler;
+    sighandler_t prev_handler;
+    /* install and check new handler */
     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);
-    /* remove alarm, return remaining time */
+    /* return remaining time */
     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 
@@ -1814,32 +1795,24 @@ struct 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. 
+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
-\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
@@ -1871,13 +1844,75 @@ 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
-                           \secref{sec:sig_xxx}).\\ 
+                           \secref{sec:sig_specific_features}).\\ 
     \hline
   \end{tabular}
   \caption{Valori del campo \var{sa\_flag} della struttura \var{sigaction}.}
   \label{tab:sig_sa_flag}
 \end{table}
 
+Come si può notare in \figref{fig:sig_sigaction} \func{sigaction}
+permette\footnote{La possibilità è prevista dallo standard POSIX.1b, ma in
+  Linux è stata aggiunta a partire dai kernel della serie 2.2.x. In precedenza
+  era possibile ottenere alcune informazioni addizionali usando
+  \var{sa\_handler} con un secondo parametro addizionale di tipo \var{struct
+    sigcontext}, che adesso è deprecato.}  di utilizzare due forme diverse di
+manipolatore, da specificare, a seconda dell'uso o meno del flag
+\macro{SA\_SIGINFO}, rispettivamente attraverso i campi \var{sa\_sigaction} o
+\var{sa\_handler}, (che devono essere usati in maniera alternativa, in certe
+implementazioni questi vengono addirittura definiti 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, attraverso la struttura \var{siginfo\_t}, riportata
+in \figref{fig:sig_siginfo_t}.
+
+\begin{figure}[!htb]
+  \footnotesize \centering
+  \begin{minipage}[c]{15cm}
+    \begin{lstlisting}[labelstep=0]{}%,frame=,indent=1cm]{}
+siginfo_t {
+    int      si_signo;  /* Signal number */
+    int      si_errno;  /* An errno value */
+    int      si_code;   /* Signal code */
+    pid_t    si_pid;    /* Sending process ID */
+    uid_t    si_uid;    /* Real user ID of sending process */
+    int      si_status; /* Exit value or signal */
+    clock_t  si_utime;  /* User time consumed */
+    clock_t  si_stime;  /* System time consumed */
+    sigval_t si_value;  /* Signal value */
+    int      si_int;    /* POSIX.1b signal */
+    void *   si_ptr;    /* POSIX.1b signal */
+    void *   si_addr;   /* Memory location which caused fault */
+    int      si_band;   /* Band event */
+    int      si_fd;     /* File descriptor */
+}
+    \end{lstlisting}
+  \end{minipage} 
+  \normalsize 
+  \caption{La struttura \var{siginfo\_t}.} 
+  \label{fig:sig_siginfo_t}
+\end{figure}
+Installando un manipolatore di tipo \var{sa\_sigaction} diventa allora
+possibile accedere alle informazioni restituite attraverso il puntatore a
+questa struttura. Tutti i segnali settano i campi \var{si\_signo}, che riporta
+il segnale ricevuto, \var{si\_errno}, che riporta il codice di errore, e
+\var{si\_code}, che viene usato per indicare la ragione per cui è stato emesso
+il segnale (come i dettagli sul tipo di errore per \macro{SIGFPE} e
+\macro{SIGILL}) ed ha valori diversi\footnote{un elenco dettagliato è
+  disponibile nella man page di \func{sigaction}.} a seconda del tipo di
+segnale ricevuto.
+
+Il resto della struttura può essere definito come \ctyp{union} ed i valori
+eventualmente presenti dipendono dal segnale, così \macro{SIGCHLD} ed i
+segnali POSIX.1b\footnote{NdA trovare quale sono e completare l'informazione.}
+inviati tramite \func{kill} avvalorano \var{si\_pid} e \var{si\_uid} coi
+valori corrispondenti al processo che ha emesso il segnale, \macro{SIGILL},
+\macro{SIGFPE}, \macro{SIGSEGV} e \macro{SIGBUS} avvalorano \var{si\_addr} con
+l'indirizzo cui è avvenuto l'errore, \macro{SIGIO} (vedi
+\secref{sec:file_asyncronous_io}) e \macro{SIGPOLL} avvalorano \var{si\_fd}
+con il numero del file descriptor.
+
 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
@@ -1891,13 +1926,49 @@ Per questo 
 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}.
+che in certi sistemi questi possono essere diversi. In definitiva dunque, a
+meno che non si sia vincolati all'aderenza stretta allo standard ISO C, è
+sempre il caso di evitare l'uso di \func{signal} a favore di \func{sigaction}.
 
+\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}
 
+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. 
 
-\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
@@ -1971,6 +2042,11 @@ 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. 
 
+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
@@ -1981,7 +2057,6 @@ 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)} 
   
@@ -1995,8 +2070,266 @@ prototipo 
   \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}.
 
 
 %%% Local Variables: