Corretti i commenti ai listati in una forma piu' leggibile (spero).
[gapil.git] / signal.tex
index c28a70c33e0ae189dbf4e5856efe5edc89b7e9ce..7a680d40d0e77c7fed49f7185c8e054a1ea4dd6f 100644 (file)
@@ -1,4 +1,4 @@
-%% signal.tex
+a%% signal.tex
 %%
 %% Copyright (C) 2000-2002 Simone Piccardi.  Permission is granted to
 %% copy, distribute and/or modify this document under the terms of the GNU Free
@@ -1171,22 +1171,7 @@ in termini di \func{setitimer}, come evidenziato dal manuale delle \acr{glibc}
 \begin{figure}[!htb]
   \footnotesize \centering
   \begin{minipage}[c]{15cm}
-    \begin{lstlisting}[stepnumber=0]{}
-unsigned int alarm(unsigned int seconds)
-{
-    struct itimerval old, new;
-    new.it_interval.tv_usec = 0;
-    new.it_interval.tv_sec = 0;
-    new.it_value.tv_usec = 0;
-    new.it_value.tv_sec = (long int) seconds;
-    if (setitimer(ITIMER_REAL, &new, &old) < 0) {
-        return 0;
-    }
-    else {
-        return old.it_value.tv_sec;
-    }
-}
-    \end{lstlisting}
+    \includestruct{listati/alarm_def.c}
   \end{minipage} 
   \normalsize 
   \caption{Definizione di \func{alarm} in termini di \func{setitimer}.} 
@@ -1413,29 +1398,10 @@ di zombie\index{zombie}.
 % gestore per che è previsto ritornare,
 
 \begin{figure}[!htb]
-  \footnotesize 
-  \begin{lstlisting}{}
-void HandSigCHLD(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}
+  \footnotesize  \centering
+  \begin{minipage}[c]{15cm}
+    \includecodesample{listati/hand_sigchild.c}
+  \end{minipage}
   \normalsize 
   \caption{Codice di una funzione generica di gestione per il segnale
     \texttt{SIGCHLD}.}  
@@ -1518,34 +1484,10 @@ rimanente (\texttt{\small 22-23}) che potr
 l'interruzione di \func{pause} venisse causata da un altro segnale.
 
 \begin{figure}[!htb]
-  \footnotesize
-    \begin{lstlisting}{}
-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;
-    }
-}
-unsigned int sleep(unsigned int seconds)
-{
-    sighandler_t prev_handler;
-    /* install and check new handler */
-    if ((prev_handler = signal(SIGALRM, alarm_hand)) == SIG_ERR) {
-        printf("Cannot set handler for alarm\n"); 
-        exit(-1);
-    }
-    /* set alarm and go to sleep */
-    alarm(seconds); 
-    pause(); 
-    /* restore previous signal handler */
-    signal(SIGALRM, prev_handler);
-    /* return remaining time */
-    return alarm(0);
-}
-  \end{lstlisting}
+  \footnotesize \centering
+  \begin{minipage}[c]{15cm}
+    \includecodesample{listati/sleep_danger.c}
+  \end{minipage}
   \normalsize 
   \caption{Una implementazione pericolosa di \func{sleep}.} 
   \label{fig:sig_sleep_wrong}
@@ -1568,36 +1510,10 @@ uscita di quest'ultima, si pu
 codice del tipo di quello riportato in \figref{fig:sig_sleep_incomplete}.
 
 \begin{figure}[!htb]
-  \footnotesize 
-    \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}
+  \footnotesize \centering
+  \begin{minipage}[c]{15cm}
+    \includecodesample{listati/sleep_defect.c}
+  \end{minipage}
   \normalsize 
   \caption{Una implementazione ancora malfunzionante di \func{sleep}.} 
   \label{fig:sig_sleep_incomplete}
@@ -1625,28 +1541,10 @@ programma (con un codice del tipo di quello riportato in
 \figref{fig:sig_event_wrong}).
 
 \begin{figure}[!htb]
