+
+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{La gestione di \macro{SIGCHLD}}
+\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}.} è pertanto
+naturale completare qui la trattazione della terminazione dei processi
+illustrando le modalità per gestire questo segnale.
+
+
+
+
+
+
+\section{Gestione avanzata}
+\label{sec:sig_control}
+
+Le funzioni esaminate finora fanno riferimento ad alle modalità più elementari
+della gestione dei segnali; non si sono pertanto ancora prese in
+considerazione le tematiche più complesse, collegate alle varie race condition
+che i segnali possono generare e alla natura asincrona degli stessi.
+
+Affronteremo queste problematiche in questa sezione, partendo da un esempio
+che le evidenzi, per poi prendere in esame le varie funzioni che permettono di
+risolvere i problemi più complessi connessi alla programmazione con i segnali.
+
+
+\subsection{Un esempio di problema}
+\label{sec:sig_example}
+
+Come accennato in \ref{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 la seguente:
+\begin{figure}[!htb]
+ \footnotesize \centering
+ \begin{minipage}[c]{15cm}
+ \begin{lstlisting}[labelstep=0,frame=,indent=1cm]{}
+unsigned int sleep(unsigned int seconds)
+{
+ signandler_t prev_handler;
+ if ((prev_handler = signal(SIGALRM, alarm_hand)) == SIG_ERR) {
+ printf("Cannot set handler for alarm\n");
+ exit(1);
+ }
+ alarm(second);
+ pause();
+ /* restore previous signal handler */
+ signal(SIGALRM, prev_handler);
+ /* remove alarm, 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
+ \caption{Una implementazione sbagliata di \func{sleep}.}
+ \label{fig:sig_timespec_def}
+\end{figure}
+
+Ma questa, a parte il non gestire il caso in cui si è avuta una precedente
+chiamata a \func{alarm}, presenta una pericolosa race condition. Infatti se il
+processo viene interrotto fra la chiamata di \func{alarm} e \func{pause} può
+capitare (nel caso il sistema sia molto carico) che quest'ultima possa essere
+eseguita dopo l'arrivo di \macro{SIGALRM}. In questo caso ci si troverebbe di
+fronte ad un deadlock, in cui \func{pause} non verrebbe mai interrotta (se non
+in caso di un altro segnale).
+
+
+\subsection{Le funzioni \func{sigprocmask} e \func{sigpending}}