Correzioni per le footnote e scritta altra roba sui segnali (finite kill e
[gapil.git] / signal.tex
index aafb4ecebfd83541240c676c89f5f59970ec2dec..90885ffd70e750208ae212cd8dbedd9bc5a3a2b1 100644 (file)
@@ -45,8 +45,8 @@ il seguente:
 \item una richiesta dell'utente di terminare o fermare il programma. In genere
   si realizza attraverso un segnale mandato dalla shell in corrispondenza
   della pressione di tasti del terminale come \code{C-c} o
-  \code{C-z}\footnote{indichiamo con \code{C-x} la pressione simultanea al
-    tasto \code{x} del tasto control (ctrl in molte tastiere)}.
+  \code{C-z}.\footnote{indichiamo con \code{C-x} la pressione simultanea al
+    tasto \code{x} del tasto control (ctrl in molte tastiere).}
 \item l'esecuzione di una \func{kill} o di una \func{raise} da parte del
   processo stesso o di un'altro (solo nel caso della \func{kill}).
 \end{itemize*}
@@ -830,6 +830,11 @@ dei casi in cui si presenta questa situazione 
   per una una risposta. 
 \item 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.
+\item la funzione \func{pause} (usata appunto per attendere l'arrivo di un
+  segnale).
+\item la funzione \func{wait} (se nessun processo figlio è ancora terminato).
 \end{itemize*}
 
 In questo caso si pone il problema di cosa fare una volta che il manipolatore
@@ -839,8 +844,23 @@ tutt'oggi una scelta corrente, ma comporta che i programmi che usano dei
 manipolatori controllino lo stato di uscita delle funzioni per ripeterne la
 chiamata qualora l'errore fosse questo.
 
-Dato che dimenticarsi di richiamare una funzione interrotta è un errore comune 
+Dimenticarsi di richiamare una system call interrotta da un segnale è un
+errore comune, tanto che le \acr{glibc} provvedono una macro
+\code{TEMP\_FAILURE\_RETRY(expr)} che esegue l'operazione automaticamente,
+ripetendo l'esecuzione dell'espressione \var{expr} fintanto che il risultato
+non è diverso dall'uscita con un errore \macro{EINTR}.
 
+La soluzione è comunque poco elegante e BSD ha scelto un approccio molto
+diverso, che è quello di fare ripartire automaticamente la system call invece
+di farla fallire. In questo caso ovviamente non c'è da preoccuparsi di
+controllare il codice di errore; si perde però la possibilità di eseguire
+azioni specifiche all'occorrenza di questa particolare condizione. 
+
+Linux e le \acr{glibc} consentono di utilizzare entrambi gli approcci,
+attraverso una opportuna opzione di \func{sigaction} (vedi
+\secref{sec:sig_sigaction}). È da chiarire comunque che nel caso di
+interruzione nel mezzo di un trasferimento parziale di dati, le system call
+ritornano sempre indicando i byte trasferiti.
 
 
 \subsection{La funzione \func{signal}}
@@ -853,7 +873,7 @@ da essere del tutto inutile in un sistema Unix; 
 ogni implementazione successiva ne ha modificato e ridefinito il
 comportamento, pur mantenendone immutato il prototipo\footnote{in realtà
   alcune vecchie implementazioni (SVR4 e 4.3+BSD) usano parametri aggiuntivi
-  per definire il comportamento della funzione} che è:
+  per definire il comportamento della funzione.} che è:
 \begin{prototype}{signal.h}
   {sighandler\_t signal(int signum, sighandler\_t handler)} 
   
@@ -865,7 +885,7 @@ comportamento, pur mantenendone immutato il prototipo\footnote{in realt
 \end{prototype}
 
 In questa definizione si è usato il tipo \type{sighandler\_t} che è una
-estensione GNU definita dalle \acr{glibc} che permette di riscrivere il
+estensione GNU, definita dalle \acr{glibc}, che permette di riscrivere il
 prototipo in una forma più leggibile dell'originario:
 \begin{verbatim}
 void (*signal(int signum, void (*handler)(int)))int)
@@ -878,10 +898,10 @@ con il precedente prototipo si pu
     typedef void (* sighandler_t)(int) 
 \end{verbatim}
 e cioè un puntatore ad una funzione \type{void} (cioè senza valore di ritorno)