-  \footnotesize
-    \begin{lstlisting}{}
-sig_atomic_t flag;
-int main()
-{
-    flag = 0;
-    ...
-    if (flag) {         /* test if signal occurred */
-        flag = 0;       /* reset flag */ 
-        do_response();  /* do things */
-    } else {
-        do_other();     /* do other things */
-    }
-    ...
-}
-void alarm_hand(int sig) 
-{
-    /* set the flag 
-    flag = 1;
-    return;
-}      
-  \end{lstlisting}
+  \footnotesize\centering
+  \begin{minipage}[c]{15cm}
+    \includecodesample{listati/sig_alarm.c}
+  \end{minipage}
   \normalsize 
   \caption{Un esempio non funzionante del codice per il controllo di un
     evento generato da un segnale.}
@@ -1676,13 +1574,11 @@ reagire alla ricezione di un segnale.
 \label{sec:sig_sigset}
 
 Come evidenziato nel paragrafo precedente, le funzioni di gestione dei segnali
-dei primi Unix, nate con la semantica inaffidabile, hanno dei limiti non
+originarie, nate con la semantica inaffidabile, hanno dei limiti non
 superabili; in particolare non è prevista nessuna funzione che permetta di
 gestire gestire il blocco dei segnali o di verificare lo stato dei segnali
-pendenti.
-
-Per questo motivo lo standard POSIX.1, insieme alla nuova semantica dei
-segnali ha introdotto una interfaccia di gestione completamente nuova, che
+pendenti.  Per questo motivo lo standard POSIX.1, insieme alla nuova semantica
+dei segnali ha introdotto una interfaccia di gestione completamente nuova, che
 permette di ottenete un controllo molto più dettagliato. In particolare lo
 standard ha introdotto un nuovo tipo di dato \type{sigset\_t}, che permette di
 rappresentare un \textsl{insieme di segnali} (un \textit{signal set}, come
@@ -1794,16 +1690,7 @@ pi
 \begin{figure}[!htb]
   \footnotesize \centering
   \begin{minipage}[c]{15cm}
-    \begin{lstlisting}[stepnumber=0]{}
-struct sigaction 
-{
-    void (*sa_handler)(int);
-    void (*sa_sigaction)(int, siginfo_t *, void *);
-    sigset_t sa_mask;
-    int sa_flags;
-    void (*sa_restorer)(void);
-}
-    \end{lstlisting}
+    \includestruct{listati/sigaction.h}
   \end{minipage} 
   \normalsize 
   \caption{La struttura \structd{sigaction}.} 
@@ -1885,24 +1772,7 @@ riportata in \figref{fig:sig_siginfo_t}.
 \begin{figure}[!htb]
   \footnotesize \centering
   \begin{minipage}[c]{15cm}
-    \begin{lstlisting}[stepnumber=0]{}
-siginfo_t {
-    int      si_signo;  /* Signal number */
-    int      si_errno;  /* An errno value */
-    int      si_code;   /* Signal code */
-    pid_t    si_pid;    /* Sending process ID */
-    uid_t    si_uid;    /* Real user ID of sending process */
-    int      si_status; /* Exit value or signal */
-    clock_t  si_utime;  /* User time consumed */
-    clock_t  si_stime;  /* System time consumed */
-    sigval_t si_value;  /* Signal value */
-    int      si_int;    /* POSIX.1b signal */
-    void *   si_ptr;    /* POSIX.1b signal */
-    void *   si_addr;   /* Memory location which caused fault */
-    int      si_band;   /* Band event */
-    int      si_fd;     /* File descriptor */
-}
-    \end{lstlisting}
+    \includestruct{listati/siginfo_t.h}
   \end{minipage} 
   \normalsize 
   \caption{La struttura \structd{siginfo\_t}.} 
@@ -1959,25 +1829,10 @@ meno che non si sia vincolati all'aderenza stretta allo standard ISO C, 
 sempre il caso di evitare l'uso di \func{signal} a favore di \func{sigaction}.
 
 \begin{figure}[!htb]
-  \footnotesize 
-  \begin{lstlisting}{}
-typedef void SigFunc(int);
-inline SigFunc * Signal(int signo, SigFunc *func) 
-{
-    struct sigaction new_handl, old_handl;
-    new_handl.sa_handler = func;
-    /* clear signal mask: no signal blocked during execution of func */
-    if (sigemptyset(&new_handl.sa_mask)!=0){        /* initialize signal set */
-        return SIG_ERR;
-    }
-    new_handl.sa_flags=0;                             /* init to 0 all flags */
-    /* change action for signo signal */
-    if (sigaction(signo, &new_handl, &old_handl)){ 
-        return SIG_ERR;
-    }
-    return (old_handl.sa_handler);
-}
-    \end{lstlisting}
+  \footnotesize  \centering
+  \begin{minipage}[c]{15.6cm}
+    \includecodesample{listati/Signal.c}
+  \end{minipage} 
   \normalsize 
   \caption{Una funzione equivalente a \func{signal} definita attraverso
     \func{sigaction}.} 
