Lavoro in treno per webbit
[gapil.git] / signal.tex
index 6f6c1110e6e1be70c400a6026ada77d813345b9e..246c308c1f36bb0ab62cfe6ca999cdd6fdd5ed10 100644 (file)
@@ -16,7 +16,7 @@ In questo capitolo esamineremo i vari aspetti della gestione dei segnali,
 partendo da una introduzione relativa ai concetti base con cui essi vengono
 realizzati, per poi affrontarne la classificazione a secondo di uso e modalità
 di generazione fino ad esaminare in dettaglio funzioni e le metodologie di
 partendo da una introduzione relativa ai concetti base con cui essi vengono
 realizzati, per poi affrontarne la classificazione a secondo di uso e modalità
 di generazione fino ad esaminare in dettaglio funzioni e le metodologie di
-gestione.
+gestione. 
 
 
 \section{Introduzione}
 
 
 \section{Introduzione}
@@ -662,11 +662,11 @@ segnali sono:
   situazione precedente.
 \item[\macro{SIGXCPU}] Sta per \textit{CPU time limit exceeded}. Questo
   segnale è generato quando un processo eccede il limite impostato per il
   situazione precedente.
 \item[\macro{SIGXCPU}] Sta per \textit{CPU time limit exceeded}. Questo
   segnale è generato quando un processo eccede il limite impostato per il
-  tempo di CPU disponibile, vedi \secref{sec:sys_xxx}. 
+  tempo di CPU disponibile, vedi \secref{sec:sys_resource_limit}. 
 \item[\macro{SIGXFSZ}] Sta per \textit{File size limit exceeded}. Questo
   segnale è generato quando un processo tenta di estendere un file oltre le
   dimensioni specificate dal limite impostato per le dimensioni massime di un
 \item[\macro{SIGXFSZ}] Sta per \textit{File size limit exceeded}. Questo
   segnale è generato quando un processo tenta di estendere un file oltre le
   dimensioni specificate dal limite impostato per le dimensioni massime di un
-  file, vedi \secref{sec:sys_xxx}. 
+  file, vedi \secref{sec:sys_resource_limit}. 
 \end{basedescript}
 
 
 \end{basedescript}
 
 
@@ -714,7 +714,7 @@ di \func{strsignal}. Nel caso si debba mantenere traccia del messaggio sar
 necessario copiarlo.
 
 La seconda funzione deriva da BSD ed è analoga alla funzione \func{perror}
 necessario copiarlo.
 
 La seconda funzione deriva da BSD ed è analoga alla funzione \func{perror}
-descritta in \secref{sec:sys_strerror}; il suo prototipo è:
+descritta sempre in \secref{sec:sys_strerror}; il suo prototipo è:
 \begin{prototype}{signal.h}{void psignal(int sig, const char *s)} 
   Stampa sullo standard error un messaggio costituito dalla stringa \param{s},
   seguita da due punti ed una descrizione del segnale indicato da \param{sig}.
 \begin{prototype}{signal.h}{void psignal(int sig, const char *s)} 
   Stampa sullo standard error un messaggio costituito dalla stringa \param{s},
   seguita da due punti ed una descrizione del segnale indicato da \param{sig}.
@@ -750,7 +750,7 @@ processo alla loro occorrenza.
 
 
 \subsection{Il comportamento generale del sistema.}
 
 
 \subsection{Il comportamento generale del sistema.}
-  \label{sec:sig_gen_beha}
+\label{sec:sig_gen_beha}
 
 Abbiamo già trattato in \secref{sec:sig_intro} le modalità con cui il sistema
 gestisce l'interazione fra segnali e processi, ci resta da esaminare però il
 
 Abbiamo già trattato in \secref{sec:sig_intro} le modalità con cui il sistema
 gestisce l'interazione fra segnali e processi, ci resta da esaminare però il