-e che prende un argomento di tipo \type{int}\footnote{si devono usare le
+e che prende un argomento di tipo \type{int}.\footnote{si devono usare le
   parentesi intorno al nome della funzione per via delle precedenze degli
   operatori del C, senza di esse si sarebbe definita una funzione che ritorna
-  un puntatore a \type{void} e non un puntatore ad una funzione \type{void}}.
+  un puntatore a \type{void} e non un puntatore ad una funzione \type{void}.}
 La funzione \func{signal} quindi restituisce e prende come secondo argomento
 un puntatore a una funzione di questo tipo, che è appunto il manipolatore del
 segnale.
@@ -891,25 +911,221 @@ direttamente con una delle costanti definite in \secref{sec:sig_standard}. Il
 manipolatore \param{handler} invece, oltre all'indirizzo della funzione da
 chiamare all'occorrenza del segnale, può assumere anche i due valori costanti
 \macro{SIG\_IGN} con cui si dice ignorare il segnale e \macro{SIG\_DFL} per
-installare l'azione di di default\footnote{si ricordi però che i due segnali
+installare l'azione di di default.\footnote{si ricordi però che i due segnali
   \macro{SIGKILL} e \macro{SIGSTOP} non possono essere ignorati né
-  intercettati}.
+  intercettati.}
+
+La funzione restituisce l'indirizzo dell'azione precedente, che può essere
+salvato per poterlo ripristinare (con un'altra chiamata a \func{signal}) in un
+secondo tempo. Si ricordi che se si setta come azione \macro{SIG\_IGN} (o si
+setta un \macro{SIG\_DFL} per un segnale il cui default è di essere ignorato),
+tutti i segnali pendenti saranno scartati, e non verranno mai notificati.
+
+L'uso di \func{signal} è soggetto a problemi di compatibilità, dato che essa
+si comporta in maniera diversa per sistemi derivati da BSD o da System V. In
+questi ultimi infatti la funzione è conforme al comportamento originale dei
+primi Unix in cui il manipolatore viene disinstallato alla sua chiamata
+secondo la semantica inaffidabile; Linux seguiva questa convenzione fino alle
+\acr{libc5}. Al contrario BSD segue la semantica affidabile, non resettando il
+manipolatore e bloccando il segnale durante l'esecuzione dello stesso. Con
+l'utilizzo delle \acr{glibc2} anche Linux è passato a questo comportamento;
+quello della versione originale della funzione, il cui uso è deprecato per i
+motivi visti in \secref{sec:sig_semantics}, può essere ottenuto chiamando
+\func{sysv\_signal}.  In generale, per evitare questi problemi, tutti i nuovi
+programmi dovrebbero usare \func{sigaction}.
+
+È da tenere presente che, seguendo lo standard POSIX, il comportamento di un
+processo che ignora i segnali \macro{SIGFPE}, \macro{SIGILL}, o
+\macro{SIGSEGV} (qualora non originino da una \func{kill} o una \func{raise})
+è indefinito. Un manipolatore che ritorna da questi segnali può dare luogo ad
+un ciclo infinito.
 
 
+\subsection{Le funzioni \func{kill} e \func{raise}}
+\label{sec:sig_kill_raise}
 
-\subsection{Funzioni rientranti e default dei segnali}
-\label{sec:sig_reentrant}
+Come accennato in \secref{sec:sig_types}, un segnale può essere generato
+direttamente da un processo. L'invio di un sengale generico può essere
+effettuato attraverso delle funzioni \func{kill} e \func{raise}. La prima
+serve per inviare un segnale al processo corrente, ed il suo prototipo è:
+\begin{prototype}{signal.h}{int raise(int sig)}
+  Invia il segnale \param{sig} al processo corrente.
+  
+  \bodydesc{La funzione restituisce zero in caso di successo e -1 per un
+    errore, il solo errore restituito è \macro{EINVAL} qualora si sia
+    specificato un numero di segnale invalido.}
+\end{prototype}
+
+Il valore di \param{sig} specifica il segnale che si vuole inviare e può
+essere specificato con una delle macro definite in
+\secref{sec:sig_classification}.  In genere questa funzione viene usata per
+riprodurre il comportamento di default di un segnale che sia stato
+intercettato. In questo caso, una volta eseguite le operazioni volute, il
+manipolatore potrà reinstallare l'azione di default, e attivarla con
+\func{raise}.
+
+Se invece si vuole inviare un segnale ad un altro processo occorre utilizzare
+la funzione \func{kill}; il suo prototipo è:
+\begin{functions}
+  \headdecl{sys/types.h}
+  \headdecl{signal.h}
+  \funcdecl{int kill(pid\_t pid, int sig)} Invia il segnale \param{sig} al
+  processo specificato con \param{pid}.
+
+  \bodydesc{La funzione restituisce zero in caso di successo e -1 per un
+    errore, nel qual caso \var{errno} assumerà i valori:
+  \begin{errlist}
+  \item[\macro{EINVAL}] Si è specificato un numero di segnale invalido.
+  \item[\macro{EPERM}] Il processo non ha il permesso di inviare il segnale
+  alla destinazione specificata.
+  \item[\macro{ESRCH}] Il \acr{pid} o il process group indicati non
+  esistono. Gli zombie (vedi \ref{sec:proc_termination}) sono considerati come
+  processi esistenti.
+  \end{errlist}}
+\end{functions}
+
+La funzione \code{raise(sig)} è sostanzialmente equivalente ad una
+\code{kill(getpid(), sig)}. Siccome \func{raise} è definita nello standard ISO
+C non esiste in alcune vecchie versioni di Unix, per cui in generale l'uso di
+\func{kill} è più portabile.
+
+Lo standard POSIX poi prevede che il valore 0 sia usato per specificare il
+segnale nullo.  Se le funzioni vengono chiamate con questo valore non viene
+inviato nessun segnale, ma viene eseguito il controllo degli errori, in tal
+caso si otterrà un errore \macro{EPERM} se non si hanno i permessi necessari
+ed un errore \macro{ESRCH} se il processo specificato non esiste. Si tenga
+conto però che il sistema ricicla i \acr{pid} (come accennato in
+\secref{sec:proc_pid}) per cui l'esistenza di un processo non significa che
+esso sia realmente quello a cui si intendeva mandare il segnale.
+
+Il valore dell'argomento \param{pid} specifica la destinazione a cui inviare
+il segnale e può assumere i seguenti significati:
+\begin{basedescript}{\desclabelwidth{2cm}\desclabelstyle{\nextlinelabel}}
+\item[$\texttt{pid}>0$] il segnale è mandato al processo con il \acr{pid}
+  indicato.
+\item[$\texttt{pid}=0$] il segnale è mandato ad ogni processo del
+  \textit{process group} del chiamante.
+\item[$\texttt{pid}=-1$] il segnale è mandato ad ogni processo (eccetto
+  \cmd{init}).
+\item[$\texttt{pid}<-1$] il segnale è mandato ad ogni processo del process
+  group $|\code{pid}|$.
+\end{basedescript}
 
+Solo l'amministratore può inviare un segnale ad un processo qualunque, in
+tutti gli altri casi il \textit{real user id} o l'\textit{effective user id}
+del processo chiamante devono corrispondere al \textit{real user id} o al
+\textit{saved user id} della destinazione. Fa eccezione il caso in cui il
+segnale inviato sia \macro{SIGCONT}, nel quale occorre che entrambi i processi
+appartengano alla stessa sessione. Inoltre, dato il ruolo fondamentale che
+riveste nel sistema (si ricordi quanto visto in \secref{sec:sig_termination}),
+non è possibile inviare al processo 1 (cioè a \cmd{init}) segnali per i quali
+esso non abbia un manipolatore installato.
+
+Infine, seguendo le specifiche POSIX 1003.1-2001, l'uso della chiamata
+\code{kill(-1, sig)} comporta che il segnale sia inviato (con la solita
+eccezione di \cmd{init}) a tutti i processi per i quali i permessi lo
+consentano. Lo standard permette comunque alle varie implementazione di
+escludere alcuni processi specifici: nel caso in questione Linux non invia il
+segnale al processo che ha effettuato la chiamata.
+
+
+\subsection{Le funzioni \func{alarm} e \func{abort}}
+\label{sec:sig_alarm_abort}
+
+Un caso particolare di segnali generati a richiesta è quello che riguarda i
+segnali di temporizzazione e e \macro{SIGABORT}, per i quali sono previste
+funzioni specifiche che ne effettuino l'invio. La prima di queste è
+\func{alarm} il cui prototipo è:
+\begin{prototype}{unistd.h}{unsigned int alarm(unsigned int seconds)}
+  Predispone l'invio di \macro{SIGALARM} dopo \param{seconds} secondi.
+  
+  \bodydesc{La funzione restituisce il numero di secondi rimanenti ad un
+    precedente allarme, o zero se non c'erano allarmi pendenti.}
+\end{prototype}
 
+La funzione provvede un meccanismo che consente ad un processo di predisporre
+un'interruzione nel futuro, (ad esempio per effettuare una qualche operazione
+dopo un certo periodo di tempo), programmando l'emissione si un segnale di
+\macro{SIGALARM} dopo il numero di secondi specificato da \param{seconds}.
+Chiaramente la precisione è determinata da quella dell'orologio di sistema, e
+sono sempre possibili ritardi in caso di un sistema eccessivamente carico.
+
+Se si specifica per \param{seconds} un valore nullo non verrà inviato nessun
+segnale; siccome alla chiamata viene cancellato ogni precedente allarme,
+questo può essere usato per cancellare una programmazione precedente. La
+funzione inoltre ritorna il numero di secondi rimanenti all'invio dell'allarme
+precedentemente programmato, in modo che sia eventualmente possibile
+effettuare delle scelte in caso di necessità di più interruzioni.
+
+In \secref{sec:sys_unix_time} abbiamo visto che ad ogni processo sono
+associati tre tempi diversi: \textit{clock time}, \textit{user time} e
+\textit{system time}.  Per poterli calcolare il kernel mantiene tre diversi
+timer per ciascun processo:
+\begin{itemize}
+\item un \textit{real-time timer} che calcola il tempo reale trascorso (che
+  corrisponde al \textit{clock time}). La scadenza di questo timer provoca
+  l'emissione di \macro{SIGALARM}.
+\item un \textit{virtual timer} che calcola il tempo di processore usato dal
+  processo in user space (che corrisponde all'\textit{user time}). La scadenza
+  di questo timer provoca l'emissione di \macro{SIGVTALRM}.
+\item un \textit{profiling timer} che calcola la somma dei tempi di processore
+  utilizzati direttamente dal processo in user space, e dal kernel nelle
+  system call ad esso relative (che corrisponde a quello che in
+  \secref{sec:sys_unix_time} abbiamo chiamato \textit{CPU time}). La scadenza
+  di questo timer provoca l'emissione di \macro{SIGPROF}.
+\end{itemize}
+
+Il timer usato da \func{alarm} è il \textit{clock time}, e corrisponde cioè al
+tempo reale.  Dato che \func{alarm} non consente di usare gli altri timer, e
+non può specificare intervalli con precisione maggiore al secondo le
+\acr{glibc} provvedono la funzione \func{setitimer} che permette un controllo
+completo, a scapito di un uso molto più complesso. Il suo prototipo è:
+\begin{prototype}{sys/time.h}{int setitimer(int which, const struct
+    itimerval *value, struct itimerval *ovalue)} 
+  
+  Predispone l'invio di un segnale di allarme alla scadenza dell'intervallo
+  \param{value} sul timer specificato da \func{which}.
+  
+  \bodydesc{La funzione restituisce 0 in caso di successo e -1 in caso di
+    errore, nel qual caso \var{errno} può assumere i valori \macro{EINVAL} e
+    \macro{EFAULT}.}
+\end{prototype}
 
-\subsection{Le funzioni \func{kill} e \func{raise}}
-\label{sec:sig_kill_raise}
+Il valore di \param{which} permette di specificare quale dei tre timer usare;
+i possibili valori sono riportati in \tabref{tab:sig_setitimer_values}.
+
+\begin{table}[htb]
+  \centering
+  \begin{tabular}[c]{|l|l|}
+    \hline
+    \textbf{Valore} & \textbf{Timer} \\
+    \hline
+    \hline
+    \macro{ITIMER\_REAL}    & \textit{real-time timer}\\
+    \macro{ITIMER\_VIRTUAL} & \textit{virtual timer}\\
+    \macro{ITIMER\_PROF}    & \textit{profiling timer}\\
+    \hline
+  \end{tabular}
+  \caption{Valori dell'argomento \param{which} per la funzione
+    \func{setitimer}.}
+  \label{tab:sig_setitimer_values}
+\end{table}
+
+
+\subsection{Le funzioni \func{pause} e \func{sleep}}
+\label{sec:sig_pause_sleep}
 
-\subsection{Le funzioni \func{alarm} e \func{pause}}
-\label{sec:sig_alarm_pause}
 
 
-\section{Il controllo dei segnali}
+
+
+\subsection{Le semantiche di \macro{SIGCHLD}}
+\label{sec:sig_sigchld}
+
+
+
+
+\section{Gestione avanzata}
 \label{sec:sig_control}
 
 
@@ -925,6 +1141,9 @@ installare l'azione di di default\footnote{si ricordi per
 
 
 
+\subsection{Funzioni rientranti e default dei segnali}
+\label{sec:sig_reentrant}
+
 
 , affrontando inoltre le varie problematiche di programmazione che si devono
 tenere presenti quando si ha a che fare con essi.