@@ -2123,39 +1978,10 @@ ottenere un'implementazione, riportata in \figref{fig:sig_sleep_ok} che non
 presenta neanche questa necessità.
 
 \begin{figure}[!htb]
-  \footnotesize 
-    \begin{lstlisting}{}
-void alarm_hand(int);
-unsigned int sleep(unsigned int seconds)
-{
-    struct sigaction new_action, old_action;
-    sigset_t old_mask, stop_mask, sleep_mask;
-    /* set the signal handler */
-    sigemptyset(&new_action.sa_mask);              /* no signal blocked */
-    new_action.sa_handler = alarm_hand;            /* set handler */
-    new_action.sa_flags = 0;                       /* no flags */
-    sigaction(SIGALRM, &new_action, &old_action);  /* install action */
-    /* block SIGALRM to avoid race conditions */
-    sigemptyset(&stop_mask);                       /* init mask to empty */
-    sigaddset(&stop_mask, SIGALRM);                /* add SIGALRM */
-    sigprocmask(SIG_BLOCK, &stop_mask, &old_mask); /* add SIGALRM to blocked */
-    /* send the alarm */
-    alarm(seconds); 
-    /* going to sleep enabling SIGALRM */
-    sleep_mask = old_mask;                         /* take mask */
-    sigdelset(&sleep_mask, SIGALRM);               /* remove SIGALRM */
-    sigsuspend(&sleep_mask);                       /* go to sleep */
-    /* restore previous settings */
-    sigprocmask(SIG_SETMASK, &old_mask, NULL);     /* reset signal mask */    
-    sigaction(SIGALRM, &old_action, NULL);         /* reset signal action */
-    /* return remaining time */
-    return alarm(0);
-}
-void alarm_hand(int sig) 
-{
-    return;     /* just return to interrupt sigsuspend */
-}
-    \end{lstlisting}
+  \footnotesize   \centering
+  \begin{minipage}[c]{15.6cm}
+    \includecodesample{listati/sleep.c}
+  \end{minipage} 
   \normalsize 
   \caption{Una implementazione completa di \func{sleep}.} 
   \label{fig:sig_sleep_ok}
@@ -2183,13 +2009,13 @@ dato che \const{SIGALRM} viene disabilitato con \func{sigprocmask} fino alla
 chiamata di \func{sigsuspend}. Questo metodo è assolutamente generale e può
 essere applicato a qualunque altra situazione in cui si deve attendere per un
 segnale, i passi sono sempre i seguenti:
-\begin{enumerate}
+\begin{enumerate*}
 \item Leggere la maschera dei segnali corrente e bloccare il segnale voluto
   con \func{sigprocmask}. 
 \item Mandare il processo in attesa con \func{sigsuspend} abilitando la
   ricezione del segnale voluto.
 \item Ripristinare la maschera dei segnali originaria.
-\end{enumerate}
+\end{enumerate*}
 Per quanto possa sembrare strano bloccare la ricezione di un segnale per poi
 riabilitarla immediatamente dopo, in questo modo si evita il
 deadlock\index{deadlock} dovuto all'arrivo del segnale prima dell'esecuzione
@@ -2228,7 +2054,7 @@ sistema un altro stack (invece di quello relativo al processo, vedi
 \secref{sec:proc_mem_layout}) solo durante l'esecuzione di un
 gestore. L'uso di uno stack alternativo è del tutto trasparente ai
 gestori, occorre però seguire una certa procedura:
-\begin{enumerate*}
+\begin{enumerate}
 \item Allocare un'area di memoria di dimensione sufficiente da usare come
   stack alternativo.
 \item Usare la funzione \func{sigaltstack} per rendere noto al sistema
@@ -2237,18 +2063,20 @@ gestori, occorre per
   specificando il flag \const{SA\_ONSTACK} (vedi \tabref{tab:sig_sa_flag}) per
   dire al sistema di usare lo stack alternativo durante l'esecuzione del
   gestore. 
