X-Git-Url: https://gapil.gnulinux.it/gitweb/?p=gapil.git;a=blobdiff_plain;f=signal.tex;h=493bf4460479e0a99b737de9537db9535557c400;hp=b26cddf79438b76ba0d4447d92539bcaf45c3d1f;hb=9b7af600ff0f73bc946c9d160c320667c7a91347;hpb=88d22f4971adcbdb816c405a1375ae0a8d57bdde diff --git a/signal.tex b/signal.tex index b26cddf..493bf44 100644 --- a/signal.tex +++ b/signal.tex @@ -477,20 +477,20 @@ affrontata nei paragrafi successivi. \label{sec:sig_prog_error} Questi segnali sono generati quando il sistema, o in certi casi direttamente -l'hardware (come per i \itindex{page~fault} \textit{page fault} non validi o -le eccezioni del processore) rileva un qualche errore insanabile nel programma -in esecuzione. In generale la generazione di questi segnali significa che il +l'hardware (come per i \textit{page fault} non validi o le eccezioni del +processore) rileva un qualche errore insanabile nel programma in +esecuzione. In generale la generazione di questi segnali significa che il programma ha dei gravi problemi (ad esempio ha dereferenziato un puntatore non valido o ha eseguito una operazione aritmetica proibita) e l'esecuzione non può essere proseguita. In genere si intercettano questi segnali per permettere al programma di terminare in maniera pulita, ad esempio per ripristinare le impostazioni della -console o eliminare i \index{file!di lock} file di lock prima dell'uscita. In -questo caso il gestore deve concludersi ripristinando l'azione predefinita e -rialzando il segnale, in questo modo il programma si concluderà senza effetti -spiacevoli, ma riportando lo stesso stato di uscita che avrebbe avuto se il -gestore non ci fosse stato. +console o eliminare i file di lock prima dell'uscita. In questo caso il +gestore deve concludersi ripristinando l'azione predefinita e rialzando il +segnale, in questo modo il programma si concluderà senza effetti spiacevoli, +ma riportando lo stesso stato di uscita che avrebbe avuto se il gestore non ci +fosse stato. L'azione predefinita per tutti questi segnali è causare la terminazione del processo che li ha causati. In genere oltre a questo il segnale provoca pure @@ -517,10 +517,10 @@ terminazione. Questi segnali sono: 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} - \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. + una variabile locale, andando a corrompere lo \textit{stack}. Lo stesso + segnale viene generato in caso di overflow dello \textit{stack} o di + problemi nell'esecuzione di un gestore. Se il gestore ritorna il + comportamento del processo è indefinito. \item[\signal{SIGSEGV}] Il nome deriva da \itindex{segment~violation} \textit{segment violation}, e significa che il programma sta cercando di @@ -535,9 +535,9 @@ terminazione. Questi segnali sono: \signal{SIGSEGV} questo è un segnale che viene generato di solito quando si dereferenzia un puntatore non inizializzato, la differenza è che \signal{SIGSEGV} indica un accesso non permesso su un indirizzo esistente - (al di fuori dallo \itindex{heap} \textit{heap} o dallo \itindex{stack} - \textit{stack}), mentre \signal{SIGBUS} indica l'accesso ad un indirizzo non - valido, come nel caso di un puntatore non allineato. + (al di fuori dallo \textit{heap} o dallo \textit{stack}), mentre + \signal{SIGBUS} indica l'accesso ad un indirizzo non valido, come nel caso + di un puntatore non allineato. \item[\signal{SIGABRT}] Il nome deriva da \textit{abort}. Il segnale indica che il programma stesso ha rilevato un errore che viene riportato chiamando @@ -860,9 +860,9 @@ stringa passata nell'argomento \param{s}, seguita dal carattere di due punti ed una descrizione del segnale indicato dall'argomento \param{sig}. Una modalità alternativa per utilizzare le descrizioni restituite da -\func{strsignal} e \func{psignal} è quello di usare la -\index{variabili!globali} variabile globale \var{sys\_siglist}, che è definita -in \headfile{signal.h} e può essere acceduta con la dichiarazione: +\func{strsignal} e \func{psignal} è quello di usare la variabile globale +\var{sys\_siglist}, che è definita in \headfile{signal.h} e può essere +acceduta con la dichiarazione: \includecodesnip{listati/siglist.c} L'array \var{sys\_siglist} contiene i puntatori alle stringhe di descrizione, @@ -1836,11 +1836,11 @@ da controllare nel corpo principale del programma, con un codice del tipo di quello riportato in fig.~\ref{fig:sig_event_wrong}. La logica del programma è quella di far impostare al gestore (\texttt{\small - 14--19}) una \index{variabili!globali} variabile globale, preventivamente -inizializzata nel programma principale, ad un diverso valore. In questo modo -dal corpo principale del programma si potrà determinare, osservandone il -contenuto di detta variabile, l'occorrenza o meno del segnale, ed eseguire le -azioni conseguenti (\texttt{\small 6--11}) relative. + 14--19}) una variabile globale, preventivamente inizializzata nel programma +principale, ad un diverso valore. In questo modo dal corpo principale del +programma si potrà determinare, osservandone il contenuto di detta variabile, +l'occorrenza o meno del segnale, ed eseguire le azioni conseguenti +(\texttt{\small 6--11}) relative. \begin{figure}[!htbp] \footnotesize\centering @@ -2114,9 +2114,8 @@ tab.~\ref{tab:sig_sa_flag}. \const{SA\_ONESHOT} & Nome obsoleto e sinonimo non standard di \const{SA\_RESETHAND}, non deve essere più utilizzato.\\ - \const{SA\_ONSTACK} & Stabilisce l'uso di uno \itindex{stack} - \textit{stack} alternativo per l'esecuzione del - gestore (vedi + \const{SA\_ONSTACK} & Stabilisce l'uso di uno \textit{stack} alternativo + per l'esecuzione del gestore (vedi sez.~\ref{sec:sig_specific_features}).\\ \const{SA\_RESETHAND}& Ristabilisce l'azione per il segnale al valore predefinito una volta che il gestore è stato @@ -2356,12 +2355,11 @@ kernel, dove in certi casi le ottimizzazioni dal compilatore, tarate per l'uso in \textit{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. +\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. @@ -2449,24 +2447,23 @@ quell'indirizzo. \end{table} In questo modo diventa possibile proteggere delle sezioni di codice bloccando -l'insieme di segnali voluto per poi riabilitarli alla fine della -\index{sezione~critica} sezione critica. La funzione permette di risolvere -problemi come quelli mostrati in fig.~\ref{fig:sig_event_wrong}, proteggendo -la sezione fra il controllo del flag e la sua cancellazione. La funzione può -essere usata anche all'interno di un gestore, ad esempio per riabilitare la -consegna del segnale che l'ha invocato, in questo caso però occorre ricordare -che qualunque modifica alla maschera dei segnali viene perduta al ritorno -dallo stesso. +l'insieme di segnali voluto per poi riabilitarli alla fine della sezione +critica. La funzione permette di risolvere problemi come quelli mostrati in +fig.~\ref{fig:sig_event_wrong}, proteggendo la sezione fra il controllo del +flag e la sua cancellazione. La funzione può essere usata anche all'interno +di un gestore, ad esempio per riabilitare la consegna del segnale che l'ha +invocato, in questo caso però occorre ricordare che qualunque modifica alla +maschera dei segnali viene perduta al ritorno dallo stesso. Benché con l'uso di \func{sigprocmask} si possano risolvere la maggior parte -dei casi di \itindex{race~condition} \textit{race condition} restano aperte -alcune possibilità legate all'uso di \func{pause}. Il caso è simile a quello -del problema illustrato nell'esempio di fig.~\ref{fig:sig_sleep_incomplete}, e -cioè la possibilità che il processo riceva il segnale che si intende usare per -uscire dallo stato di attesa invocato con \func{pause} immediatamente prima -dell'esecuzione di quest'ultima. Per poter effettuare atomicamente la modifica -della maschera dei segnali (di solito attivandone uno specifico) insieme alla -sospensione del processo lo standard POSIX ha previsto la funzione di sistema +dei casi di \textit{race condition} restano aperte alcune possibilità legate +all'uso di \func{pause}. Il caso è simile a quello del problema illustrato +nell'esempio di fig.~\ref{fig:sig_sleep_incomplete}, e cioè la possibilità che +il processo riceva il segnale che si intende usare per uscire dallo stato di +attesa invocato con \func{pause} immediatamente prima dell'esecuzione di +quest'ultima. Per poter effettuare atomicamente la modifica della maschera dei +segnali (di solito attivandone uno specifico) insieme alla sospensione del +processo lo standard POSIX ha previsto la funzione di sistema \funcd{sigsuspend}, il cui prototipo è: \begin{funcproto}{ @@ -2641,11 +2638,10 @@ ulteriori funzioni in fig.~\ref{fig:sig_safe_functions_posix_2008}. 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 \index{variabili!globali} -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. +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} @@ -3676,13 +3672,14 @@ dato che essa può solo assicurare che un segnale è stato inviato, dato che escluderne l'avvenuto invio al momento della chiamata non significa nulla rispetto a quanto potrebbe essere in un qualunque momento successivo. +\itindbeg{stack} + Una delle caratteristiche di BSD, disponibile anche in Linux, è la possibilità -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: +di usare uno \textit{stack} alternativo per i segnali; è cioè possibile fare +usare al sistema un altro \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 \textit{stack} alternativo; @@ -3698,18 +3695,18 @@ In genere il primo passo viene effettuato allocando un'opportuna area di memoria con \code{malloc}; in \headfile{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} -\textit{stack} di segnali e di norma è sufficiente per tutti gli usi normali. +prima delle due è la dimensione canonica per uno \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 \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. +uno \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 è: +Come accennato, per poter essere usato, lo \textit{stack} per i segnali deve +essere indicato al sistema attraverso la funzione \funcd{sigaltstack}; il suo +prototipo è: \begin{funcproto}{ \fhead{signal.h} @@ -3735,8 +3732,8 @@ i segnali deve essere indicato al sistema attraverso la funzione 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} \textit{stack} da installare e quello corrente (che viene -restituito dalla funzione per un successivo ripristino). +\textit{stack} da installare e quello corrente (che viene restituito dalla +funzione per un successivo ripristino). \begin{figure}[!htb] \footnotesize \centering @@ -3749,35 +3746,35 @@ restituito dalla funzione per un successivo ripristino). \end{figure} Il campo \var{ss\_sp} di \struct{stack\_t} indica l'indirizzo base dello -\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. +\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} \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 \signal{SIGSEGV}, che potrebbe essere gestito soltanto avendo -abilitato uno \itindex{stack} \textit{stack} alternativo. +dimensione dello \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 \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 \signal{SIGSEGV}, che potrebbe essere gestito +soltanto avendo abilitato uno \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. +contrario di quanto avviene per lo \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. + +\itindend{stack} Abbiamo visto in fig.~\ref{fig:sig_sleep_incomplete} come si possa usare \func{longjmp} per uscire da un gestore rientrando direttamente nel corpo @@ -3814,19 +3811,17 @@ prototipi sono: \end{funcproto} Le due funzioni prendono come primo argomento la variabile su cui viene -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 -maschera dei segnali. +salvato il contesto dello \textit{stack} per permettere il salto non-locale; +nel caso specifico essa è di tipo \type{sigjmp\_buf}, e non \type{jmp\_buf} +come per le analoghe di sez.~\ref{sec:proc_longjmp} in quanto in questo caso +viene salvata anche la maschera dei segnali. Nel caso di \func{sigsetjmp}, se si specifica un valore di \param{savesigs} diverso da zero la maschera dei valori verrà salvata in \param{env} insieme al -contesto dello \itindex{stack} \textit{stack} usato per il salto non -locale. Se così si è fatto la maschera dei segnali verrà ripristinata in una -successiva chiamata a \func{siglongjmp}. Quest'ultima, a parte l'uso di un -valore di \param{env} di tipo \type{sigjmp\_buf}, è assolutamente identica a -\func{longjmp}. +contesto dello \textit{stack} usato per il salto non locale. Se così si è +fatto la maschera dei segnali verrà ripristinata in una successiva chiamata a +\func{siglongjmp}. Quest'ultima, a parte l'uso di un valore di \param{env} di +tipo \type{sigjmp\_buf}, è assolutamente identica a \func{longjmp}. % TODO: se e quando si troverà un argomento adeguato inserire altre funzioni