\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}).
+ processo stesso o di un altro (solo nel caso della \func{kill}).
\end{itemize*}
Ciascuno di questi eventi (compresi gli ultimi due che pure sono controllati
di un segnale, pur mantenendo memoria del fatto che è avvenuto.
Nella semantica \textsl{affidabile} (quella utilizzata da Linux e da ogni Unix
-moderno) il gestore una volta installato resta attivo e non si hanno
-tutti i problemi precedenti. In questa semantica i segnali vengono
-\textsl{generati} dal kernel per un processo all'occorrenza dell'evento che
-causa il segnale. In genere questo viene fatto dal kernel impostando l'apposito
-campo della \struct{task\_struct} del processo nella process table (si veda
-fig.~\ref{fig:proc_task_struct}).
+moderno) il gestore una volta installato resta attivo e non si hanno tutti i
+problemi precedenti. In questa semantica i segnali vengono \textsl{generati}
+dal kernel per un processo all'occorrenza dell'evento che causa il segnale. In
+genere questo viene fatto dal kernel impostando l'apposito campo della
+\struct{task\_struct} del processo nella \itindex{process~table}
+\textit{process table} (si veda fig.~\ref{fig:proc_task_struct}).
Si dice che il segnale viene \textsl{consegnato} al processo (dall'inglese
\textit{delivered}) quando viene eseguita l'azione per esso prevista, mentre
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 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} 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}
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 stack e delle variabili al momento della
-ricezione del segnale.
+per esaminare lo stato dello \itindex{stack} stack e delle variabili al
+momento della ricezione del segnale.
\begin{table}[htb]
\footnotesize
% molte diverse eccezioni che \texttt{SIGFPE} non distingue, mentre lo
% standard IEEE per le operazioni in virgola mobile definisce varie eccezioni
% aritmetiche e richiede che esse siano notificate.
+% TODO trovare altre info su SIGFPE e trattare la notifica delle eccezioni
\item[\const{SIGILL}] Il nome deriva da \textit{illegal instruction},
significa che il programma sta cercando di eseguire una istruzione
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 stack. Lo stesso segnale viene
- generato in caso di overflow dello stack o di problemi nell'esecuzione di un
- gestore. Se il gestore ritorna il comportamento del processo è
- indefinito.
+ 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
\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 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} 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.
\begin{basedescript}{\desclabelwidth{2.0cm}}
\item[\const{SIGPIPE}] Sta per \textit{Broken pipe}. Se si usano delle pipe,
(o delle FIFO o dei socket) è necessario, prima che un processo inizi a
- scrivere su una di esse, che un'altro l'abbia aperta in lettura (si veda
+ scrivere su una di esse, che un altro l'abbia aperta in lettura (si veda
sez.~\ref{sec:ipc_pipes}). Se il processo in lettura non è partito o è
terminato inavvertitamente alla scrittura sulla pipe il kernel genera questo
segnale. Se il segnale è bloccato, intercettato o ignorato la chiamata che
\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
+ \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.}
\end{prototype}
\funcdecl{int kill(pid\_t pid, int sig)} Invia il segnale \param{sig} al
processo specificato con \param{pid}.
- \bodydesc{La funzione restituisce 0 in caso di successo e -1 in caso di
+ \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.
\code{kill(-pidgrp, signal)}; il suo prototipo è:
\begin{prototype}{signal.h}{int killpg(pid\_t pidgrp, int signal)}
- Invia il segnale \param{signal} al process group \param{pidgrp}.
- \bodydesc{La funzione restituisce 0 in caso di successo e -1 in caso di
+ Invia il segnale \param{signal} al \itindex{process~group} \textit{process
+ group} \param{pidgrp}.
+
+ \bodydesc{La funzione restituisce 0 in caso di successo e $-1$ in caso di
errore, gli errori sono gli stessi di \func{kill}.}
\end{prototype}
-\noindent e permette di inviare un segnale a tutto un \textit{process group}
-(vedi sez.~\ref{sec:sess_proc_group}).
+\noindent e permette di inviare un segnale a tutto un \itindex{process~group}
+\textit{process group} (vedi sez.~\ref{sec:sess_proc_group}).
\begin{table}[htb]
\footnotesize
\hline
\hline
$>0$ & il segnale è mandato al processo con il \acr{pid} indicato.\\
- 0 & il segnale è mandato ad ogni processo del \textit{process group}
- del chiamante.\\
+ 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 process group
- $|\code{pid}|$.\\
+ $<-1$ & il segnale è mandato ad ogni processo del \textit{process group}
+ \itindex{process~group} $|\code{pid}|$.\\
\hline
\end{tabular}
\caption{Valori dell'argomento \param{pid} per la funzione
Predispone l'invio di un segnale di allarme alla scadenza dell'intervallo
\param{value} sul timer specificato da \param{which}.
- \bodydesc{La funzione restituisce 0 in caso di successo e -1 in caso di
+ \bodydesc{La funzione restituisce 0 in caso di successo e $-1$ in caso di
errore, nel qual caso \var{errno} assumerà uno dei valori \errval{EINVAL} o
\errval{EFAULT}.}
\end{prototype}
Legge in \param{value} il valore del timer specificato da \param{which}.
- \bodydesc{La funzione restituisce 0 in caso di successo e -1 in caso di
+ \bodydesc{La funzione restituisce 0 in caso di successo e $-1$ in caso di
errore e restituisce gli stessi errori di \func{getitimer}}
\end{prototype}
\noindent i cui argomenti hanno lo stesso significato e formato di quelli di
Pone il processo in stato di sleep fino al ritorno di un gestore.
\bodydesc{La funzione ritorna solo dopo che un segnale è stato ricevuto ed
- il relativo gestore è ritornato, nel qual caso restituisce -1 e
+ il relativo gestore è ritornato, nel qual caso restituisce $-1$ e
\var{errno} assumerà il valore \errval{EINTR}.}
\end{prototype}
Pone il processo in stato di sleep per \param{usec} microsecondi.
- \bodydesc{La funzione restituisce zero se l'attesa viene completata, o -1 in
- caso di errore, nel qual caso \var{errno} assumerà il valore
+ \bodydesc{La funzione restituisce zero se l'attesa viene completata, o $-1$
+ in caso di errore, nel qual caso \var{errno} assumerà il valore
\errval{EINTR}.}
\end{prototype}
Pone il processo in stato di sleep per il tempo specificato da \param{req}.
In caso di interruzione restituisce il tempo restante in \param{rem}.
- \bodydesc{La funzione restituisce zero se l'attesa viene completata, o -1 in
- caso di errore, nel qual caso \var{errno} assumerà uno dei valori:
+ \bodydesc{La funzione restituisce zero se l'attesa viene completata, o $-1$
+ in caso di errore, nel qual caso \var{errno} assumerà uno dei valori:
\begin{errlist}
\item[\errcode{EINVAL}] si è specificato un numero di secondi negativo o un
numero di nanosecondi maggiore di 999.999.999.
\bodydesc{Le prime quattro funzioni ritornano 0 in caso di successo, mentre
\func{sigismember} ritorna 1 se \param{signum} è in \param{set} e 0
- altrimenti. In caso di errore tutte ritornano -1, con \var{errno}
+ altrimenti. In caso di errore tutte ritornano $-1$, con \var{errno}
impostata a \errval{EINVAL} (il solo errore possibile è che \param{signum}
non sia un segnale valido).}
\end{functions}
Installa una nuova azione per il segnale \param{signum}.
- \bodydesc{La funzione restituisce zero in caso di successo e -1 per un
+ \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 è
\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 stack alternativo per
- l'esecuzione del gestore (vedi
+ \const{SA\_ONSTACK} & Stabilisce l'uso di uno \itindex{stack} stack
+ alternativo per l'esecuzione del gestore (vedi
sez.~\ref{sec:sig_specific_features}).\\
\hline
\end{tabular}
\label{tab:sig_sa_flag}
\end{table}
+% TODO con il 2.6 sono stati aggiunti SA_NOCLDWAIT e altro, documentare
+
Come si può notare in fig.~\ref{fig:sig_sigaction} \func{sigaction} permette
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
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 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
+ 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.}
Cambia la \textsl{maschera dei segnali} del processo corrente.
- \bodydesc{La funzione restituisce zero in caso di successo e -1 per un
+ \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.
Imposta la \textit{signal mask} specificata, mettendo in attesa il processo.
- \bodydesc{La funzione restituisce zero in caso di successo e -1 per un
+ \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.
Scrive in \param{set} l'insieme dei segnali pendenti.
- \bodydesc{La funzione restituisce zero in caso di successo e -1 per un
+ \bodydesc{La funzione restituisce zero in caso di successo e $-1$ per un
errore.}
\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 stack alternativo per i segnali; è cioè possibile fare usare al
-sistema un altro 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} 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:
\begin{enumerate}
\item Allocare un'area di memoria di dimensione sufficiente da usare come
stack alternativo;
memoria con \code{malloc}; in \file{signal.h} sono definite due costanti,
\const{SIGSTKSZ} e \const{MINSIGSTKSZ}, che possono essere utilizzate per
allocare una quantità di spazio opportuna, in modo da evitare overflow. La
-prima delle due è la dimensione canonica per uno stack di segnali e di norma è
-sufficiente per tutti gli usi normali.
+prima delle due è la dimensione canonica per uno \itindex{stack} stack di
+segnali e di norma è sufficiente per tutti gli usi normali.
La seconda è lo spazio che occorre al sistema per essere in grado di lanciare
il gestore e la dimensione di uno stack alternativo deve essere sempre
maggiore di questo valore. Quando si conosce esattamente quanto è lo spazio
necessario al gestore gli si può aggiungere questo valore per allocare uno
-stack di dimensione sufficiente.
+\itindex{stack} stack di dimensione sufficiente.
-Come accennato, per poter essere usato, lo stack per i segnali deve essere
-indicato al sistema attraverso la funzione \funcd{sigaltstack}; il suo
-prototipo è:
+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 è:
\begin{prototype}{signal.h}
{int sigaltstack(const stack\_t *ss, stack\_t *oss)}
Installa un nuovo stack per i segnali.
- \bodydesc{La funzione restituisce zero in caso di successo e -1 per un
+ \bodydesc{La funzione restituisce zero in caso di successo e $-1$ per un
errore, nel qual caso \var{errno} assumerà i valori:
\begin{errlist}
\end{prototype}
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 stack da
-installare e quello corrente (che viene restituito dalla funzione per un
-successivo ripristino).
+\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).
\begin{figure}[!htb]
\footnotesize \centering
\label{fig:sig_stack_t}
\end{figure}
-Il campo \var{ss\_sp} di \struct{stack\_t} indica l'indirizzo base dello 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
+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.
Se \param{oss} non è nullo verrà restituito dalla funzione indirizzo e
-dimensione dello 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 stack alternativo per i segnali quando si teme di
-avere problemi di esaurimento dello stack standard o di superamento di un
-limite 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 stack alternativo.
+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 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.
+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.
Abbiamo visto in fig.~\ref{fig:sig_sleep_incomplete} come si possa usare
\func{longjmp} per uscire da un gestore rientrando direttamente nel corpo
\end{functions}
Le due funzioni prendono come primo argomento la variabile su cui viene
-salvato il contesto dello stack per permettere il
+salvato il contesto dello \itindex{stack} 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
Invia il segnale \param{signo} al processo \param{pid}, restituendo al
gestore il valore \param{value}.
- \bodydesc{La funzione restituisce 0 in caso di successo e -1 in caso di
+ \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}
Attende che uno dei segnali specificati in \param{set} sia pendente.
- \bodydesc{La funzione restituisce 0 in caso di successo e -1 in caso di
+ \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.
timeout in \param{timeout}.
- \bodydesc{Le funzioni restituiscono 0 in caso di successo e -1 in caso di
+ \bodydesc{Le funzioni restituiscono 0 in caso di successo e $-1$ in caso di
errore, nel qual caso \var{errno} assumerà uno dei valori già visti per
\func{sigwait}, ai quali si aggiunge, per \func{sigtimedwait}:
\begin{errlist}