@@ -778,28 +778,29 @@ manipolatore; viene mantenuto invece ogni eventuale settaggio dell'azione a
 programmi eseguiti in background, che altrimenti sarebbero interrotti da una
 successiva pressione di \texttt{C-c} o \texttt{C-y}.
 
 programmi eseguiti in background, che altrimenti sarebbero interrotti da una
 successiva pressione di \texttt{C-c} o \texttt{C-y}.
 
-Per quanto riguarda tutte le altre system call esse vengono tradizionalmente
-classificate, proprio in base al loro comportamento nei confronti dei segnali,
-in \textsl{lente} (\textit{slow}) e \textsl{veloci} (\textit{fast}). La gran
-parte appartiene a quest'ultima categoria che non è influenzata dall'arrivo di
-un segnale. In tal caso un eventuale manipolatore viene sempre eseguito dopo
-che la system call è stata completata. Esse sono dette \textsl{veloci} proprio
-in quanto la loro esecuzione è sostanzialmente immediata e attendere per
-eseguire un manipolatore non comporta nessun inconveniente.
-
-Esistono però dei casi in cui questo non è possibile perché renderebbe
-impossibile una risposta pronta al segnale. In generale questo avviene tutte
-le volte che si ha a che fare con system call che possono bloccarsi
-indefinitamente, (quelle che, per questo, vengono chiamate \textsl{lente}). Un
-elenco dei casi in cui si presenta questa situazione è il seguente:
+Per quanto riguarda il comportamento di tutte le altre system call si danno
+sostanzialmente due casi, a seconda che esse siano \textsl{lente}
+(\textit{slow}) o \textsl{veloci} (\textit{fast}). La gran parte di esse
+appartiene a quest'ultima categoria, che non è influenzata dall'arrivo di un
+segnale. Esse sono dette \textsl{veloci} in quanto la loro esecuzione è
+sostanzialmente immediata; la risposta al segnale viene sempre data dopo che
+la system call è stata completata, in quanto attendere per eseguire un
+manipolatore non comporta nessun inconveniente.
+
+In alcuni casi però alcune system call (che per questo motivo vengono chiamate
+\textsl{lente}) possono bloccarsi indefinitamente. In questo caso non si può
+attendere la conclusione della sistem call, perché questo renderebbe
+impossibile una risposta pronta al segnale, per cui il manipolatore viene
+eseguito prima che la system call sia ritornata.  Un elenco dei casi in cui si
+presenta questa situazione è il seguente:
 \begin{itemize}
 \begin{itemize}
-\item lettura da file che possono bloccarsi in attesa di dati non ancora
-  presenti (come per certi file di dispositivo, la rete o le pipe).
-\item scrittura sugli stessi file, nel caso in cui dati non possano essere
+\item la lettura da file che possono bloccarsi in attesa di dati non ancora
+  presenti (come per certi file di dispositivo, i socket o le pipe).
+\item la scrittura sugli stessi file, nel caso in cui dati non possano essere
   accettati immediatamente.
   accettati immediatamente.
-\item apertura di un file di dispositivo che richiede operazioni non immediate
-  per una una risposta. 
-\item operazioni eseguite con \func{ioctl} che non è detto possano essere
+\item l'apertura di un file di dispositivo che richiede operazioni non
+  immediate per una una risposta.
+\item le operazioni eseguite con \func{ioctl} che non è detto possano essere
   eseguite immediatamente.
 \item le funzioni di intercomunicazione che si bloccano in attesa di risposte
   da altri processi.
   eseguite immediatamente.
 \item le funzioni di intercomunicazione che si bloccano in attesa di risposte
   da altri processi.
@@ -1141,12 +1142,6 @@ struct itimerval
     struct timeval it_interval; /* next value */
     struct timeval it_value;    /* current value */
 };
     struct timeval it_interval; /* next value */
     struct timeval it_value;    /* current value */
 };
-
-struct timeval 
-{
-    long tv_sec;                /* seconds */
-    long tv_usec;               /* microseconds */
-};
     \end{lstlisting}
   \end{minipage} 
   \normalsize 
     \end{lstlisting}
   \end{minipage} 
   \normalsize 
@@ -1336,9 +1331,9 @@ 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
 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. 
