Correzione ai limiti, aggiustate referenze e iniziato le funzioni per
[gapil.git] / signal.tex
index be01dc4ec8304c0b992281a202f3c5aa056a6633..f0565a23a2e305ccbfbe3fa04130cad36872efa8 100644 (file)
@@ -19,7 +19,6 @@ di generazione fino ad esaminare in dettaglio funzioni e le metodologie di
 gestione.
 
 
-
 \section{Introduzione}
 \label{sec:sig_intro}
 
@@ -64,17 +63,17 @@ stata specificata dall'utente (nel qual caso si dice che si
 \textsl{intercetta} il segnale).
 
 
-\subsection{Le modalità di funzionamento}
+\subsection{Le \textsl{semantiche} del funzionamento dei segnali}
 \label{sec:sig_semantics}
 
 Negli anni il comportamento del sistema in risposta ai segnali è stato
 modificato in vari modi nelle differenti implementazioni di Unix.  Si possono
 individuare due tipologie fondamentali di comportamento dei segnali (dette
-semantiche) che vengono chiamate rispettivamente semantica \textsl{affidabile}
-(o \textit{reliable}) e semantica \textsl{inaffidabile} (o
+\textsl{semantiche}) che vengono chiamate rispettivamente \textsl{semantica
+  affidabile} (o \textit{reliable}) e \textsl{semantica inaffidabile} (o
 \textit{unreliable}).
 
