+\subsection{Le funzioni \func{pause} e \func{sleep}}
+\label{sec:sig_pause_sleep}
+
+Il metodo tradizionale per fare attendere 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)}
+
+ Pone il processo in stato di sleep fino al ritorno di un manipolatore.
+
+ \bodydesc{La funzione ritorna solo dopo che un segnale è stato ricevuto ed
+ il relativo manipolatore è ritornato, nel qual caso restituisce -1 e setta
+ \var{errno} a \macro{EINTR}.}
+\end{prototype}
+
+La funzione segnala sempre una condizione di errore (il successo sarebbe
+quello di aspettare indefinitamente). In genere si usa questa funzione quando
+si vuole mettere un processo in attesa di un qualche evento specifico che non
+è sotto il suo diretto controllo (ad esempio la si può usare per far reagire
+il processo ad un segnale inviato da un altro processo).
+
+
+Se invece si vuole fare attendere un processo per un determinato intervallo di
+tempo lo standard POSIX.1 definisce la funzione \func{sleep}, il cui prototipo
+è:
+\begin{prototype}{unistd.h}{unsigned int sleep(unsigned int seconds)}
+
+ Pone il processo in stato di sleep per \param{seconds} secondi.
+
+ \bodydesc{La funzione restituisce zero se l'attesa viene completata, o il
+ numero di secondi restanti se viene interrotta da un segnale.}
+\end{prototype}
+
+La funzione attende per il tempo specificato, a meno di non essere interrotta
+da un segnale. In questo caso non è una buona idea ripetere la chiamata per il
+tempo rimanente, in quanto la riattivazione del processo può avvenire in un
+qualunque momento, ma il valore restituito sarà sempre arrotondato al secondo,
+con la conseguenza che, se la successione dei segnali è particolarmente
+sfortunata, si potranno avere ritardi anche di parecchi secondi. In genere la
+scelta più sicura è quella di stabilire un termine per l'attesa, e ricalcolare
+tutte le volte il numero di secondi da aspettare.
+
+In alcune implementazioni inoltre l'uso di \func{sleep} può avere conflitti
+con quello di \macro{SIGALRM}, dato che la funzione può essere realizzata
+attraverso \func{pause} e \func{alarm} (in maniera analoga all'esempio che
+vedremo in \ref{sec:sig_example}). In tal caso mescolare chiamata di
+\func{alarm} e \func{sleep} o modificare l'azione di \macro{SIGALRM}, può
+causare risultati indefiniti. Nel caso delle \acr{glibc} è stata usata una
+implementazione completamente indipendente e questi problemi non ci sono.
+
+La granularità di \func{sleep} permette di specificare attese in secondi, per
+questo sia sotto BSD4.3 che in SUSv2 è stata definita la funzione
+\func{usleep} (dove la \texttt{u} è intesa come sostituzione di $\mu$); i due
+standard hanno delle definizioni diverse, ma le \acr{glibc}
+seguono\footnote{secondo la man page almeno dalla versione 2.2.2.} seguono
+quella di SUSv2 che prevede il seguente prototipo:
+\begin{prototype}{unistd.h}{int usleep(unsigned long usec)}
+
+ Pone il processo in stato di sleep per \param{usec} microsecondi.
+
+ \bodydesc{La funzione restituisce zero se l'attesa viene completata, o -1 in
+ caso di errore, nel qual caso \var{errno} è settata a \macro{EINTR}.}
+
+\end{prototype}
+
+Anche questa funzione a seconda delle implementazioni può presentare problemi
+nell'interazione con \func{alarm} e \macro{SIGALRM}, ed è pertanto deprecata
+in favore di \func{nanosleep}, definita dallo standard POSIX1.b, il cui
+prototipo è:
+\begin{prototype}{unistd.h}{int nanosleep(const struct timespec *req, struct
+ timespec *rem)}
+
+ Pone il processo in stato di sleep per il tempo specificato da \param{req}.
+ In caso di interruzione restituisce il tempo restante in \param{rem}.
+
+ \bodydesc{La funzione restituisce zero se l'attesa viene completata, o -1 in
+ caso di errore, nel qual caso \var{errno} è settata a
+ \begin{errlist}
+ \item[\macro{EINVAL}] si è specificato un numero di secondi negativo o un
+ numero di nanosecondi maggiore di 999.999.999.
+ \item[\macro{EINTR}] la funzione è stata interrotta da un segnale.
+ \end{errlist}}
+\end{prototype}
+
+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.
+
+\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
+basta richiamare la funzione per completare l'attesa.
+
+Chiaramente, anche se il tempo può essere specificato con risoluzioni fino al
+nanosecondo, la precisione di \func{nanosleep} è determinata dalla risoluzione
+temporale del timer di sistema. Perciò la funzione attenderà comunque il tempo
+specificato, ma prima che il processo possa tornare ad essere eseguito
+occorrerà almeno attendere il successivo giro di scheduler e cioè un tempo che
+a seconda dei casi può arrivare fino a 1/\macro{HZ}, (sempre che il sistema
+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}.
+
+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
+viene evitato, e si raggiungono pause fino ai 2~ms con precisioni del $\mu$s.
+
+
+
+\subsection{Un esempio elementare}
+\label{sec:sig_sigchld}
+
+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
+ 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
+ terminazione viene scartato senza dover chiamare una \func{wait}). L'azione
+ di default è sempre quella di ignorare il segnale, ma non attiva questo
+ comportamento. Linux, come BSD e POSIX, non supporta questa semantica ed usa
+ il nome di \macro{SIGCLD} come sinonimo di \macro{SIGCHLD}.} in questo caso
+tutto quello che dovrà fare il manipolatore è ricevere lo stato di
+terminazione in modo da evitare la formazione di zombie.
+
+% è pertanto
+% naturale usare un esempio che ci permette di concludere la trattazione della
+% terminazione dei processi.
+% In questo caso si è tratterà di illustrare un esempio relativo ad un
+% manipolatore per che è previsto ritornare,
+
+In realtà nel caso di \macro{SIGCHLD} occorre tenere conto anche di un altro
+aspetto del comportamento dei segnali e cioè del fatto
+
+
+
+
+\begin{figure}[!htb]
+ \footnotesize \centering
+ \begin{minipage}[c]{15cm}
+ \begin{lstlisting}[labelstep=0,frame=,indent=1cm]{}
+#include <errno.h> /* error simbol definitions */
+#include <signal.h> /* signal handling declarations */
+#include <sys/types.h>
+#include <sys/wait.h>
+#include "macro.h"
+
+void Hand_CHLD(int sig)
+{
+ int errno_save;
+ int status;
+ pid_t pid;
+ /* save errno current value */
+ errno_save = errno;
+ /* loop until no */
+ do {
+ errno = 0;
+ pid = waitpid(WAIT_ANY, &status, WNOHANG);
+ if (pid > 0) {
+ debug("child %d terminated with status %x\n", pid, status);
+ }
+ } while ((pid > 0) && (errno == EINTR));
+ /* restore errno value*/
+ errno = errno_save;
+ /* return */
+ return;
+}
+ \end{lstlisting}
+ \end{minipage}
+ \normalsize
+ \caption{Una implementazione sbagliata di \func{sleep}.}
+ \label{fig:sig_timespec_def}
+\end{figure}