+delle strutture di tipo \var{timespec}, la cui definizione è riportata in
+\figref{fig:sys_timeval_struct}, che permettono di specificare un tempo con
+una precisione (teorica) fino al nanosecondo.
 
 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
 
 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
@@ -1355,21 +1350,6 @@ 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}.
 
 questo motivo il valore restituito in \param{rem} è sempre arrotondato al
 multiplo successivo di 1/\macro{HZ}.
 
-\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}
-
 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
 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
@@ -1421,7 +1401,7 @@ la creazione di zombie.
 #include <sys/wait.h>
 #include "macro.h"
 
 #include <sys/wait.h>
 #include "macro.h"
 
-void Hand_CHLD(int sig)
+void sigchld_hand(int sig)
 {
     int errno_save;
     int status;
 {
     int errno_save;
     int status;
@@ -1815,16 +1795,6 @@ struct sigaction
   \label{fig:sig_sigaction}
 \end{figure}
 
   \label{fig:sig_sigaction}
 \end{figure}
 
-Come si può notare da quanto riportato in \figref{fig:sig_sigaction} in Linux
-\func{sigaction} permette di specificare il manipolatore in due forme diverse,
-indicate dai campi \var{sa\_handler} e \var{sa\_sigaction}; esse devono essere
-usate in maniera alternativa (in certe implementazioni questi vengono
-specificati come \ctyp{union}): la prima è quella classica usata anche con
-\func{signal}, la seconda permette invece di usare un manipolatore in grado di
-ricevere informazioni più dettagliate dal sistema (ad esempio il tipo di
-errore in caso di \macro{SIGFPE}), attraverso dei parametri aggiuntivi; per i
-dettagli si consulti la man page di \func{sigaction}).
-
 Il campo \var{sa\_mask} serve ad indicare l'insieme dei segnali che devono
 essere bloccati durante l'esecuzione del manipolatore, ad essi viene comunque
 sempre aggiunto il segnale che ne ha causato la chiamata, a meno che non si
 Il campo \var{sa\_mask} serve ad indicare l'insieme dei segnali che devono
 essere bloccati durante l'esecuzione del manipolatore, ad essi viene comunque
 sempre aggiunto il segnale che ne ha causato la chiamata, a meno che non si
@@ -1839,11 +1809,10 @@ dell'implementazione di \code{sleep} mostrata in
 allarme avesse interrotto un altro manipolatore questo non sarebbe stato
 eseguito correttamente; la cosa poteva essere prevenuta installando gli altri
 manipolatori usando \var{sa\_mask} per bloccare \macro{SIGALRM} durante la
 allarme avesse interrotto un altro manipolatore questo non sarebbe stato
 eseguito correttamente; la cosa poteva essere prevenuta installando gli altri
 manipolatori usando \var{sa\_mask} per bloccare \macro{SIGALRM} durante la
-loro esecuzione. 
-Il valore di \var{sa\_flag} permette di specificare vari aspetti del
-comportamento di \func{sigaction}, e della reazione del processo ai vari
-segnali; i valori possibili ed il relativo significato sono riportati in
-\tabref{tab:sig_sa_flag}. 
+loro esecuzione.  Il valore di \var{sa\_flag} permette di specificare vari
+aspetti del comportamento di \func{sigaction}, e della reazione del processo
+ai vari segnali; i valori possibili ed il relativo significato sono riportati
+in \tabref{tab:sig_sa_flag}.
 
 \begin{table}[htb]
   \footnotesize
 
 \begin{table}[htb]
   \footnotesize
@@ -1882,6 +1851,68 @@ segnali; i valori possibili ed il relativo significato sono riportati in
   \label{tab:sig_sa_flag}
 \end{table}
 
   \label{tab:sig_sa_flag}
 \end{table}
 
+Come si può notare in \figref{fig:sig_sigaction} \func{sigaction}
+permette\footnote{La possibilità è prevista dallo standard POSIX.1b, ma in
+  Linux è stata aggiunta a partire dai kernel della serie 2.2.x. In precedenza
+  era possibile ottenere alcune informazioni addizionali usando
+  \var{sa\_handler} con un secondo parametro addizionale di tipo \var{struct
+    sigcontext}, che adesso è deprecato.}  di utilizzare due forme diverse di
+manipolatore, da specificare, a seconda dell'uso o meno del flag
+\macro{SA\_SIGINFO}, rispettivamente attraverso i campi \var{sa\_sigaction} o
+\var{sa\_handler}, (che devono essere usati in maniera alternativa, in certe
+implementazioni questi vengono addirittura definiti come \ctyp{union}): la
+prima è quella classica usata anche con \func{signal}, la seconda permette
+invece di usare un manipolatore in grado di ricevere informazioni più
+dettagliate dal sistema, attraverso la struttura \var{siginfo\_t}, riportata
+in \figref{fig:sig_siginfo_t}.
+
+\begin{figure}[!htb]
+  \footnotesize \centering
+  \begin{minipage}[c]{15cm}
+    \begin{lstlisting}[labelstep=0]{}%,frame=,indent=1cm]{}
+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}
+  \end{minipage} 
+  \normalsize 
+  \caption{La struttura \var{siginfo\_t}.} 
+  \label{fig:sig_siginfo_t}
+\end{figure}
+Installando un manipolatore di tipo \var{sa\_sigaction} diventa allora
+possibile accedere alle informazioni restituite attraverso il puntatore a
+questa struttura. Tutti i segnali settano i campi \var{si\_signo}, che riporta
+il segnale ricevuto, \var{si\_errno}, che riporta il codice di errore, e
+\var{si\_code}, che viene usato per indicare la ragione per cui è stato emesso
+il segnale (come i dettagli sul tipo di errore per \macro{SIGFPE} e
+\macro{SIGILL}) ed ha valori diversi\footnote{un elenco dettagliato è
+  disponibile nella man page di \func{sigaction}.} a seconda del tipo di
+segnale ricevuto.
+
+Il resto della struttura può essere definito come \ctyp{union} ed i valori
+eventualmente presenti dipendono dal segnale, così \macro{SIGCHLD} ed i
+segnali POSIX.1b\footnote{NdA trovare quale sono e completare l'informazione.}
+inviati tramite \func{kill} avvalorano \var{si\_pid} e \var{si\_uid} coi
+valori corrispondenti al processo che ha emesso il segnale, \macro{SIGILL},
+\macro{SIGFPE}, \macro{SIGSEGV} e \macro{SIGBUS} avvalorano \var{si\_addr} con
+l'indirizzo cui è avvenuto l'errore, \macro{SIGIO} (vedi
+\secref{sec:file_asyncronous_io}) e \macro{SIGPOLL} avvalorano \var{si\_fd}
+con il numero del file descriptor.
+
 Benché sia possibile usare nello stesso programma sia \func{sigaction} che
 \func{signal} occorre molta attenzione, in quanto le due funzioni possono
 interagire in maniera anomala. Infatti l'azione specificata con
 Benché sia possibile usare nello stesso programma sia \func{sigaction} che
 \func{signal} occorre molta attenzione, in quanto le due funzioni possono
 interagire in maniera anomala. Infatti l'azione specificata con
@@ -1895,11 +1926,46 @@ Per questo 
 ripristinare correttamente un manipolatore precedente, anche se questo è stato
 installato con \func{signal}. In generale poi non è il caso di usare il valore
 di ritorno di \func{signal} come campo \var{sa\_handler}, o viceversa, dato
 ripristinare correttamente un manipolatore precedente, anche se questo è stato
 installato con \func{signal}. In generale poi non è il caso di usare il valore
 di ritorno di \func{signal} come campo \var{sa\_handler}, o viceversa, dato
-che in certi sistemi questi possono essere diversi. In generale dunque, a meno
-che non si sia vincolati allo standard ISO C, è sempre il caso di evitare
-l'uso di \func{signal} a favore di \func{sigaction}.
+che in certi sistemi questi possono essere diversi. In definitiva dunque, a
+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 \centering
+  \begin{minipage}[c]{15cm}
+    \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 */
+        perror("cannot initializes the signal set to empty"); /* see mess. */
+        exit(1);
+    }
+    new_handl.sa_flags=0;                  /* init to 0 all flags */
+    /* change action for signo signal */
+    if (sigaction(signo,&new_handl,&old_handl)){ 
+        perror("sigaction failed on signal action setting");
+        exit(1);
+    }
+    return (old_handl.sa_handler);
+}
+    \end{lstlisting}
+  \end{minipage} 
+  \normalsize 
+  \caption{Una funzione equivalente a \func{signal} definita attraverso
+    \func{sigaction}.} 
+  \label{fig:sig_Signal_code}
+\end{figure}
 
 
+Per questo motivo si è provveduto, per mantenere un'interfaccia semplificata
+che abbia le stesse caratteristiche di \func{signal}, a definire una funzione
+equivalente attraverso \func{sigaction}; la funzione è \code{Signal}, e si
+trova definita come \code{inline} nel file \file{wrapper.h} (nei sorgenti
+allegati), riportata in \figref{fig:sig_Signal_code}. La riutilizzeremo spesso
+in seguito. 
 
 \subsection{La gestione della \textsl{maschera dei segnali} o 
   \textit{signal mask}}
 
 \subsection{La gestione della \textsl{maschera dei segnali} o 
   \textit{signal mask}}