-Nella semantica \textsl{inaffidabile} (quella implementata dalle prime
+Nella \textsl{semantica inaffidabile} (quella implementata dalle prime
 versioni di Unix) la routine di gestione del segnale specificata dall'utente
 non resta attiva una volta che è stata eseguita; è perciò compito dell'utente
 stesso ripetere l'installazione della stessa all'interno della routine di
@@ -82,27 +81,41 @@ gestione, in tutti i casi in cui si vuole che il manipolatore esterno resti
 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: 
+perduti. Si consideri il segmento di codice riportato in
+\secref{fig:sig_old_handler}, nel programma principale viene installato un
+manipolatore (\texttt{\small 5}), ed in quest'ultimo la prima operazione
+(\texttt{\small 11}) è quella di reinstallare se stesso. Se nell'esecuzione
+del manipolatore un secondo segnale arriva prima che esso abbia potuto
+eseguire la reinstallazione, verrà eseguito il comportamento di default
+assegnato al segnale stesso, il che può comportare, a seconda dei casi, che il
+segnale viene perso (se il default era quello di ignorarlo) o la terminazione
+immediata del processo; in entrambi i casi l'azione prevista non verrà
+eseguita.
 
-\footnotesize
-\begin{lstlisting}[labelstep=0,frame=,indent=1cm]{}
-    int sig_handler();            /* handler function */
+\begin{figure}[!htb]
+  \footnotesize \centering
+  \begin{minipage}[c]{15cm}
+    \begin{lstlisting}{}
+int sig_handler();            /* handler function */
+int main()
+{
     ...
     signal(SIGINT, sig_handler);  /* establish handler */
     ...
+}
 
 int sig_handler() 
 {
     signal(SIGINT, sig_handler);  /* restablish handler */
     ...                           /* process signal */
 }
-\end{lstlisting}
-\normalsize
-se un secondo segnale arriva prima che il manipolatore invocato dal primo
-abbia eseguito la reinstallazione di se stesso il segnale può essere perso o
-causare il comportamento originale assegnato al segnale (in genere la
-terminazione del processo).
+    \end{lstlisting}
+  \end{minipage} 
+  \normalsize 
+  \caption{Esempio di codice di un manipolatore di segnale per la semantica
+    inaffidabile.} 
+  \label{fig:sig_old_handler}
+\end{figure}
 
 Questa è la ragione per cui l'implementazione dei segnali secondo questa
 semantica viene chiamata \textsl{inaffidabile}; infatti la ricezione del
@@ -115,49 +128,6 @@ segnali quando non si vuole che arrivino; i processi possono ignorare il
 segnale, ma non è possibile istruire il sistema a non fare nulla in occasione
 di un segnale, pur mantenendo memoria del fatto che è avvenuto.
 
-% Un caso classico in cui si incontra questo problema, è quello in cui si usa il
-% manipolatore per settare un flag che riporta al processo l'occorrenza del
-% segnale, così che questo possa prendere provvedimenti al di fuori del
-% manipolatore. Si consideri il seguente segmento di codice il cui scopo sarebbe
-% quello di fermare il processo fino all'occorrenza di un opportuno segnale:
-
-% \footnotesize
-% \begin{lstlisting}[labelstep=0,frame=,indent=1cm]{}
-% int signal_flag = 0;
-% main()
-% {
-%     int sig_handler();            /* handler function */
-%     ...
-%     signal(SIGINT, sig_handler);  /* establish handler */
-%     ...
-%     while(signal_flag == 0) {     /* while flag is zero */
-%         pause();                  /* go to sleep */
-%     }
-%     ... 
-% }
-% int sig_handler() 
-% {
-%     signal(SIGINT, sig_handler);  /* restablish handler */
-%     signal_flag = 1;              /* set flag */
-% }
-% \end{lstlisting}
-% \normalsize
-% l'idea è che quando il processo trova il flag a zero viene messo in sleep e
-% verrà risvegliato solo dalla ricezione di un segnale. Il manipolatore si
-% limita in questo caso a settare il flag a uno; all'uscita dal manipolatore la
-% chiamata a \func{pause} è interrotta ed il processo viene risvegliato e
-% riprende l'esecuzione all'istruzione successiva, ma essendo cambiato il flag
-% la condizione non è più soddisfatta e il programma prosegue.
-
-% Il problema con l'implementazione inaffidabile è che niente ci garantisce che
-% il segnale arrivi fra la valutazione della condizione del \code{while} e la
-% chiamata a \func{pause}, nel qual caso, se il segnale non viene più generato,
-% il processo resterà in sleep permanentemente.
-
-% Questo ci mostra ad esempio come con la semantica inaffidabile non esista una
-% modalità semplice per ottenere una operazione di attesa mandando in stato di
-% sleep (vedi \ref{sec:proc_sched}) un processo fino all'arrivo di un segnale.
-
 Nella semantica \textsl{affidabile} (quella utilizzata da Linux e da ogni Unix
 moderno) il manipolatore una volta installato resta attivo e non si hanno
 tutti i problemi precedenti. In questa semantica i segnali vengono
@@ -183,9 +153,8 @@ ignorarlo.
 Si tenga presente che il kernel stabilisce cosa fare con un segnale che è
 stato bloccato al momento della consegna, non quando viene generato; questo
 consente di cambiare l'azione per il segnale prima che esso venga consegnato,
-e si può usare la funzione \func{sigpending} (vedi
-\secref{sec:sig_sigpending}) per determinare quali segnali sono bloccati e
-quali sono pendenti.
+e si può usare la funzione \func{sigpending} (vedi \secref{sec:sig_sigmask})
+per determinare quali segnali sono bloccati e quali sono pendenti.
 
 
 \subsection{Tipi di segnali}
@@ -322,7 +291,6 @@ In \tabref{tab:sig_signal_list} si 
 definiti in Linux (estratto dalle man page), comparati con quelli definiti in
 vari standard.
 
-
 \begin{table}[htb]
   \footnotesize
   \centering
@@ -383,18 +351,19 @@ stato dello stack e delle variabili al momento della ricezione del segnale.
   \centering
   \begin{tabular}[c]{|l|c|c|p{8cm}|}
     \hline
-    \textbf{Segnale}&\textbf{Standard}&\textbf{Azione}&\textbf{Descrizione} \\
+    \textbf{Segnale} &\textbf{Standard}&\textbf{Azione}&\textbf{Descrizione} \\
     \hline
     \hline
-    \macro{SIGHUP}   &PL & A & Hangup o fine del processo di controllo      \\
-    \macro{SIGINT}   &PL & A & Interrupt da tastiera (\cmd{C-c})            \\
-    \macro{SIGQUIT}  &PL & C & Quit da tastiera (\cmd{C-y})                 \\
-    \macro{SIGILL}   &PL & C & Istruzione illegale                          \\
-    \macro{SIGABRT}  &PL & C & Segnale di abort da \func{abort}             \\
-    \macro{SIGFPE}   &PL & C & Errore aritmetico                            \\
-    \macro{SIGKILL}  &PL &AEF& Segnale di terminazione forzata              \\
-    \macro{SIGSEGV}  &PL & C & Errore di accesso in memoria                 \\
-    \macro{SIGPIPE}  &PL & A & Pipe spezzata                                \\
+    \macro{SIGHUP}   &PL & A & Hangup o terminazione del processo di 
+                               controllo                                     \\
+    \macro{SIGINT}   &PL & A & Interrupt da tastiera (\cmd{C-c})             \\
+    \macro{SIGQUIT}  &PL & C & Quit da tastiera (\cmd{C-y})                  \\
+    \macro{SIGILL}   &PL & C & Istruzione illegale                           \\
+    \macro{SIGABRT}  &PL & C & Segnale di abort da \func{abort}              \\
+    \macro{SIGFPE}   &PL & C & Errore aritmetico                             \\
+    \macro{SIGKILL}  &PL &AEF& Segnale di terminazione forzata               \\
+    \macro{SIGSEGV}  &PL & C & Errore di accesso in memoria                  \\
+    \macro{SIGPIPE}  &PL & A & Pipe spezzata                                 \\
     \macro{SIGALRM}  &PL & A & Segnale del timer da \func{alarm}             \\
     \macro{SIGTERM}  &PL & A & Segnale di terminazione \verb|C-\|            \\
     \macro{SIGUSR1}  &PL & A & Segnale utente numero 1                       \\
@@ -402,31 +371,32 @@ stato dello stack e delle variabili al momento della ricezione del segnale.
     \macro{SIGCHLD}  &PL & B & Figlio terminato o fermato                    \\
     \macro{SIGCONT}  &PL &   & Continua se fermato                           \\
     \macro{SIGSTOP}  &PL &DEF& Ferma il processo                             \\
-    \macro{SIGTSTP}  &PL & D & Stop typed at tty                             \\
+    \macro{SIGTSTP}  &PL & D & Pressione del tasto di stop sul terminale     \\
     \macro{SIGTTIN}  &PL & D & Input sul terminale per un processo 
                                in background                                 \\
     \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 & Bad argument to routine (SVID)                \\
-    \macro{SIGTRAP}  &SL & C & Trace/breakpoint trap                         \\
-    \macro{SIGURG}   &SLB& B & Urgent condition on socket                    \\
+    \macro{SIGSYS}   &SL & C & Argomento sbagliato per una subroutine (SVID) \\
+    \macro{SIGTRAP}  &SL & C & Trappole per un Trace/breakpoint              \\
+    \macro{SIGURG}   &SLB& B & Ricezione di una urgent condition su un socket\\
     \macro{SIGVTALRM}&SLB& A & Virtual alarm clock                           \\
     \macro{SIGXCPU}  &SLB& C & Ecceduto il limite sul CPU time               \\
     \macro{SIGXFSZ}  &SLB& C & Ecceduto il limite sulla dimensione dei file  \\
-    \macro{SIGIOT}   &L  & C & IOT trap. A synonym for \macro{SIGABRT}       \\
+    \macro{SIGIOT}   &L  & C & IOT trap. Sinonimo di \macro{SIGABRT}         \\
     \macro{SIGEMT}   &L  &   &                                               \\
-    \macro{SIGSTKFLT}&L  & A & Stack fault on coprocessor                    \\
-    \macro{SIGIO}    &LB & A & I/O now possible (4.2 BSD)                    \\
-    \macro{SIGCLD}   &L  &   & A synonym for \macro{SIGCHLD}                 \\
+    \macro{SIGSTKFLT}&L  & A & Errore sullo stack del coprocessore           \\
+    \macro{SIGIO}    &LB & A & L'I/O è possibile (4.2 BSD)                   \\
+    \macro{SIGCLD}   &L  &   & Sinonimo di \macro{SIGCHLD}                   \\
     \macro{SIGPWR}   &L  & A & Fallimento dell'alimentazione                 \\
-    \macro{SIGINFO}  &L  &   & A synonym for \macro{SIGPWR}                  \\
+    \macro{SIGINFO}  &L  &   & Sinonimo di \macro{SIGPWR}                    \\
     \macro{SIGLOST}  &L  & A & Perso un lock sul file (per NFS)              \\
-    \macro{SIGWINCH} &LB & B & Window resize signal (4.3 BSD, Sun)           \\
-    \macro{SIGUNUSED}&L  & A & Unused signal (will be SIGSYS)                \\
+    \macro{SIGWINCH} &LB & B & Finestra ridimensionata (4.3 BSD, Sun)        \\
+    \macro{SIGUNUSED}&L  & A & Segnale inutilizzato (diventerà 
+                               \macro{SIGSYS})                               \\
     \hline
   \end{tabular}
   \caption{Lista dei segnali in Linux.}
@@ -434,7 +404,7 @@ stato dello stack e delle variabili al momento della ricezione del segnale.
 \end{table}
 
 La descrizione dettagliata del significato dei vari segnali, raggruppati per
-tipologia, verrà affrontate nel seguito.
+tipologia, verrà affrontate nei paragrafi successivi.
 
 
 \subsection{Segnali di errore di programma}
@@ -469,7 +439,7 @@ Questi segnali sono:
   aritmetici compresa la divisione per zero e l'overflow. 
   
   Se il manipolatore ritorna il comportamento del processo è indefinito, ed
-  ignorare questo segnale può condurre ad un loop infinito.
+  ignorare questo segnale può condurre ad un ciclo infinito.
 
 %   Per questo segnale le cose sono complicate dal fatto che possono esserci
 %   molte diverse eccezioni che \texttt{SIGFPE} non distingue, mentre lo
@@ -595,8 +565,8 @@ sempre la necessit
 \item[\macro{SIGPROF}] Il nome sta per \textit{profiling}. Indica la scadenza
   di un timer che misura sia il tempo di CPU speso direttamente dal processo
   che quello che il sistema ha speso per conto di quest'ultimo. In genere
-  viene usato dai tool che servono a fare il profilo d'uso della CPU da parte
-  del processo.
+  viene usato dagli strumenti che servono a fare la profilazione dell'utilizzo
+  del tempo di CPU da parte del processo.
 \end{basedescript}
 
 
@@ -706,13 +676,14 @@ segnali sono:
 Raccogliamo qui infine usa serie di segnali che hanno scopi differenti non
 classificabili in maniera omogenea. Questi segnali sono:
 \begin{basedescript}{\desclabelwidth{2.0cm}}
-\item[\macro{SIGUSR1} e \macro{SIGUSR2}] Sono due segnali a disposizione
+\item[\macro{SIGUSR1}] Vedi \macro{SIGUSR2}.
+\item[\macro{SIGUSR2}] Insieme a \macro{SIGUSR1} è un segnale a disposizione
   dell'utente che li può usare per quello che vuole. Possono essere utili per
   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.
@@ -788,12 +759,11 @@ comportamento delle system call; in particolare due di esse, \func{fork} ed
 loro stretta relazione con la creazione di nuovi processi.
 
 Come accennato in \secref{sec:proc_fork} quando viene creato un nuovo processo
-con \func{fork} esso eredita dal padre sia le azioni che sono state settate
-per i singoli segnali, che la maschera dei segnali bloccati (tratteremo
-quest'ultimo argomento in \ref{sec:sig_sigpending}). Invece tutti i segnali
-pendenti e gli allarmi vengono cancellati; essi infatti devono essere
-recapitati solo al padre, al figlio dovranno arrivare solo i segnali dovuti
-alle sue azioni.
+esso eredita dal padre sia le azioni che sono state settate per i singoli
+segnali, che la maschera dei segnali bloccati (vedi \secref{sec:sig_sigmask}).
+Invece tutti i segnali pendenti e gli allarmi vengono cancellati; essi infatti
+devono essere recapitati solo al padre, al figlio dovranno arrivare solo i
+segnali dovuti alle sue azioni.
 
 Quando si mette in esecuzione un nuovo programma con \func{exec} (si ricordi
 quanto detto in \secref{sec:proc_exec}) tutti i segnali per i quali è stato
@@ -822,7 +792,7 @@ 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:
-\begin{itemize*}
+\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
@@ -833,10 +803,10 @@ elenco dei casi in cui si presenta questa situazione 
   eseguite immediatamente.
 \item le funzioni di intercomunicazione che si bloccano in attesa di risposte
   da altri processi.
-\item la funzione \func{pause} (usata appunto per attendere l'-arrivo di un
+\item la funzione \func{pause} (usata appunto per attendere l'arrivo di un
   segnale).
 \item la funzione \func{wait} (se nessun processo figlio è ancora terminato).
-\end{itemize*}
+\end{itemize}
 
 In questo caso si pone il problema di cosa fare una volta che il manipolatore
 sia ritornato. La scelta originaria dei primi Unix era quella di far ritornare
@@ -872,9 +842,11 @@ funzione \func{signal} che 
 però non considera sistemi multitasking, per cui la definizione è tanto vaga
 da essere del tutto inutile in un sistema Unix; è questo il motivo per cui
 ogni implementazione successiva ne ha modificato e ridefinito il
-comportamento, pur mantenendone immutato il prototipo\footnote{in realtà
-  alcune vecchie implementazioni (SVR4 e 4.3+BSD) usano parametri aggiuntivi
-  per definire il comportamento della funzione.} che è:
+comportamento, pur mantenendone immutato il prototipo\footnote{in realtà in
+  alcune vecchie implementazioni (SVr4 e 4.3+BSD in particolare) vengono usati
+  alcuni parametri aggiuntivi per definire il comportamento della funzione,
+  vedremo in \secref{sec:sig_sigaction} che questo è possibile usando la
+  funzione \func{sigaction}.}  che è:
 \begin{prototype}{signal.h}
   {sighandler\_t signal(int signum, sighandler\_t handler)} 
   
@@ -885,11 +857,13 @@ comportamento, pur mantenendone immutato il prototipo\footnote{in realt
     o \macro{SIG\_ERR} in caso di errore.}
 \end{prototype}
 
-In questa definizione si è usato il tipo \type{sighandler\_t} che è una
-estensione GNU, definita dalle \acr{glibc}, che permette di riscrivere il
-prototipo in una forma più leggibile dell'originario:
+In questa definizione si è usato un tipo di dato, \type{sighandler\_t}, che è
+una estensione GNU, definita dalle \acr{glibc}, esso permette di riscrivere il
+prototipo di \func{signal} nella forma appena vista, che risulta molto più
+leggibile di quanto non sia la versione originaria che di norma è definita
+come:
 \begin{verbatim}
-void (*signal(int signum, void (*handler)(int)))int)
+    void (*signal(int signum, void (*handler)(int)))int)
 \end{verbatim}
 questa infatti, per la poca chiarezza della sintassi del C quando si vanno a
 trattare puntatori a funzioni, è molto meno comprensibile.  Da un confronto
@@ -898,11 +872,11 @@ con il precedente prototipo si pu
 \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
-  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.
@@ -929,11 +903,11 @@ primi Unix in cui il manipolatore viene disinstallato alla sua chiamata,
 secondo la semantica inaffidabile; Linux seguiva questa convenzione fino alle
 \acr{libc5}. Al contrario BSD segue la semantica affidabile, non resettando il
 manipolatore e bloccando il segnale durante l'esecuzione dello stesso. Con
-l'utilizzo delle \acr{glibc2} anche Linux è passato a questo comportamento;
-quello della versione originale della funzione, il cui uso è deprecato per i
-motivi visti in \secref{sec:sig_semantics}, può essere ottenuto chiamando
-\func{sysv\_signal}.  In generale, per evitare questi problemi, tutti i nuovi
-programmi dovrebbero usare \func{sigaction}.
+l'utilizzo delle \acr{glibc} dalla versione 2 anche Linux è passato a questo
+comportamento; quello della versione originale della funzione, il cui uso è
+deprecato per i motivi visti in \secref{sec:sig_semantics}, può essere
+ottenuto chiamando \func{sysv\_signal}.  In generale, per evitare questi
+problemi, tutti i nuovi programmi dovrebbero usare \func{sigaction}.
 
 È da tenere presente che, seguendo lo standard POSIX, il comportamento di un
 processo che ignora i segnali \macro{SIGFPE}, \macro{SIGILL}, o
@@ -966,43 +940,37 @@ manipolatore potr
 \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}.
-
-  \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}
 
-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]
+  \footnotesize
   \centering
   \begin{tabular}[c]{|r|l|}
     \hline
@@ -1022,6 +990,23 @@ riportati in \tabref{tab:sig_kill_values}.
   \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.
+
+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}
@@ -1045,37 +1030,41 @@ 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
-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{SIGABRT}, 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.
+  Predispone l'invio di \macro{SIGALRM} dopo \param{seconds} secondi.
   
   \bodydesc{La funzione restituisce il numero di secondi rimanenti ad un
     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
-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{SIGALRM}) 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,
-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
-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
   corrisponde al \textit{clock time}). La scadenza di questo timer provoca
-  l'emissione di \macro{SIGALARM}.
+  l'emissione di \macro{SIGALRM}.
 \item un \textit{virtual timer} che calcola il tempo di processore usato dal
   processo in user space (che corrisponde all'\textit{user time}). La scadenza
   di questo timer provoca l'emissione di \macro{SIGVTALRM}.
@@ -1111,6 +1100,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]
+  \footnotesize
   \centering
   \begin{tabular}[c]{|l|l|}
     \hline
@@ -1130,7 +1120,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
-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
@@ -1138,18 +1128,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
-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{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 {
+
+struct timeval 
+{
     long tv_sec;                /* seconds */
     long tv_usec;               /* microseconds */
 };
@@ -1165,12 +1159,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}
-\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{lstlisting}[labelstep=0,frame=,indent=1cm]{}
+    \begin{lstlisting}[labelstep=0]{}%,frame=,indent=1cm]{}
 unsigned int alarm(unsigned int seconds)
 {
     struct itimerval old, new;
@@ -1178,10 +1173,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;
-    if (setitimer(ITIMER_REAL, &new, &old) < 0)
+    if (setitimer(ITIMER_REAL, &new, &old) < 0) {
         return 0;
-    else
+    }
+    else {
         return old.it_value.tv_sec;
+    }
 }
     \end{lstlisting}
   \end{minipage} 