-\end{enumerate*}
+\end{enumerate}
 
 In genere il primo passo viene effettuato allocando un'opportuna area di
 memoria con \code{malloc}; in \file{signal.h} sono definite due costanti,
 \const{SIGSTKSZ} e \const{MINSIGSTKSZ}, che possono essere utilizzate per
 allocare una quantità di spazio opportuna, in modo da evitare overflow. La
 prima delle due è la dimensione canonica per uno stack di segnali e di norma è
-sufficiente per tutti gli usi normali. La seconda è lo spazio che occorre al
-sistema per essere in grado di lanciare il gestore e la dimensione di uno
-stack alternativo deve essere sempre maggiore di questo valore. Quando si
-conosce esattamente quanto è lo spazio necessario al gestore gli si può
-aggiungere questo valore per allocare uno stack di dimensione sufficiente.
+sufficiente per tutti gli usi normali. 
+
+La seconda è lo spazio che occorre al sistema per essere in grado di lanciare
+il gestore e la dimensione di uno stack alternativo deve essere sempre
+maggiore di questo valore. Quando si conosce esattamente quanto è lo spazio
+necessario al gestore gli si può aggiungere questo valore per allocare uno
+stack di dimensione sufficiente.
 
 Come accennato per poter essere usato lo stack per i segnali deve essere
 indicato al sistema attraverso la funzione \funcd{sigaltstack}; il suo
@@ -2281,13 +2109,7 @@ successivo ripristino).
 \begin{figure}[!htb]
   \footnotesize \centering
   \begin{minipage}[c]{15cm}
-    \begin{lstlisting}[stepnumber=0]{}
-typedef struct {
-    void  *ss_sp;     /* Base address of stack */
-    int    ss_flags;  /* Flags */
-    size_t ss_size;   /* Number of bytes in stack */
-} stack_t;
-    \end{lstlisting}
+    \includestruct{listati/stack_t.h}
   \end{minipage} 
   \normalsize 
   \caption{La struttura \structd{stack\_t}.} 
@@ -2330,9 +2152,11 @@ modificarlo con \func{sigprocmask}.
 
 Resta quindi il problema di cosa succede alla maschera dei segnali quando si
 esce da un gestore usando questa funzione. Il comportamento dipende
-dall'implementazione; in particolare BSD ripristina la maschera dei segnali
-precedente l'invocazione, come per un normale ritorno, mentre System V no. Lo
-standard POSIX.1 non specifica questo comportamento per \func{setjmp} e
+dall'implementazione; in particolare BSD prevede che sia ripristinata la
+maschera dei segnali precedente l'invocazione, come per un normale ritorno,
+mentre System V no.
+
+Lo standard POSIX.1 non specifica questo comportamento per \func{setjmp} e
 \func{longjmp}, ed il comportamento delle \acr{glibc} dipende da quale delle
 caratteristiche si sono abilitate con le macro viste in
 \secref{sec:intro_gcc_glibc_std}.
@@ -2436,40 +2260,38 @@ l'I/O asincrono (vedi \secref{sec:file_asyncronous_io}) o per le code di
 messaggi POSIX (vedi \secref{sec:ipc_posix_mq}); pertanto devono essere
 inviati esplicitamente. 
 
-Inoltre per poter usufruire della capacità di restituire dei dati i relativi
-gestori devono essere installati con \func{sigaction} specificando la modalità
-\const{SA\_SIGINFO} che permette di utilizzare la forma estesa
-\var{sa\_sigaction} (vedi \secref{sec:sig_sigaction}).  In questo modo tutti i
-segnali real-time possono restituire al gestore una serie di informazioni
-aggiuntive attraverso l'argomento \struct{siginfo\_t} (la cui definizione è
-riportata in \figref{fig:sig_siginfo_t}).
+Inoltre, per poter usufruire della capacità di restituire dei dati, i relativi
+gestori devono essere installati con \func{sigaction}, specificando per
+\var{sa\_flags} la modalità \const{SA\_SIGINFO} che permette di utilizzare la
+forma estesa \var{sa\_sigaction} (vedi \secref{sec:sig_sigaction}).  In questo
+modo tutti i segnali real-time possono restituire al gestore una serie di
+informazioni aggiuntive attraverso l'argomento \struct{siginfo\_t}, la cui
+definizione abbiamo già visto in \figref{fig:sig_siginfo_t}, nella trattazione
+dei gestori in forma estesa.
 
 In particolare i campi utilizzati dai segnali real-time sono \var{si\_pid} e
