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 fra poco). 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.
+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
\label{fig:sig_timespec_def}
\end{figure}
-La
+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.
\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; 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 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.
+ 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 è possibile implementare \func{sleep} a partire da dall'uso di
-\func{pause} e \func{alarm};
+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}}
+
\subsection{La funzione \func{sigaction}}
\label{sec:sig_sigaction}