@@ -1191,13 +1188,23 @@ unsigned int alarm(unsigned int seconds)
 \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
@@ -1244,7 +1251,7 @@ eventuali funzioni registrate con \func{at\_exit} e \func{on\_exit}.
 \label{sec:sig_pause_sleep}
 
 Il metodo tradizionale per fare attendere\footnote{cioè di porre
-  temporanemente il processo in stato di \textit{sleep}, vedi
+  temporaneamente il processo in stato di \textit{sleep}, vedi
   \ref{sec:proc_sched}.}  ad un processo fino all'arrivo di un segnale è
 quello di usare la funzione \func{pause}, il cui prototipo è:
 \begin{prototype}{unistd.h}{int pause(void)}
@@ -1333,22 +1340,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. 
 
-\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
@@ -1364,6 +1355,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}.
 
+\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
@@ -1378,7 +1384,7 @@ Un semplice esempio per illustrare il funzionamento di un manipolatore di
 segnale è quello della gestione di \macro{SIGCHLD}. Abbiamo visto in
 \secref{sec:proc_termination} che una delle azioni eseguite dal kernel alla
 conclusione di un processo è quella di inviare questo segnale al
-padre.\footnote{in realtà in SRV4 eredita la semantica di System V, in cui il
+padre.\footnote{in realtà in SVr4 eredita la semantica di System V, in cui il
   segnale si chiama \macro{SIGCLD} e viene trattato in maniera speciale; in
   System V infatti se si setta esplicitamente l'azione a \macro{SIG\_IGN} il
   segnale non viene generato ed il sistema non genera zombie (lo stato di
@@ -1394,7 +1400,7 @@ zombie.
 
 In \figref{fig:sig_sigchld_handl} è mostrato il codice della nostra
 implementazione del manipolatore; se aggiungiamo al codice di
-\file{ForkTest.c} l'intallazione di questo manipolatore potremo verificare che
+\file{ForkTest.c} l'installazione di questo manipolatore potremo verificare che
 ripetendo l'esempio visto in \secref{sec:proc_termination} che non si ha più
 la creazione di zombie.
 
@@ -1409,7 +1415,7 @@ la creazione di zombie.
   \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>
@@ -1467,8 +1473,8 @@ 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.
 
-Allora nel caso della terminazione dei processi figli, se si chiamasse
-\func{waitpid} una sola volta, essa leggerebbe lo stato di teminazione per un
+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.
 
@@ -1496,54 +1502,55 @@ fino a trattare le caratteristiche generali della gestione dei medesimi nella
 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
-\func{sleep} a partire da dall'uso di \func{pause} e \func{alarm}. A prima
-vista questo può sembrare di implementazione immediata; ad esempio una
-semplice versione di \func{sleep} potrebbe essere quella illustrata in
+\func{sleep} a partire dall'uso di \func{pause} e \func{alarm}. A prima vista
+questo può sembrare di implementazione immediata; ad esempio una semplice
+versione di \func{sleep} potrebbe essere quella illustrata in
 \figref{fig:sig_sleep_wrong}.
 
-
-Dato che è nostra intenzione utilizzare \macro{SIGALARM} il primo passo della
+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 
@@ -1556,13 +1563,13 @@ precedente chiamata a \func{alarm} (che si 
 presenta una pericolosa race condition.  Infatti se il processo viene
 interrotto fra la chiamata di \func{alarm} e \func{pause} può capitare (ad
 esempio se il sistema è molto carico) che il tempo di attesa scada prima
-dell'esecuzione quest'ultima, cosicchè essa sarebbe eseguita dopo l'arrivo di
+dell'esecuzione quest'ultima, cosicché essa sarebbe eseguita dopo l'arrivo di
 \macro{SIGALRM}. In questo caso ci si troverebbe di fronte ad un deadlock, in
 quanto \func{pause} non verrebbe mai più interrotta (se non in caso di un
 altro segnale).
 
 Questo problema può essere risolto (ed è la modalità con cui veniva fatto in
-SVr2) usando la funzione \func{longjump} (vedi \secref{sec:proc_longjmp}) per
+SVr2) usando la funzione \func{longjmp} (vedi \secref{sec:proc_longjmp}) per
 uscire dal manipolatore; in questo modo, con una condizione sullo stato di
 uscita di quest'ultima, si può evitare la chiamata a \func{pause}, usando un
 codice del tipo di quello riportato in \figref{fig:sig_sleep_incomplete}.
@@ -1588,7 +1595,8 @@ unsigned int sleep(unsigned int seconds)
     /* 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");
@@ -1607,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
-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.
 
@@ -1615,29 +1623,700 @@ 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
-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
+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
+\figref{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 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.
+
+
+
+\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
+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 \textsl{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 \textsl{insieme di segnali} è 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
+degli insiemi di segnali: \func{sigemptyset}, \func{sigfillset},
+\func{sigaddset}, \func{sigdelset} e \func{sigismember}, i cui prototipi sono:
+\begin{functions}
+  \headdecl{signal.h} 
+  
+  \funcdecl{int sigemptyset(sigset\_t *set)} Inizializza un insieme di segnali
+  vuoto (in cui non c'è nessun segnale).
+  \funcdecl{int sigfillset(sigset\_t *set)} Inizializza un insieme di segnali
+  pieno (in cui ci sono tutti i segnali).
+  
+  \funcdecl{int sigaddset(sigset\_t *set, int signum)} Aggiunge il segnale
+  \param{signum} all'insieme di segnali \param{set}.
 
-\subsection{Le funzioni \func{sigprocmask} e \func{sigpending}}
-\label{sec:sig_sigpending}
+  \funcdecl{int sigdelset(sigset\_t *set, int signum)} Toglie il segnale
+  \param{signum} dall'insieme di segnali \param{set}.
+  
+  \funcdecl{int sigismember(const sigset\_t *set, int signum)} Controlla se il
+  segnale \param{signum} è nell'insieme di segnali \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 insieme di segnali per specificare quali segnali si vuole
+bloccare, o per riottenere dalle varie funzioni di gestione la maschera dei
+segnali attivi (vedi \secref{sec:sig_sigmask}). 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 verificare la presenza di uno specifico segnale in un
+insieme.
 
 
 \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 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)} 
+  
+  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:
+  \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 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
+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. 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 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
+  \centering
+  \begin{tabular}[c]{|l|p{8cm}|}
+    \hline
+    \textbf{Valore} & \textbf{Significato} \\
+    \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} o 
+                           \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_specific_features}).\\ 
+    \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}.
+
+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 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 è
+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,
+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
+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.
+
+Le operazioni più semplici, come l'assegnazione o il controllo di una
+variabile (per essere sicuri si può usare il tipo \type{sig\_atomic\_t}) di
+norma sono atomiche, quando occorrono operazioni più complesse si può invece
+usare la funzione \func{sigprocmask} che permette di bloccare uno o più
+segnali; il suo prototipo è:
+\begin{prototype}{signal.h}
+{int sigprocmask(int how, const sigset\_t *set, sigset\_t *oldset)} 
+  
+  Cambia la \textsl{maschera dei segnali} del processo corrente.
+  
+  \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{EFAULT}] Si sono specificati indirizzi non validi.
+  \end{errlist}}
+\end{prototype}
+
+La funzione usa l'insieme di segnali dato all'indirizzo \param{set} per
+modificare la maschera dei segnali del processo corrente. La modifica viene
+effettuata a seconda del valore dell'argomento \param{how}, secondo le modalità
+specificate in \tabref{tab:sig_procmask_how}. Qualora si specifichi un valore
+non nullo per \param{oldset} la maschera dei segnali corrente viene salvata a
+quell'indirizzo.
+
+\begin{table}[htb]
+  \footnotesize
+  \centering
+  \begin{tabular}[c]{|l|p{8cm}|}
+    \hline
+    \textbf{Valore} & \textbf{Significato} \\
+    \hline
+    \hline
+    \macro{SIG\_BLOCK}   & L'insieme dei segnali bloccati è l'unione fra
+                           quello specificato e quello corrente.\\
+    \macro{SIG\_UNBLOCK} & I segnali specificati in \param{set} sono rimossi
+                           dalla maschera dei segnali, specificare la
+                           cancellazione di un segnale non bloccato è legale.\\
+    \macro{SIG\_SETMASK} & La maschera dei segnali è settata al valore
+                           specificato da \param{set}.\\
+    \hline
+  \end{tabular}
+  \caption{Valori e significato dell'argomento \param{how} della funzione
+    \func{sigprocmask}.}
+  \label{tab:sig_procmask_how}
+\end{table}
+
+In questo modo diventa possibile proteggere delle sezioni di codice bloccando
+l'insieme di segnali voluto per poi riabilitarli alla fine della sezione
+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
+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)} 
+  
+  Setta la \textit{signal mask} specificata, mettendo in attesa il processo.
+  
+  \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{EFAULT}] Si sono specificati indirizzi non validi.
+  \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à.
 
-\subsection{Funzioni rientranti e default dei segnali}
-\label{sec:sig_reentrant}
+\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}
 
-, affrontando inoltre le varie problematiche di programmazione che si devono
-tenere presenti quando si ha a che fare con essi.
+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}