-\var{si\_uid} in cui vengono memorizzati rispettivamente \acr{pid} e userid
-effettivo del processo che ha inviato il segnale, mentre per la restituzione
-dei dati viene usato il campo \var{si\_value}, questo è una \ctyp{union} di
-tipo \struct{sigval\_t} (la sua definizione è in \figref{fig:sig_sigval}) in
-cui può essere memorizzato o un valore numerico o un indirizzo,\footnote{un
-  campo di tipo \struct{sigval\_t} è presente anche nella struttura
-  \struct{sigevent} che viene usata dai meccanismi di notifica come quelli per
-  l'I/O asincrono (vedi \secref{sec:file_asyncronous_io}) o le code di
-  messaggi POSIX (vedi \secref{sec:ipc_posix_mq}).}
+\var{si\_uid} in cui vengono memorizzati rispettivamente il \acr{pid} e
+l'user-ID effettivo del processo che ha inviato il segnale, mentre per la
+restituzione dei dati viene usato il campo \var{si\_value}.
+
+Questo è una \ctyp{union} di tipo \struct{sigval\_t} (la sua definizione è in
+\figref{fig:sig_sigval}) in cui può essere memorizzato o un valore numerico,
+se usata nella forma \var{sival\_int}, o un indirizzo, se usata nella forma
+\var{sival\_ptr}. L'unione viene usata dai segnali real-time e da vari
+meccanismi di notifica\footnote{un campo di tipo \struct{sigval\_t} è presente
+  anche nella struttura \struct{sigevent} che viene usata dai meccanismi di
+  notifica come quelli per l'I/O asincrono (vedi
+  \secref{sec:file_asyncronous_io}) o le code di messaggi POSIX (vedi
+  \secref{sec:ipc_posix_mq}).} per restituire dati al gestore del segnale; in
+alcune definizioni essa viene identificata anche come \code{union sigval}.
 
 \begin{figure}[!htb]
   \footnotesize \centering
   \begin{minipage}[c]{15cm}
-    \begin{lstlisting}[stepnumber=0]{}
-union sigval_t {
-        int sival_int;
-        void *sival_ptr;
-}
-    \end{lstlisting}
+    \includestruct{listati/sigval_t.h}
   \end{minipage} 
   \normalsize 
-  \caption{La struttura \structd{sigval\_t}, una \ctyp{union} usata dai
-    segnali real-time e dai meccanismi di notifica per restituire dati al
-    gestore, (in alcune definizione essa viene identificata anche come
-    \code{union sigval}).}
+  \caption{La unione \structd{sigval\_t}.}
   \label{fig:sig_sigval}
 \end{figure}
 
@@ -2508,13 +2330,13 @@ installato un gestore con \const{SA\_SIGINFO} e ci sono risorse disponibili,
   costante \const{SIGQUEUE\_MAX}, una della tante costanti di sistema definite
   dallo standard POSIX, che non abbiamo riportato esplicitamente in
   \secref{sec:sys_limits}. Il suo valore minimo secondo lo standard,
-  \const{\_POSIX\_SIGQUEUE\_MAX}, è pari a 32.} nella coda) esso viene
-inserito e diventa pendente; una volta consegnato riporterà nel campo
-\var{si\_code} di \struct{siginfo} il valore \const{SI\_QUEUE} e il campo
-\var{si\_value} riceverà quanto inviato con \param{value}. Se invece si è
-installato un gestore nella forma classica il segnale sarà generato, ma tutte
-le caratteristiche tipiche dei segnali real-time (priorità e coda) saranno
-perse.
+  \const{\_POSIX\_SIGQUEUE\_MAX}, è pari a 32.} nella coda dei segnali
+real-time) esso viene inserito e diventa pendente; una volta consegnato
+riporterà nel campo \var{si\_code} di \struct{siginfo\_t} il valore
+\const{SI\_QUEUE} e il campo \var{si\_value} riceverà quanto inviato con
+\param{value}. Se invece si è installato un gestore nella forma classica il
+segnale sarà generato, ma tutte le caratteristiche tipiche dei segnali
+real-time (priorità e coda) saranno perse.
 
 Lo standard POSIX.1b definisce inoltre delle nuove funzioni che permettono di
 gestire l'attesa di segnali specifici su una coda, esse servono in particolar