gestione.
+
\section{Introduzione}
\label{sec:sig_intro}
normalmente i segnali vengono ``fusi'' insieme ed al processo ne viene
recapitato soltanto uno.
-Questo può essere un caso comune proprio con \texttt{SIGCHLD}, quando molti
+Questo può essere un caso comune proprio con \macro{SIGCHLD}, quando molti
processi figli terminano in rapida successione. Esso comunque si presenta
tutte le volte che un segnale viene bloccato: per quanti siano i segnali
emessi durante il periodo di blocco, una volta che esso viene rimosso ne sarà
sono stati ricevuti.
+
\section{Gestione avanzata}
\label{sec:sig_control}
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.
+risolvere i problemi più complessi connessi alla programmazione con i segnali,
+fino a trattare le caratteristiche generali della gestione dei medesimi nella
+casistica ordinaria.
\subsection{Un esempio di problema}
semplice versione di \func{sleep} potrebbe essere la seguente quella
illustrata in \ref{fig:sig_sleep_wrong}.
+In questo caso si salva il precedente manipolatore in (\texttt{\small 15--21})
+per poi chiamare in sequenza \func{alarm} per specificare l'attesa e
+\func{pause} per fermare il programma. Al ritorno di pause, causato dal
+ritorno del manipolatore (\texttt{\small 15--21}) si ripristina il
+manipolatore (\texttt{\small 15--21}) restituendo l'eventuale tempo rimanente
+(\texttt{\small 15--21}).
+
\begin{figure}[!htb]
\footnotesize \centering
\begin{minipage}[c]{15cm}
\end{lstlisting}
\end{minipage}
\normalsize
- \caption{Una implementazione sbagliata di \func{sleep}.}
+ \caption{Una implementazione pericolosamente sbagliata di \func{sleep}.}
\label{fig:sig_sleep_wrong}
\end{figure}
-Ma questa funzione, a parte il non gestire il caso in cui si è avuta una
+Ma questo codice, 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
+\func{pause} può capitare (ad esempio se il sistema è 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).
+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
+uscire dal manipolatore, in modo da sfruttare lo stato di uscita di
+quest'ultima per evitare la chiamata a \func{pause}, con un codice del tipo:
+
+\begin{figure}[!htb]
+ \footnotesize \centering
+ \begin{minipage}[c]{15cm}
+ \begin{lstlisting}{}
+static jmp_buff alarm_return;
+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);
+ }
+ if (setjmp(alarm_return) == 0) { /* if not returning from handler */
+ alarm(second); /* call alarm */
+ pause(); /* then wait */
+ }
+ /* 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 { /* return in main after the call to pause */
+ longjump(alarm_return, 1);
+ }
+}
+ \end{lstlisting}
+ \end{minipage}
+ \normalsize
+ \caption{Una implementazione ancora malfunzionante di \func{sleep}.}
+ \label{fig:sig_sleep_incomplete}
+\end{figure}
+
+In questo modo all'uscita dal manipolatore si eviterà comunque la chiamata di
+\func{pause}, dato che in questo caso il valore di uscita di \func{setjmp} è
+uno ed il condizionale in (\texttt{\small 15--21}) viene evitato.
-Come abbiamo accennato in \secref{sec:proc_atom_oper} quando si ha a che fare
-con i segnali
+Ma anche questa implementazione comporta dei problemi; in questo caso infatti
+non viene gestita correttamente l'interazione con 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.