Aggiuno un altro esempio
authorSimone Piccardi <piccardi@gnulinux.it>
Tue, 26 Mar 2002 23:16:05 +0000 (23:16 +0000)
committerSimone Piccardi <piccardi@gnulinux.it>
Tue, 26 Mar 2002 23:16:05 +0000 (23:16 +0000)
signal.tex

index fec20a72c0d0465508faae3bda50031b4a894bc8..bbfea4f851f101561bc6adecfae0aaddd5b0f368 100644 (file)
@@ -19,6 +19,7 @@ di generazione fino ad esaminare in dettaglio funzioni e le metodologie di
 gestione.
 
 
 gestione.
 
 
+
 \section{Introduzione}
 \label{sec:sig_intro}
 
 \section{Introduzione}
 \label{sec:sig_intro}
 
@@ -1460,7 +1461,7 @@ della generazione di altri segnali dello stesso tipo. In questo caso
 normalmente i segnali vengono ``fusi'' insieme ed al processo ne viene
 recapitato soltanto uno.
 
 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à
 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à
@@ -1480,6 +1481,7 @@ permette di evitare che essa si blocchi quando tutti gli stati di terminazione
 sono stati ricevuti.
 
 
 sono stati ricevuti.
 
 
+
 \section{Gestione avanzata}
 \label{sec:sig_control}
 
 \section{Gestione avanzata}
 \label{sec:sig_control}
 
@@ -1490,7 +1492,9 @@ 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
 
 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}
 
 
 \subsection{Un esempio di problema}
@@ -1502,6 +1506,13 @@ vista questo pu
 semplice versione di \func{sleep} potrebbe essere la seguente quella
 illustrata in \ref{fig:sig_sleep_wrong}.
 
 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}
 \begin{figure}[!htb]
   \footnotesize \centering
   \begin{minipage}[c]{15cm}
@@ -1532,21 +1543,70 @@ void alarm_hand(int sig) {
     \end{lstlisting}
   \end{minipage} 
   \normalsize 
     \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}
 
   \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
 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
 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.