@@ -2221,7 +2287,49 @@ avviene per lo stack ordinario dei processi, non si accresce automaticamente
 Si ricordi infine che una chiamata ad una funzione della famiglia
 \func{exec} cancella ogni stack alternativo.
 
 Si ricordi infine che una chiamata ad una funzione della famiglia
 \func{exec} cancella ogni stack alternativo.
 
+Abbiamo visto in \secref{fig:sig_sleep_incomplete} come si possa usare
+\func{longjmp} per uscire da un manipolatore rientrando direttamente nel corpo
+del programma; sappiamo però che nell'esecuzione di un manipolatore il segnale
+che l'ha invocato viene bloccato, e abbiamo detto che possiamo ulteriormente
+modificarlo con \func{sigprocmask}. 
+
+Resta quindi il problema di cosa succede alla maschera dei segnali quando si
+esce da un manipolatore 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
+\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}.
+
+Lo standard POSIX però prevede anche la presenza di altre due funzioni
+\func{sigsetjmp} e \func{siglongjmp}, che permettono di decidere quale dei due
+comportamenti il programma deve assumere; i loro prototipi sono:
+\begin{functions}
+  \headdecl{setjmp.h} 
+  
+  \funcdecl{int sigsetjmp(sigjmp\_buf env, int savesigs)} Salva il contesto
+  dello stack per un salto non locale.
+  \funcdecl{void siglongjmp(sigjmp\_buf env, int val)} Esegue un salto non
+  locale su un precedente contesto.
+
+  \bodydesc{Le due funzioni sono identiche alle analoghe \func{setjmp} e
+    \func{longjmp} di \secref{sec:proc_longjmp}, ma consentono di specificare
+    il comportamento sul ripristino o meno della maschera dei segnali.}
+\end{functions}
 
 
+Le due funzioni prendono come primo argomento la variabile su cui viene
+salvato il contesto dello stack per permettere il salto non locale; nel caso
+specifico essa è di tipo \type{sigjmp\_buf}, e non \type{jmp\_buf} come per le
+analoghe di \secref{sec:proc_longjmp} in quanto in questo caso viene salvata
+anche la maschera dei segnali.
+
+Nel caso di \func{sigsetjmp} se si specifica un valore di \param{savesigs}
+diverso da zero la maschera dei valori sarà salvata in \param{env} e
+ripristinata in un successivo \func{siglongjmp}; quest'ultima funzione, a
+parte l'uso di \type{sigjmp\_buf} per \param{env}, è assolutamente identica a
+\func{longjmp}.
 
 
 %%% Local Variables: 
 
 
 %%% Local Variables: