%% signal.tex
%%
-%% Copyright (C) 2000-2007 Simone Piccardi. Permission is granted to
+%% Copyright (C) 2000-2009 Simone Piccardi. Permission is granted to
%% copy, distribute and/or modify this document under the terms of the GNU Free
%% Documentation License, Version 1.1 or any later version published by the
%% Free Software Foundation; with the Invariant Sections being "Un preambolo",
I segnali che rappresentano errori del programma (divisione per zero o
violazioni di accesso) hanno anche la caratteristica di scrivere un file di
\itindex{core~dump} \textit{core dump} che registra lo stato del processo (ed
-in particolare della memoria e dello \itindex{stack} stack) prima della
-terminazione. Questo può essere esaminato in seguito con un debugger per
-investigare sulla causa dell'errore. Lo stesso avviene se i suddetti segnali
-vengono generati con una \func{kill}.
+in particolare della memoria e dello \itindex{stack} \textit{stack}) prima
+della terminazione. Questo può essere esaminato in seguito con un debugger
+per investigare sulla causa dell'errore. Lo stesso avviene se i suddetti
+segnali vengono generati con una \func{kill}.
\section{La classificazione dei segnali}
\textbf{Sigla} & \textbf{Significato} \\
\hline
\hline
- A & L'azione predefinita è terminare il processo. \\
- B & L'azione predefinita è ignorare il segnale. \\
+ A & L'azione predefinita è terminare il processo.\\
+ B & L'azione predefinita è ignorare il segnale.\\
C & L'azione predefinita è terminare il processo e scrivere un
- \itindex{core~dump} \textit{core dump}. \\
- D & L'azione predefinita è fermare il processo. \\
- E & Il segnale non può essere intercettato. \\
+ \itindex{core~dump} \textit{core dump}.\\
+ D & L'azione predefinita è fermare il processo.\\
+ E & Il segnale non può essere intercettato.\\
F & Il segnale non può essere ignorato.\\
\hline
\end{tabular}
\textbf{Sigla} & \textbf{Standard} \\
\hline
\hline
- P & POSIX. \\
- B & BSD. \\
- L & Linux.\\
- S & SUSv2.\\
+ P & POSIX \\
+ B & BSD \\
+ L & Linux \\
+ S & SUSv2 \\
\hline
\end{tabular}
\caption{Legenda dei valori della colonna \textbf{Standard} di
file (posto nella directory corrente del processo e chiamato \file{core}) su
cui viene salvata un'immagine della memoria del processo (il cosiddetto
\itindex{core~dump} \textit{core dump}), che può essere usata da un debugger
-per esaminare lo stato dello \itindex{stack} stack e delle variabili al
-momento della ricezione del segnale.
+per esaminare lo stato dello \itindex{stack} \textit{stack} e delle variabili
+al momento della ricezione del segnale.
\begin{table}[htb]
\footnotesize
\const{SIGTRAP} &SL & C & Trappole per un Trace/breakpoint. \\
\const{SIGURG} &SLB& B & Ricezione di una \textit{urgent condition} su
un socket. \\
- \const{SIGVTALRM}&SLB& A & Virtual alarm clock. \\
+ \const{SIGVTALRM}&SLB& A & Timer di esecuzione scaduto. \\
\const{SIGXCPU} &SLB& C & Ecceduto il limite sul tempo di CPU. \\
\const{SIGXFSZ} &SLB& C & Ecceduto il limite sulla dimensione dei file. \\
\const{SIGIOT} &L & C & IOT trap. Sinonimo di \const{SIGABRT}. \\
file eseguibile è corrotto o si stanno cercando di eseguire dei dati.
Quest'ultimo caso può accadere quando si passa un puntatore sbagliato al
posto di un puntatore a funzione, o si eccede la scrittura di un vettore di
- una variabile locale, andando a corrompere lo \itindex{stack} stack. Lo
- stesso segnale viene generato in caso di overflow dello \itindex{stack}
- stack o di problemi nell'esecuzione di un gestore. Se il gestore ritorna il
- comportamento del processo è indefinito.
-\item[\const{SIGSEGV}] Il nome deriva da \textit{segment violation}, e
- significa che il programma sta cercando di leggere o scrivere in una zona di
- memoria protetta al di fuori di quella che gli è stata riservata dal
- sistema. In genere è il meccanismo della protezione della memoria che si
- accorge dell'errore ed il kernel genera il segnale. Se il gestore
- ritorna il comportamento del processo è indefinito.
+ una variabile locale, andando a corrompere lo \itindex{stack}
+ \textit{stack}. Lo stesso segnale viene generato in caso di overflow dello
+ \itindex{stack} \textit{stack} o di problemi nell'esecuzione di un gestore.
+ Se il gestore ritorna il comportamento del processo è indefinito.
+\item[\const{SIGSEGV}] Il nome deriva da \itindex{segment~violation}
+ \textit{segment violation}, e significa che il programma sta cercando di
+ leggere o scrivere in una zona di memoria protetta al di fuori di quella che
+ gli è stata riservata dal sistema. In genere è il meccanismo della
+ protezione della memoria che si accorge dell'errore ed il kernel genera il
+ segnale. Se il gestore ritorna il comportamento del processo è indefinito.
È tipico ottenere questo segnale dereferenziando un puntatore nullo o non
inizializzato leggendo al di là della fine di un vettore.
\const{SIGSEGV} questo è un segnale che viene generato di solito quando si
dereferenzia un puntatore non inizializzato, la differenza è che
\const{SIGSEGV} indica un accesso non permesso su un indirizzo esistente
- (tipo fuori dallo heap o dallo \itindex{stack} stack), mentre \const{SIGBUS}
- indica l'accesso ad un indirizzo non valido, come nel caso di un puntatore
- non allineato.
+ (tipo fuori dallo heap o dallo \itindex{stack} \textit{stack}), mentre
+ \const{SIGBUS} indica l'accesso ad un indirizzo non valido, come nel caso di
+ un puntatore non allineato.
\item[\const{SIGABRT}] Il nome deriva da \textit{abort}. Il segnale indica che
il programma stesso ha rilevato un errore che viene riportato chiamando la
funzione \func{abort} che genera questo segnale.
\subsection{I segnali di allarme}
\label{sec:sig_alarm}
-Questi segnali sono generati dalla scadenza di un timer. Il loro comportamento
-predefinito è quello di causare la terminazione del programma, ma con questi
-segnali la scelta predefinita è irrilevante, in quanto il loro uso presuppone
-sempre la necessità di un gestore. Questi segnali sono:
+Questi segnali sono generati dalla scadenza di un timer (vedi
+sez.~\ref{sec:sig_alarm_abort}). Il loro comportamento predefinito è quello di
+causare la terminazione del programma, ma con questi segnali la scelta
+predefinita è irrilevante, in quanto il loro uso presuppone sempre la
+necessità di un gestore. Questi segnali sono:
\begin{basedescript}{\desclabelwidth{2.0cm}}
\item[\const{SIGALRM}] Il nome sta per \textit{alarm}. Segnale la scadenza di
un timer misurato sul tempo reale o sull'orologio di sistema. È normalmente
usato dalla funzione \func{alarm}.
-\item[\const{SIGVTALRM}] Il nome sta per \textit{virtual alarm}. È analogo al
+\item[\const{SIVGTALRM}] Il nome sta per \textit{virtual alarm}. È analogo al
precedente ma segnala la scadenza di un timer sul tempo di CPU usato dal
processo.
-\section{La gestione dei segnali}
+\section{La gestione di base dei segnali}
\label{sec:sig_management}
I segnali sono il primo e più classico esempio di eventi asincroni, cioè di
operatori del C, senza di esse si sarebbe definita una funzione che ritorna
un puntatore a \ctyp{void} e non un puntatore ad una funzione \ctyp{void}.}
La funzione \func{signal} quindi restituisce e prende come secondo argomento
-un puntatore a una funzione di questo tipo, che è appunto il gestore del
-segnale.
-
-Il numero di segnale passato in \param{signum} può essere indicato
-direttamente con una delle costanti definite in sez.~\ref{sec:sig_standard}. Il
-gestore \param{handler} invece, oltre all'indirizzo della funzione da chiamare
-all'occorrenza del segnale, può assumere anche i due valori costanti
-\const{SIG\_IGN} con cui si dice di ignorare il segnale e \const{SIG\_DFL} per
-reinstallare l'azione predefinita.\footnote{si ricordi però che i due segnali
+un puntatore a una funzione di questo tipo, che è appunto la funzione che
+verrà usata come gestore del segnale.
+
+Il numero di segnale passato nell'argomento \param{signum} può essere indicato
+direttamente con una delle costanti definite in sez.~\ref{sec:sig_standard}.
+L'argomento \param{handler} che indica il gestore invece, oltre all'indirizzo
+della funzione da chiamare all'occorrenza del segnale, può assumere anche i
+due valori costanti \const{SIG\_IGN} e \const{SIG\_DFL}; il primo indica che
+il segnale deve essere ignorato,\footnote{si ricordi però che i due segnali
\const{SIGKILL} e \const{SIGSTOP} non possono essere né ignorati né
intercettati; l'uso di \const{SIG\_IGN} per questi segnali non ha alcun
- effetto.}
+ effetto.} mentre il secondo ripristina l'azione predefinita.\footnote{e
+ serve a tornare al comportamento di default quando non si intende più
+ gestire direttamente un segnale.}
La funzione restituisce l'indirizzo dell'azione precedente, che può essere
salvato per poterlo ripristinare (con un'altra chiamata a \func{signal}) in un
per i motivi visti in sez.~\ref{sec:sig_semantics}, può essere ottenuto
chiamando \func{sysv\_signal}, una volta che si sia definita la macro
\macro{\_XOPEN\_SOURCE}. In generale, per evitare questi problemi, l'uso di
-\func{signal} (ed ogni eventuale ridefinizione della stessa) è da evitare;
-tutti i nuovi programmi dovrebbero usare \func{sigaction}.
+\func{signal}, che tra l'altro ha un comportamento indefinito in caso di
+processo \itindex{thread} multi-\textit{thread}, è da evitare; 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 \const{SIGFPE}, \const{SIGILL}, o
\subsection{Le funzioni \func{kill} e \func{raise}}
\label{sec:sig_kill_raise}
-Come accennato in sez.~\ref{sec:sig_types}, un segnale può essere generato
-direttamente da un processo attraverso una opportuna system call. Le funzioni
-che si usano di solito per inviare un segnale generico sono due, \func{raise} e
+Come precedentemente accennato in sez.~\ref{sec:sig_types}, un segnale può
+anche essere generato direttamente nell'esecuzione di un programma, attraverso
+la chiamata ad una opportuna system call. Le funzioni che si utilizzano di
+solito per inviare un segnale generico ad un processo sono due: \func{raise} e
\func{kill}.
La prima funzione è \funcd{raise}, che è definita dallo standard ANSI C, e
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 è \errval{EINVAL} qualora si sia
specificato un numero di segnale invalido.}
\bodydesc{La funzione restituisce 0 in caso di successo e $-1$ in caso di
errore nel qual caso \var{errno} assumerà uno dei valori:
\begin{errlist}
- \item[\errcode{EINVAL}] Il segnale specificato non esiste.
- \item[\errcode{ESRCH}] Il processo selezionato non esiste.
- \item[\errcode{EPERM}] Non si hanno privilegi sufficienti ad inviare il
+ \item[\errcode{EINVAL}] il segnale specificato non esiste.
+ \item[\errcode{ESRCH}] il processo selezionato non esiste.
+ \item[\errcode{EPERM}] non si hanno privilegi sufficienti ad inviare il
segnale.
\end{errlist}}
\end{functions}
\textbf{Valore} & \textbf{Significato} \\
\hline
\hline
- $>0$ & il segnale è mandato al processo con il \acr{pid} indicato.\\
- 0 & il segnale è mandato ad ogni processo del \itindex{process~group}
+ $>0$ & Il segnale è mandato al processo con il \acr{pid} indicato.\\
+ 0 & Il segnale è mandato ad ogni processo del \itindex{process~group}
\textit{process group} del chiamante.\\
- $-1$ & il segnale è mandato ad ogni processo (eccetto \cmd{init}).\\
- $<-1$ & il segnale è mandato ad ogni processo del \textit{process group}
+ $-1$ & Il segnale è mandato ad ogni processo (eccetto \cmd{init}).\\
+ $<-1$ & Il segnale è mandato ad ogni processo del \textit{process group}
\itindex{process~group} $|\code{pid}|$.\\
\hline
\end{tabular}
mai generato prima della scadenza programmata (l'arrotondamento cioè è sempre
effettuato per eccesso).
+% TODO: verificare cose è successo con l'introduzione nel kernel con i timer
+% ad alta risoluzione
+
Una seconda causa di potenziali ritardi è che il segnale viene generato alla
scadenza del timer, ma poi deve essere consegnato al processo; se quest'ultimo
è attivo (questo è sempre vero per \const{ITIMER\_VIRT}) la consegna è
stato consegnato; in questo caso, per il comportamento dei segnali descritto
in sez.~\ref{sec:sig_sigchld}, un solo segnale sarà consegnato.
-
Dato che sia \func{alarm} che \func{setitimer} non consentono di leggere il
valore corrente di un timer senza modificarlo, è possibile usare la funzione
\funcd{getitimer}, il cui prototipo è:
utilizzando direttamente il timer del kernel.} e sia utilizzabile senza
interferenze con l'uso di \const{SIGALRM}. La funzione prende come argomenti
delle strutture di tipo \struct{timespec}, la cui definizione è riportata in
-fig.~\ref{fig:sys_timeval_struct}, che permettono di specificare un tempo con
-una precisione (teorica) fino al nanosecondo.
+fig.~\ref{fig:sys_timespec_struct}, che permette di specificare un tempo con
+una precisione 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
-\section{Gestione avanzata}
-\label{sec:sig_control}
+\section{La gestione avanzata dei segnali}
+\label{sec:sig_adv_control}
Le funzioni esaminate finora fanno riferimento alle modalità più elementari
della gestione dei segnali; non si sono pertanto ancora prese in
Ma anche questa implementazione comporta dei problemi; in questo caso infatti
non viene gestita correttamente l'interazione con gli altri segnali; se
-infatti il segnale di allarme interrompe un altro gestore, in questo caso
-l'esecuzione non riprenderà nel gestore in questione, ma nel ciclo
-principale, interrompendone inopportunamente l'esecuzione. Lo stesso tipo di
-problemi si presenterebbero se si volesse usare \func{alarm} per stabilire un
-timeout su una qualunque system call bloccante.
+infatti il segnale di allarme interrompe un altro gestore, l'esecuzione non
+riprenderà nel gestore in questione, ma nel ciclo principale, interrompendone
+inopportunamente l'esecuzione. Lo stesso tipo di problemi si presenterebbero
+se si volesse usare \func{alarm} per stabilire un timeout su una qualunque
+system call bloccante.
Un secondo esempio è quello in cui si usa il segnale per notificare una
qualche forma di evento; in genere quello che si fa in questo caso è impostare
nel gestore un opportuno flag da controllare nel corpo principale del
programma (con un codice del tipo di quello riportato in
-fig.~\ref{fig:sig_event_wrong}).
+fig.~\ref{fig:sig_event_wrong}). La logica è quella di far impostare al
+gestore (\texttt{\small 14-19}) una variabile globale preventivamente
+inizializzata nel programma principale, il quale potrà determinare,
+osservandone il contenuto, l'occorrenza o meno del segnale, e prendere le
+relative azioni conseguenti (\texttt{\small 6-11}).
\begin{figure}[!htb]
\footnotesize\centering
\label{fig:sig_event_wrong}
\end{figure}
-La logica è quella di far impostare al gestore (\texttt{\small 14-19}) una
-variabile globale preventivamente inizializzata nel programma principale, il
-quale potrà determinare, osservandone il contenuto, l'occorrenza o meno del
-segnale, e prendere le relative azioni conseguenti (\texttt{\small 6-11}).
-
Questo è il tipico esempio di caso, già citato in
sez.~\ref{sec:proc_race_cond}, in cui si genera una \itindex{race~condition}
\textit{race condition}; infatti, in una situazione in cui un segnale è già
-arrivato (e \var{flag} è già ad 1) se un altro segnale segnale arriva
-immediatamente dopo l'esecuzione del controllo (\texttt{\small 6}) ma prima
-della cancellazione del flag (\texttt{\small 7}), la sua occorrenza sarà
-perduta.
+arrivato (e \var{flag} è già ad 1) se un altro segnale arriva immediatamente
+dopo l'esecuzione del controllo (\texttt{\small 6}) ma prima della
+cancellazione del flag (\texttt{\small 7}), la sua occorrenza sarà perduta.
Questi esempi ci mostrano che per una gestione effettiva dei segnali occorrono
delle funzioni più sofisticate di quelle finora illustrate, queste hanno la
\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[\errcode{EINVAL}] Si è specificato un numero di segnale invalido o si è
+ \item[\errcode{EINVAL}] si è specificato un numero di segnale invalido o si è
cercato di installare il gestore per \const{SIGKILL} o
\const{SIGSTOP}.
- \item[\errcode{EFAULT}] Si sono specificati indirizzi non validi.
+ \item[\errcode{EFAULT}] si sono specificati indirizzi non validi.
\end{errlist}}
\end{prototype}
L'uso di questo campo permette ad esempio di risolvere il problema residuo
dell'implementazione di \code{sleep} mostrata in
fig.~\ref{fig:sig_sleep_incomplete}. In quel caso infatti se il segnale di
-allarme avesse interrotto un altro gestore questo non sarebbe stato
-eseguito correttamente; la cosa poteva essere prevenuta installando gli altri
-gestori usando \var{sa\_mask} per bloccare \const{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 tab.~\ref{tab:sig_sa_flag}.
+allarme avesse interrotto un altro gestore questo non sarebbe stato eseguito
+correttamente; la cosa poteva essere prevenuta installando gli altri gestori
+usando \var{sa\_mask} per bloccare \const{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
+tab.~\ref{tab:sig_sa_flag}.
\begin{table}[htb]
\footnotesize
fermato da uno dei segnali \const{SIGSTOP},
\const{SIGTSTP}, \const{SIGTTIN} o
\const{SIGTTOU}.\\
- \const{SA\_ONESHOT} & Ristabilisce l'azione per il segnale al valore
+ \const{SA\_RESETHAND}& Ristabilisce l'azione per il segnale al valore
predefinito una volta che il gestore è stato
lanciato, riproduce cioè il comportamento della
semantica inaffidabile.\\
- \const{SA\_RESETHAND}& Sinonimo di \const{SA\_ONESHOT}. \\
+ \const{SA\_ONESHOT} & Nome obsoleto, sinonimo non standard di
+ \const{SA\_RESETHAND}; da evitare.\\
+ \const{SA\_ONSTACK} & Stabilisce l'uso di uno \itindex{stack}
+ \textit{stack} alternativo per l'esecuzione del
+ gestore (vedi
+ sez.~\ref{sec:sig_specific_features}).\\
\const{SA\_RESTART} & Riavvia automaticamente le \textit{slow system
call} quando vengono interrotte dal suddetto
segnale; riproduce cioè il comportamento standard
di BSD.\index{system~call~lente}\\
- \const{SA\_NOMASK} & Evita che il segnale corrente sia bloccato durante
+ \const{SA\_NODEFER} & Evita che il segnale corrente sia bloccato durante
l'esecuzione del gestore.\\
- \const{SA\_NODEFER} & Sinonimo di \const{SA\_NOMASK}.\\
+ \const{SA\_NOMASK} & Nome obsoleto, sinonimo non standard di
+ \const{SA\_NODEFER}.\\
\const{SA\_SIGINFO} & Deve essere specificato quando si vuole usare un
gestore in forma estesa usando
- \var{sa\_sigaction} al posto di \var{sa\_handler}.\\
- \const{SA\_ONSTACK} & Stabilisce l'uso di uno \itindex{stack} stack
- alternativo per l'esecuzione del gestore (vedi
- sez.~\ref{sec:sig_specific_features}).\\
+ \var{sa\_sigaction} al posto di
+ \var{sa\_handler}.\\
+ \const{SA\_NOCLDWAIT}& Se il segnale è \const{SIGCHLD} allora i processi
+ figli non diventano \textit{zombie} quando
+ terminano.\footnotemark \\
\hline
\end{tabular}
\caption{Valori del campo \var{sa\_flag} della struttura \struct{sigaction}.}
\label{tab:sig_sa_flag}
\end{table}
-% TODO con il 2.6 sono stati aggiunti SA_NOCLDWAIT e altro, documentare
+\footnotetext{questa funzionalità è stata introdotta nel kernel 2.6 e va a
+ modificare il comportamento di \func{waitpid}.}
Come si può notare in fig.~\ref{fig:sig_sigaction} \func{sigaction} permette
-di utilizzare due forme diverse di gestore,\footnote{La possibilità è prevista
+di utilizzare due forme diverse di gestore,\footnote{la possibilità è prevista
dallo standard POSIX.1b, ed è stata aggiunta nei kernel della serie 2.1.x
con l'introduzione dei segnali real-time (vedi
sez.~\ref{sec:sig_real_time}); in precedenza era possibile ottenere alcune
addizionale di tipo \var{sigcontext}, che adesso è deprecato.} da
specificare, a seconda dell'uso o meno del flag \const{SA\_SIGINFO},
rispettivamente attraverso i campi \var{sa\_sigaction} o
-\var{sa\_handler},\footnote{i due tipi devono essere usati in maniera
+\var{sa\_handler},\footnote{i due campi devono essere usati in maniera
alternativa, in certe implementazioni questi campi vengono addirittura
definiti come \ctyp{union}.} Quest'ultima è quella classica usata anche con
\func{signal}, mentre la prima permette di usare un gestore più complesso, in
causato l'emissione del segnale.
In generale \var{si\_code} contiene, per i segnali generici, per quelli
-real-time e per tutti quelli inviati tramite \func{kill}, informazioni circa
-l'origine del segnale (se generato dal kernel, da un timer, da \func{kill},
-ecc.). Alcuni segnali però usano \var{si\_code} per fornire una informazione
-specifica: ad esempio i vari segnali di errore (\const{SIGFPE},
-\const{SIGILL}, \const{SIGBUS} e \const{SIGSEGV}) lo usano per fornire
-maggiori dettagli riguardo l'errore (come il tipo di errore aritmetico, di
-istruzione illecita o di violazione di memoria) mentre alcuni segnali di
+real-time e per tutti quelli inviati tramite da un processo con \func{kill} o
+affini, le informazioni circa l'origine del segnale stesso, ad esempio se
+generato dal kernel, da un timer, da \func{kill}, ecc. Il valore viene sempre
+espresso come una costante,\footnote{le definizioni di tutti i valori
+ possibili si trovano in \file{bits/siginfo.h}.} ed i valori possibili in
+questo caso sono riportati in tab.~\ref{tab:sig_sa_code_generic}.
+
+\begin{table}[!htb]
+ \footnotesize
+ \centering
+ \begin{tabular}[c]{|l|p{8cm}|}
+ \hline
+ \textbf{Valore} & \textbf{Significato} \\
+ \hline
+ \hline
+ \const{SI\_USER} & generato da \func{kill} o \func{raise}.\\
+ \const{SI\_KERNEL} & inviato dal kernel.\\
+ \const{SI\_QUEUE} & inviato con \func{sigqueue} (vedi
+ sez.~\ref{sec:sig_real_time}).\\
+ \const{SI\_TIMER} & scadenza di un POSIX timer
+ (vedi sez.~\ref{sec:sig_timer_adv}).\\
+ \const{SI\_MESGQ} & inviato al cambiamento di stato di una coda di
+ messaggi POSIX (vedi
+ sez.~\ref{sec:ipc_posix_mq}).\footnotemark\\
+ \const{SI\_ASYNCIO}& una operazione di I/O asincrono (vedi
+ sez.~\ref{sec:file_asyncronous_access}) è stata
+ completata.\\
+ \const{SI\_SIGIO} & segnale di \const{SIGIO} da una coda (vedi
+ sez.~\ref{sec:file_asyncronous_operation}).\\
+ \const{SI\_TKILL} & inviato da \func{tkill} o \func{tgkill} (vedi
+ sez.~\ref{cha:threads_xxx}).\footnotemark\\
+ \hline
+ \end{tabular}
+ \caption{Valori del campo \var{sa\_code} della struttura \struct{sigaction}
+ per i segnali generici.}
+ \label{tab:sig_sa_code_generic}
+\end{table}
+
+\footnotetext[17]{introdotto con il kernel 2.6.6.}
+\footnotetext{introdotto con il kernel 2.4.19.}
+
+Nel caso di alcuni segnali però il valore di \var{si\_code} viene usato per
+fornire una informazione specifica relativa alle motivazioni della ricezione
+dello stesso; ad esempio i vari segnali di errore (\const{SIGILL},
+\const{SIGFPE}, \const{SIGSEGV} e \const{SIGBUS}) lo usano per fornire
+maggiori dettagli riguardo l'errore, come il tipo di errore aritmetico, di
+istruzione illecita o di violazione di memoria; mentre alcuni segnali di
controllo (\const{SIGCHLD}, \const{SIGTRAP} e \const{SIGPOLL}) forniscono
-altre informazioni specifiche. In tutti i casi il valore del campo è
-riportato attraverso delle costanti (le cui definizioni si trovano
-\file{bits/siginfo.h}) il cui elenco dettagliato è disponibile nella pagina di
-manuale di \func{sigaction}.
+altre informazioni specifiche.
+
+In questo caso il valore del campo \var{si\_code} deve essere verificato nei
+confronti delle diverse costanti previste per ciascuno di detti
+segnali;\footnote{dato che si tratta di una costante, e non di una maschera
+ binaria, i valori numerici vengono riutilizzati e ciascuno di essi avrà un
+ significato diverso a seconda del segnale a cui è associato.} l'elenco
+dettagliato dei nomi di queste costanti è riportato nelle diverse sezioni di
+tab.~\ref{tab:sig_sa_code_special} che sono state ordinate nella sequenza in
+cui si sono appena citati i rispettivi segnali.\footnote{il prefisso del nome
+ indica comunque in maniera diretta il segnale a cui le costanti fanno
+ riferimento.}
+
+\begin{table}[!htb]
+ \footnotesize
+ \centering
+ \begin{tabular}[c]{|l|p{8cm}|}
+ \hline
+ \textbf{Valore} & \textbf{Significato} \\
+ \hline
+ \hline
+ \const{ILL\_ILLOPC} & codice di operazione illegale.\\
+ \const{ILL\_ILLOPN} & operando illegale.\\
+ \const{ILL\_ILLADR} & modo di indirizzamento illegale.\\
+ \const{ILL\_ILLTRP} & trappola di processore illegale.\\
+ \const{ILL\_PRVOPC} & codice di operazione privilegiato.\\
+ \const{ILL\_PRVREG} & registro privilegiato.\\
+ \const{ILL\_COPROC} & errore del coprocessore.\\
+ \const{ILL\_BADSTK} & errore nello stack interno.\\
+ \hline
+ \const{FPE\_INTDIV} & divisione per zero intera.\\
+ \const{FPE\_INTOVF} & overflow intero.\\
+ \const{FPE\_FLTDIV} & divisione per zero in virgola mobile.\\
+ \const{FPE\_FLTOVF} & overflow in virgola mobile.\\
+ \const{FPE\_FLTUND} & underflow in virgola mobile.\\
+ \const{FPE\_FLTRES} & risultato in virgola mobile non esatto.\\
+ \const{FPE\_FLTINV} & operazione in virgola mobile non valida.\\
+ \const{FPE\_FLTSUB} & mantissa? fuori intervallo.\\
+ \hline
+ \const{SEGV\_MAPERR} & indirizzo non mappato.\\
+ \const{SEGV\_ACCERR} & permessi non validi per l'indirizzo.\\
+ \hline
+ \const{BUS\_ADRALN} & allineamento dell'indirizzo non valido.\\
+ \const{BUS\_ADRERR} & indirizzo fisico inesistente.\\
+ \const{BUS\_OBJERR} & errore hardware sull'indirizzo.\\
+ \hline
+ \const{TRAP\_BRKPT} & breakpoint sul processo.\\
+ \const{TRAP\_TRACE} & trappola di tracciamento del processo.\\
+ \hline
+ \const{CLD\_EXITED} & il figlio è uscito.\\
+ \const{CLD\_KILLED} & il figlio è stato terminato.\\
+ \const{CLD\_DUMPED} & il figlio è terminato in modo anormale.\\
+ \const{CLD\_TRAPPED} & un figlio tracciato ha raggiunto una trappola.\\
+ \const{CLD\_STOPPED} & il figlio è stato fermato.\\
+ \const{CLD\_CONTINUED}& il figlio è ripartito.\\
+ \hline
+ \const{POLL\_IN} & disponibili dati in ingresso.\\
+ \const{POLL\_OUT} & spazio disponibile sul buffer di uscita.\\
+ \const{POLL\_MSG} & disponibili messaggi in ingresso.\\
+ \const{POLL\_ERR} & errore di I/O.\\
+ \const{POLL\_PRI} & disponibili dati di alta priorità in ingresso.\\
+ \const{POLL\_HUP} & il dispositivo è stato disconnesso.\\
+ \hline
+ \end{tabular}
+ \caption{Valori del campo \var{sa\_code} della struttura \struct{sigaction}
+ impostati rispettivamente dai segnali \const{SIGILL}, \const{SIGFPE},
+ \const{SIGSEGV}, \const{SIGBUS}, \const{SIGCHLD}, \const{SIGTRAP} e
+ \const{SIGPOLL}.}
+ \label{tab:sig_sa_code_special}
+\end{table}
-Il resto della struttura è definito come \ctyp{union} ed i valori
-eventualmente presenti dipendono dal segnale, così \const{SIGCHLD} ed i
+Il resto della struttura \struct{siginfo\_t} è definito come \ctyp{union} ed i
+valori eventualmente presenti dipendono dal segnale, così \const{SIGCHLD} ed i
segnali real-time (vedi sez.~\ref{sec:sig_real_time}) inviati tramite
\func{kill} avvalorano \var{si\_pid} e \var{si\_uid} coi valori corrispondenti
-al processo che ha emesso il segnale, \const{SIGILL}, \const{SIGFPE},
-\const{SIGSEGV} e \const{SIGBUS} avvalorano \var{si\_addr} con l'indirizzo in
-cui è avvenuto l'errore, \const{SIGIO} (vedi
+al processo che ha emesso il segnale, \const{SIGCHLD} avvalora anche i campi
+\const{si\_status}, \const{si\_utime} and \const{si\_stime} che indicano
+rispettivamente lo stato di uscita, l'\textit{user time} e il \textit{system
+ time} (vedi sez.~\ref{sec:sys_cpu_times}) usati dal processo;
+\const{SIGILL}, \const{SIGFPE}, \const{SIGSEGV} e \const{SIGBUS} avvalorano
+\var{si\_addr} con l'indirizzo in cui è avvenuto l'errore, \const{SIGIO} (vedi
sez.~\ref{sec:file_asyncronous_io}) avvalora \var{si\_fd} con il numero del
-file descriptor e \var{si\_band} per i \itindex{out-of-band} dati urgenti (vedi
-sez.~\ref{sec:TCP_urgent_data}) su un socket.
+file descriptor e \var{si\_band} per i \itindex{out-of-band} dati urgenti
+(vedi sez.~\ref{sec:TCP_urgent_data}) su un socket.
Benché sia possibile usare nello stesso programma sia \func{sigaction} che
\func{signal} occorre molta attenzione, in quanto le due funzioni possono
Per questo motivo si è provveduto, per mantenere un'interfaccia semplificata
che abbia le stesse caratteristiche di \func{signal}, a definire attraverso
-\func{sigaction} una funzione equivalente, il cui codice è riportato in
-fig.~\ref{fig:sig_Signal_code} (il codice completo si trova nel file
-\file{SigHand.c} nei sorgenti allegati). Si noti come, essendo la funzione
-estremamente semplice, è definita come \direct{inline}.\footnote{la direttiva
- \direct{inline} viene usata per dire al compilatore di trattare la funzione
- cui essa fa riferimento in maniera speciale inserendo il codice direttamente
- nel testo del programma. Anche se i compilatori più moderni sono in grado
- di effettuare da soli queste manipolazioni (impostando le opportune
- ottimizzazioni) questa è una tecnica usata per migliorare le prestazioni per
- le funzioni piccole ed usate di frequente (in particolare nel kernel, dove
- in certi casi le ottimizzazioni dal compilatore, tarate per l'uso in user
- space, non sono sempre adatte). In tal caso infatti le istruzioni per creare
- un nuovo frame nello \itindex{stack} stack per chiamare la funzione
- costituirebbero una parte rilevante del codice, appesantendo inutilmente il
- programma. Originariamente questo comportamento veniva ottenuto con delle
- macro, ma queste hanno tutta una serie di problemi di sintassi nel passaggio
- degli argomenti (si veda ad esempio \cite{PratC}) che in questo modo possono
- essere evitati.}
+\func{sigaction} una funzione equivalente \func{Signal}, il cui codice è
+riportato in fig.~\ref{fig:sig_Signal_code} (il codice completo si trova nel
+file \file{SigHand.c} nei sorgenti allegati). Si noti come, essendo la
+funzione estremamente semplice, essa è definita come
+\direct{inline};\footnote{la direttiva \direct{inline} viene usata per dire al
+ compilatore di trattare la funzione cui essa fa riferimento in maniera
+ speciale inserendo il codice direttamente nel testo del programma. Anche se
+ i compilatori più moderni sono in grado di effettuare da soli queste
+ manipolazioni (impostando le opportune ottimizzazioni) questa è una tecnica
+ usata per migliorare le prestazioni per le funzioni piccole ed usate di
+ frequente (in particolare nel kernel, dove in certi casi le ottimizzazioni
+ dal compilatore, tarate per l'uso in user space, non sono sempre adatte). In
+ tal caso infatti le istruzioni per creare un nuovo frame nello
+ \itindex{stack} \textit{stack} per chiamare la funzione costituirebbero una
+ parte rilevante del codice, appesantendo inutilmente il programma.
+ Originariamente questo comportamento veniva ottenuto con delle macro, ma
+ queste hanno tutta una serie di problemi di sintassi nel passaggio degli
+ argomenti (si veda ad esempio \cite{PratC}) che in questo modo possono
+ essere evitati.} per semplificare ulteriormente la definizione si è poi
+definito un apposito tipo \texttt{SigFunc}.
\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[\errcode{EINVAL}] Si è specificato un numero di segnale invalido.
- \item[\errcode{EFAULT}] Si sono specificati indirizzi non validi.
+ \item[\errcode{EINVAL}] si è specificato un numero di segnale invalido.
+ \item[\errcode{EFAULT}] si sono specificati indirizzi non validi.
\end{errlist}}
\end{prototype}
\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[\errcode{EINVAL}] Si è specificato un numero di segnale invalido.
- \item[\errcode{EFAULT}] Si sono specificati indirizzi non validi.
+ \item[\errcode{EINVAL}] si è specificato un numero di segnale invalido.
+ \item[\errcode{EFAULT}] si sono specificati indirizzi non validi.
\end{errlist}}
\end{prototype}
rispetto a quanto potrebbe essere in un qualunque momento successivo.
Una delle caratteristiche di BSD, disponibile anche in Linux, è la possibilità
-di usare uno \itindex{stack} stack alternativo per i segnali; è cioè possibile
-fare usare al sistema un altro \itindex{stack} stack (invece di quello
-relativo al processo, vedi sez.~\ref{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:
+di usare uno \itindex{stack} \textit{stack} alternativo per i segnali; è cioè
+possibile fare usare al sistema un altro \itindex{stack} \textit{stack}
+(invece di quello relativo al processo, vedi sez.~\ref{sec:proc_mem_layout})
+solo durante l'esecuzione di un gestore. L'uso di uno \textit{stack}
+alternativo è del tutto trasparente ai gestori, occorre però seguire una certa
+procedura:
\begin{enumerate}
\item Allocare un'area di memoria di dimensione sufficiente da usare come
- stack alternativo;
+ \textit{stack} alternativo;
\item Usare la funzione \func{sigaltstack} per rendere noto al sistema
- l'esistenza e la locazione dello stack alternativo;
+ l'esistenza e la locazione dello \textit{stack} alternativo;
\item Quando si installa un gestore occorre usare \func{sigaction}
specificando il flag \const{SA\_ONSTACK} (vedi tab.~\ref{tab:sig_sa_flag})
- per dire al sistema di usare lo stack alternativo durante l'esecuzione del
- gestore.
+ per dire al sistema di usare lo \textit{stack} alternativo durante
+ l'esecuzione del gestore.
\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 \itindex{stack} stack di
-segnali e di norma è sufficiente per tutti gli usi normali.
+prima delle due è la dimensione canonica per uno \itindex{stack}
+\textit{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
-\itindex{stack} stack di dimensione sufficiente.
-
-Come accennato, per poter essere usato, lo \itindex{stack} stack per i segnali
-deve essere indicato al sistema attraverso la funzione \funcd{sigaltstack}; il
-suo prototipo è:
+il gestore e la dimensione di uno \textit{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 \itindex{stack} \textit{stack} di dimensione sufficiente.
+
+Come accennato, per poter essere usato, lo \itindex{stack} \textit{stack} per
+i segnali deve essere indicato al sistema attraverso la funzione
+\funcd{sigaltstack}; il suo prototipo è:
\begin{prototype}{signal.h}
{int sigaltstack(const stack\_t *ss, stack\_t *oss)}
-Installa un nuovo stack per i segnali.
+Installa un nuovo \textit{stack} per i segnali.
\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[\errcode{ENOMEM}] La dimensione specificata per il nuovo stack è minore
- di \const{MINSIGSTKSZ}.
- \item[\errcode{EPERM}] Uno degli indirizzi non è valido.
- \item[\errcode{EFAULT}] Si è cercato di cambiare lo stack alternativo mentre
- questo è attivo (cioè il processo è in esecuzione su di esso).
+ \item[\errcode{ENOMEM}] la dimensione specificata per il nuovo
+ \textit{stack} è minore di \const{MINSIGSTKSZ}.
+ \item[\errcode{EPERM}] uno degli indirizzi non è valido.
+ \item[\errcode{EFAULT}] si è cercato di cambiare lo \textit{stack}
+ alternativo mentre questo è attivo (cioè il processo è in esecuzione su di
+ esso).
\item[\errcode{EINVAL}] \param{ss} non è nullo e \var{ss\_flags} contiene un
valore diverso da zero che non è \const{SS\_DISABLE}.
\end{errlist}}
La funzione prende come argomenti puntatori ad una struttura di tipo
\var{stack\_t}, definita in fig.~\ref{fig:sig_stack_t}. I due valori
\param{ss} e \param{oss}, se non nulli, indicano rispettivamente il nuovo
-\itindex{stack} stack da installare e quello corrente (che viene restituito
-dalla funzione per un successivo ripristino).
+\itindex{stack} \textit{stack} da installare e quello corrente (che viene
+restituito dalla funzione per un successivo ripristino).
\begin{figure}[!htb]
\footnotesize \centering
\end{figure}
Il campo \var{ss\_sp} di \struct{stack\_t} indica l'indirizzo base dello
-\itindex{stack} stack, mentre \var{ss\_size} ne indica la dimensione; il campo
-\var{ss\_flags} invece indica lo stato dello stack. Nell'indicare un nuovo
-stack occorre inizializzare \var{ss\_sp} e \var{ss\_size} rispettivamente al
-puntatore e alla dimensione della memoria allocata, mentre \var{ss\_flags}
-deve essere nullo. Se invece si vuole disabilitare uno stack occorre indicare
-\const{SS\_DISABLE} come valore di \var{ss\_flags} e gli altri valori saranno
-ignorati.
+\itindex{stack} \textit{stack}, mentre \var{ss\_size} ne indica la dimensione;
+il campo \var{ss\_flags} invece indica lo stato dello \textit{stack}.
+Nell'indicare un nuovo \textit{stack} occorre inizializzare \var{ss\_sp} e
+\var{ss\_size} rispettivamente al puntatore e alla dimensione della memoria
+allocata, mentre \var{ss\_flags} deve essere nullo. Se invece si vuole
+disabilitare uno \textit{stack} occorre indicare \const{SS\_DISABLE} come
+valore di \var{ss\_flags} e gli altri valori saranno ignorati.
Se \param{oss} non è nullo verrà restituito dalla funzione indirizzo e
-dimensione dello \itindex{stack} stack corrente nei relativi campi, mentre
-\var{ss\_flags} potrà assumere il valore \const{SS\_ONSTACK} se il processo è
-in esecuzione sullo stack alternativo (nel qual caso non è possibile
-cambiarlo) e \const{SS\_DISABLE} se questo non è abilitato.
-
-In genere si installa uno \itindex{stack} stack alternativo per i segnali
-quando si teme di avere problemi di esaurimento dello stack standard o di
-superamento di un limite (vedi sez.~\ref{sec:sys_resource_limit}) imposto con
-chiamate del tipo \code{setrlimit(RLIMIT\_STACK, \&rlim)}. In tal caso
-infatti si avrebbe un segnale di \const{SIGSEGV}, che potrebbe essere gestito
-soltanto avendo abilitato uno \itindex{stack} stack alternativo.
-
-Si tenga presente che le funzioni chiamate durante l'esecuzione sullo stack
-alternativo continueranno ad usare quest'ultimo, che, al contrario di quanto
-avviene per lo \itindex{stack} stack ordinario dei processi, non si accresce
-automaticamente (ed infatti eccederne le dimensioni può portare a conseguenze
-imprevedibili). Si ricordi infine che una chiamata ad una funzione della
-famiglia \func{exec} cancella ogni stack alternativo.
+dimensione dello \itindex{stack} \textit{stack} corrente nei relativi campi,
+mentre \var{ss\_flags} potrà assumere il valore \const{SS\_ONSTACK} se il
+processo è in esecuzione sullo \textit{stack} alternativo (nel qual caso non è
+possibile cambiarlo) e \const{SS\_DISABLE} se questo non è abilitato.
+
+In genere si installa uno \itindex{stack} \textit{stack} alternativo per i
+segnali quando si teme di avere problemi di esaurimento dello \textit{stack}
+standard o di superamento di un limite (vedi
+sez.~\ref{sec:sys_resource_limit}) imposto con chiamate del tipo
+\code{setrlimit(RLIMIT\_STACK, \&rlim)}. In tal caso infatti si avrebbe un
+segnale di \const{SIGSEGV}, che potrebbe essere gestito soltanto avendo
+abilitato uno \itindex{stack} \textit{stack} alternativo.
+
+Si tenga presente che le funzioni chiamate durante l'esecuzione sullo
+\textit{stack} alternativo continueranno ad usare quest'ultimo, che, al
+contrario di quanto avviene per lo \itindex{stack} \textit{stack} ordinario
+dei processi, non si accresce automaticamente (ed infatti eccederne le
+dimensioni può portare a conseguenze imprevedibili). Si ricordi infine che
+una chiamata ad una funzione della famiglia \func{exec} cancella ogni
+\textit{stack} alternativo.
Abbiamo visto in fig.~\ref{fig:sig_sleep_incomplete} come si possa usare
\func{longjmp} per uscire da un gestore rientrando direttamente nel corpo
\headdecl{setjmp.h}
\funcdecl{int sigsetjmp(sigjmp\_buf env, int savesigs)} Salva il contesto
- dello stack per un \index{salto~non-locale} salto non-locale.
+ dello \textit{stack} per un \index{salto~non-locale} salto non-locale.
\funcdecl{void siglongjmp(sigjmp\_buf env, int val)} Esegue un salto
non-locale su un precedente contesto.
\end{functions}
Le due funzioni prendono come primo argomento la variabile su cui viene
-salvato il contesto dello \itindex{stack} stack per permettere il
+salvato il contesto dello \itindex{stack} \textit{stack} per permettere il
\index{salto~non-locale} salto non-locale; nel caso specifico essa è di tipo
\type{sigjmp\_buf}, e non \type{jmp\_buf} come per le analoghe di
sez.~\ref{sec:proc_longjmp} in quanto in questo caso viene salvata anche la
\func{longjmp}.
+\subsection{Criteri di programmazione per i gestori dei segnali}
+\label{sec:sig_signal_handler}
+
+Abbiamo finora parlato dei gestori dei segnali come funzioni chiamate in
+corrispondenza della consegna di un segnale. In realtà un gestore non può
+essere una funzione qualunque, in quanto esso può essere eseguito in
+corrispondenza all'interruzione in un punto qualunque del programma principale,
+ed ad esempio può essere problematico chiamare all'interno di un gestore di
+segnali la stessa funzione che dal segnale è stata interrotta.
+
+\index{funzioni!sicure|(}
+
+Il concetto è comunque più generale e porta ad una distinzione fra quelle che
+che POSIX chiama \textsl{funzioni insicure} (\textit{n'Usane function}) e
+\textsl{funzioni sicure} (\textit{safe function}); quando un segnale
+interrompe una funzione insicura ed il gestore chiama al suo interno una
+funzione insicura il sistema può dare luogo ad un comportamento indefinito.
+
+Tutto questo significa che un gestore di segnale deve essere programmato con
+molta cura per evitare questa evenienza, pertanto è non è possibile chiamare
+al suo interno una funzione qualunque, e si può ricorrere soltanto all'uso di
+funzioni sicure.
+
+L'elenco delle funzioni sicure varia a secondo dello standard a cui si fa
+riferimento, secondo quanto riportato dallo standard POSIX 1003.1 nella
+revisione del 2003, le ``\textit{signal safe function}'' che possono essere
+chiamate anche all'interno di un gestore di segnali sono quelle della lista
+riportata in fig.~\ref{fig:sig_safe_functions}.
+
+\begin{figure}[!htb]
+ \footnotesize \centering
+ \begin{minipage}[c]{15cm}
+ \func{\_exit}, \func{abort}, \func{accept}, \func{access},
+ \func{aio\_error} \func{aio\_return}, \func{aio\_suspend}, \func{alarm},
+ \func{bind}, \func{cfgetispeed}, \func{cfgetospeed}, \func{cfsetispeed},
+ \func{cfsetospeed}, \func{chdir}, \func{chmod}, \func{chown},
+ \func{clock\_gettime}, \func{close}, \func{connect}, \func{creat},
+ \func{dup}, \func{dup2}, \func{execle}, \func{execve}, \func{fchmod},
+ \func{fchown}, \func{fcntl}, \func{fdatasync}, \func{fork},
+ \func{fpathconf}, \func{fstat}, \func{fsync}, \func{ftruncate},
+ \func{getegid}, \func{geteuid}, \func{getgid}, \func{getgroups},
+ \func{getpeername}, \func{getpgrp}, \func{getpid}, \func{getppid},
+ \func{getsockname}, \func{getsockopt}, \func{getuid}, \func{kill},
+ \func{link}, \func{listen}, \func{lseek}, \func{lstat}, \func{mkdir},
+ \func{mkfifo}, \func{open}, \func{pathconf}, \func{pause}, \func{pipe},
+ \func{poll}, \func{posix\_trace\_event}, \func{pselect}, \func{raise},
+ \func{read}, \func{readlink}, \func{recv}, \func{recvfrom},
+ \func{recvmsg}, \func{rename}, \func{rmdir}, \func{select},
+ \func{sem\_post}, \func{send}, \func{sendmsg}, \func{sendto},
+ \func{setgid}, \func{setpgid}, \func{setsid}, \func{setsockopt},
+ \func{setuid}, \func{shutdown}, \func{sigaction}, \func{sigaddset},
+ \func{sigdelset}, \func{sigemptyset}, \func{sigfillset},
+ \func{sigismember}, \func{signal}, \func{sigpause}, \func{sigpending},
+ \func{sigprocmask}, \func{sigqueue}, \func{sigset}, \func{sigsuspend},
+ \func{sleep}, \func{socket}, \func{socketpair}, \func{stat},
+ \func{symlink}, \func{sysconf}, \func{tcdrain}, \func{tcflow},
+ \func{tcflush}, \func{tcgetattr}, \func{tcgetgrp}, \func{tcsendbreak},
+ \func{tcsetattr}, \func{tcsetpgrp}, \func{time}, \func{timer\_getoverrun},
+ \func{timer\_gettime}, \func{timer\_settime}, \func{times}, \func{umask},
+ \func{uname}, \func{unlink}, \func{utime}, \func{wait}, \func{waitpid},
+ \func{write}.
+ \end{minipage}
+ \normalsize
+ \caption{Elenco delle funzioni sicure secondo lo standard POSIX
+ 1003.1-2003.}
+ \label{fig:sig_safe_functions}
+\end{figure}
+
+\index{funzioni!sicure|)}
+
+Per questo motivo è opportuno mantenere al minimo indispensabile le operazioni
+effettuate all'interno di un gestore di segnali, qualora si debbano compiere
+operazioni complesse è sempre preferibile utilizzare la tecnica in cui si usa
+il gestore per impostare il valore di una qualche variabile globale, e poi si
+eseguono le operazioni complesse nel programma verificando (con tutti gli
+accorgimenti visti in precedenza) il valore di questa variabile tutte le volte
+che si è rilevata una interruzione dovuta ad un segnale.
+
+
+\section{Funzionalità avanzate}
+\label{sec:sig_advanced_signal}
+
+
+Tratteremo in questa ultima sezione alcune funzionalità avanzate relativa ai
+segnali ed in generale ai meccanismi di notifica, a partire dalla funzioni
+introdotte per la gestione dei cosiddetti ``\textsl{segnali real-time}'', alla
+gestione avanzata delle temporizzazioni e le nuove interfacce per la gestione
+di segnali ed eventi attraverso l'uso di file descriptor.
\subsection{I segnali real-time}
\label{sec:sig_real_time}
-
Lo standard POSIX.1b, nel definire una serie di nuove interfacce per i servizi
real-time, ha introdotto una estensione del modello classico dei segnali che
presenta dei significativi miglioramenti,\footnote{questa estensione è stata
certi segnali ha la precedenza rispetto ad altri.
\end{basedescript}
-
Per poter superare queste limitazioni lo standard ha introdotto delle nuove
caratteristiche, che sono state associate ad una nuova classe di segnali, che
vengono chiamati \textsl{segnali real-time}, in particolare le funzionalità
\bodydesc{La funzione restituisce 0 in caso di successo e $-1$ in caso di
errore, nel qual caso \var{errno} assumerà uno dei valori:
\begin{errlist}
- \item[\errcode{EAGAIN}] La coda è esaurita, ci sono già \const{SIGQUEUE\_MAX}
- segnali in attesa si consegna.
- \item[\errcode{EPERM}] Non si hanno privilegi appropriati per inviare il
+ \item[\errcode{EAGAIN}] la coda è esaurita, ci sono già
+ \const{SIGQUEUE\_MAX} segnali in attesa si consegna.
+ \item[\errcode{EPERM}] non si hanno privilegi appropriati per inviare il
segnale al processo specificato.
- \item[\errcode{ESRCH}] Il processo \param{pid} non esiste.
- \item[\errcode{EINVAL}] Si è specificato un valore non valido per
+ \item[\errcode{ESRCH}] il processo \param{pid} non esiste.
+ \item[\errcode{EINVAL}] si è specificato un valore non valido per
\param{signo}.
\end{errlist}
ed inoltre \errval{ENOMEM}.}
sez.~\ref{sec:sys_limits}; il suo valore minimo secondo lo standard,
\const{\_POSIX\_SIGQUEUE\_MAX}, è pari a 32. Nel caso di Linux questo è uno
dei parametri del kernel impostabili sia con \func{sysctl}, che scrivendolo
- direttamente in \file{/proc/sys/kernel/rtsig-max}, il valore predefinito è
- di 1024.} nella coda dei segnali real-time) esso viene inserito e diventa
+ direttamente in \procfile{/proc/sys/kernel/rtsig-max}, il valore predefinito
+ è di 1024.} 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
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
-modo nel caso dei thread, in cui si possono usare i segnali real-time come
-meccanismi di comunicazione elementare; la prima di queste funzioni è
-\funcd{sigwait}, il cui prototipo è:
+modo nel caso dei \itindex{thread} \textit{thread}, in cui si possono usare i
+segnali real-time come meccanismi di comunicazione elementare; la prima di
+queste funzioni è \funcd{sigwait}, il cui prototipo è:
\begin{prototype}{signal.h}
{int sigwait(const sigset\_t *set, int *sig)}
\bodydesc{La funzione restituisce 0 in caso di successo e $-1$ in caso di
errore, nel qual caso \var{errno} assumerà uno dei valori:
\begin{errlist}
- \item[\errcode{EINTR}] La funzione è stata interrotta.
- \item[\errcode{EINVAL}] Si è specificato un valore non valido per
+ \item[\errcode{EINTR}] la funzione è stata interrotta.
+ \item[\errcode{EINVAL}] si è specificato un valore non valido per
\param{set}.
\end{errlist}
ed inoltre \errval{EFAULT}.}
prevedibile.
Lo standard POSIX.1b definisce altre due funzioni, anch'esse usate
-prevalentemente con i thread; \funcd{sigwaitinfo} e \funcd{sigtimedwait}, i
-relativi prototipi sono:
+prevalentemente con i \itindex{thread} \textit{thread}; \funcd{sigwaitinfo} e
+\funcd{sigtimedwait}, i relativi prototipi sono:
\begin{functions}
\headdecl{signal.h}
errore, nel qual caso \var{errno} assumerà uno dei valori già visti per
\func{sigwait}, ai quali si aggiunge, per \func{sigtimedwait}:
\begin{errlist}
- \item[\errcode{EAGAIN}] Si è superato il timeout senza che un segnale atteso
+ \item[\errcode{EAGAIN}] si è superato il timeout senza che un segnale atteso
fosse emesso.
\end{errlist}
}
immediatamente; in questo modo si può eliminare un segnale dalla coda senza
dover essere bloccati qualora esso non sia presente.
+\itindbeg{thread}
+
L'uso di queste funzioni è principalmente associato alla gestione dei segnali
-con i thread. In genere esse vengono chiamate dal thread incaricato della
-gestione, che al ritorno della funzione esegue il codice che usualmente
-sarebbe messo nel gestore, per poi ripetere la chiamata per mettersi in attesa
-del segnale successivo. Questo ovviamente comporta che non devono essere
-installati gestori, che solo il thread di gestione deve usare \func{sigwait} e
-che, per evitare che venga eseguita l'azione predefinita, i segnali gestiti in
-questa maniera devono essere mascherati per tutti i thread, compreso quello
-dedicato alla gestione, che potrebbe riceverlo fra due chiamate successive.
+con i \textit{thread}. In genere esse vengono chiamate dal \textit{thread}
+incaricato della gestione, che al ritorno della funzione esegue il codice che
+usualmente sarebbe messo nel gestore, per poi ripetere la chiamata per
+mettersi in attesa del segnale successivo. Questo ovviamente comporta che non
+devono essere installati gestori, che solo il \textit{thread} di gestione deve
+usare \func{sigwait} e che, per evitare che venga eseguita l'azione
+predefinita, i segnali gestiti in questa maniera devono essere mascherati per
+tutti i \textit{thread}, compreso quello dedicato alla gestione, che potrebbe
+riceverlo fra due chiamate successive.
+
+\itindend{thread}
+
+
+\subsection{La gestione avanzata delle temporizzazioni}
+\label{sec:sig_timer_adv}
+
+% TODO trattare i Posix timer, e le fuzioni:
+% clock_getres clock_gettime clock_settime (vedi man page)
+% timer_getoverrun, timer_gettime, timer_settime, timer_create, timer_delete
+
+
+\subsection{Le interfacce per la notifica attraverso i file descriptor}
+\label{sec:sig_signalfd_eventfd}
+
+
+% TODO trattare qui eventfd signalfd e timerfd introdotte con il 2.6.22
+% timerfd è stata tolta nel 2.6.23 e rifatta per bene nel 2.6.25
+% vedi: http://lwn.net/Articles/233462/
+% http://lwn.net/Articles/245533/
+% http://lwn.net/Articles/267331/
+
-%%% Local Variables:
-%%% mode: latex
-%%% TeX-master: "gapil"
-%%% End:
% LocalWords: kernel POSIX timer shell control ctrl kill raise signal handler
% LocalWords: reliable unreliable fig race condition sez struct process table
% LocalWords: how oldset BLOCK UNBLOCK SETMASK sigsuspend sigaltstack malloc
% LocalWords: SIGSTKSZ MINSIGSTKSZ ss oss ENOMEM flags DISABLE sp setrlimit LB
% LocalWords: RLIMIT rlim sigsetjmp siglongjmp sigjmp buf env savesigs jmp ptr
-% LocalWords: SIGRTMIN SIGRTMAX sigval sival sigevent sigqueue EAGAIN sysctl
-% LocalWords: QUEUE thread sigwait sigwaitinfo sigtimedwait info DEF SLB
+% LocalWords: SIGRTMIN SIGRTMAX sigval sigevent sigqueue EAGAIN sysctl safe
+% LocalWords: QUEUE thread sigwait sigwaitinfo sigtimedwait info DEF SLB bind
+% LocalWords: function accept return cfgetispeed cfgetospeed cfsetispeed chdir
+% LocalWords: cfsetospeed chmod chown gettime close connect creat dup execle
+% LocalWords: execve fchmod fchown fdatasync fpathconf fstat fsync ftruncate
+% LocalWords: getegid geteuid getgid getgroups getpeername getpgrp getppid sem
+% LocalWords: getsockname getsockopt getuid listen lseek lstat mkdir mkfifo
+% LocalWords: pathconf poll posix pselect read readlink recv recvfrom recvmsg
+% LocalWords: rename rmdir select send sendmsg sendto setgid setpgid setsid
+% LocalWords: setsockopt setuid shutdown sigpause socketpair stat symlink page
+% LocalWords: sysconf tcdrain tcflow tcflush tcgetattr tcgetgrp tcsendbreak
+% LocalWords: tcsetattr tcsetpgrp getoverrun times umask uname unlink utime
+% LocalWords: write sival SIVGTALRM NOCLDWAIT MESGQ ASYNCIO TKILL tkill tgkill
+
+
+%%% Local Variables:
+%%% mode: latex
+%%% TeX-master: "gapil"
+%%% End:
+% LocalWords: ILL ILLOPC ILLOPN ILLADR ILLTRP PRVOPC PRVREG COPROC BADSTK FPE
+% LocalWords: INTDIV INTOVF FLTDIV FLTOVF FLTUND underflow FLTRES FLTINV SEGV
+% LocalWords: FLTSUB MAPERR ACCERR ADRALN ADRERR OBJERR BRKPT CLD EXITED MSG
+% LocalWords: KILLED DUMPED TRAPPED STOPPED CONTINUED PRI HUP SigFunc