X-Git-Url: https://gapil.gnulinux.it/gitweb/?p=gapil.git;a=blobdiff_plain;f=signal.tex;h=b60bd7aeeb0c5cab3b9e110fb6a2ce81cbd56da2;hp=966e32a1aa0759a2d1d6b15210171c3f2680d5e7;hb=a751a5e636b08a4250db5203a3e0b1d4ef3b9be2;hpb=2fbc954b9f4f62f19fa3409512ecdcb87c05350c diff --git a/signal.tex b/signal.tex index 966e32a..b60bd7a 100644 --- a/signal.tex +++ b/signal.tex @@ -84,6 +84,20 @@ attivo. In questo caso è possibile una situazione in cui i segnali possono essere perduti. Si consideri il seguente segmento di codice, in cui la prima operazione del manipolatore è quella di reinstallare se stesso: +\footnotesize +\begin{lstlisting}[labelstep=0,frame=,indent=1cm]{} + int sig_handler(); /* handler function */ + ... + signal(SIGINT, sig_handler); /* establish handler */ + ... + +int sig_handler() +{ + signal(SIGINT, sig_handler); /* restablish handler */ + ... /* process signal */ +} +\end{lstlisting} +\normalsize se un secondo segnale arriva prima che il manipolatore invocato dal primo abbia eseguito la reinstallazione di se stesso il segnale può essere perso o causare il comportamento originale assegnato al segnale (in genere la @@ -418,7 +432,7 @@ stato dello stack e delle variabili al momento della ricezione del segnale. \end{table} La descrizione dettagliata del significato dei vari segnali, raggruppati per -tipologia, verrà affrontate nel seguito. +tipologia, verrà affrontate nei paragrafi successivi. \subsection{Segnali di errore di programma} @@ -1621,44 +1635,62 @@ 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 manipolatore, in questo caso l'esecuzione non riprenderà nel manipolatore in questione, ma nel ciclo -principale, interrompendone inopportunamente l'esecuzione. +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. -Lo stesso tipo di problema si presenterebbe se si volesse usare \func{alarm} -per stabilire un timeout su una sistem call bloccante. Un secondo esempio è -quello in cui si usa il segnale per notificare una quelche forma di evento; in -genere quello che si fa in questo caso è settare nel manipolatore un opportuno -flag da controllare nel corpo principale del programma (con un codice del tipo -di quello riportato in +Un secondo esempio è quello in cui si usa il segnale per notificare una +quelche forma di evento; in genere quello che si fa in questo caso è settare +nel manipolatore un opportuno flag da controllare nel corpo principale del +programma (con un codice del tipo di quello riportato in +\secref{fig:sig_event_wrong}. \begin{figure}[!htb] \footnotesize \centering \begin{minipage}[c]{15cm} \begin{lstlisting}{} sig_atomic_t flag; -unsigned int control(unsigned int seconds) +int main() { - da fare + flag = 0; + ... + if (flag) { /* test if signal occurred */ + flag = 0; /* reset flag */ + do_response(); /* do things */ + } else { + do_other(); /* do other things */ + } + ... } void alarm_hand(int sig) { /* set the flag flag = 1; + return; } \end{lstlisting} \end{minipage} \normalsize - \caption{Un esempio non funzionante di restituzione di un evento da parte di - un segnale.} + \caption{Un esempio non funzionante del codice per il controllo di un + evento generato da un segnale.} \label{fig:sig_event_wrong} \end{figure} +La logica è quella di far settare al manipolatore (\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 \secref{sec:proc_race_cond}, +in cui si genera una race condition; se infatti il 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. -È per questo motivo che occorrono funzioni più sofisticate della semplice -\func{signal} che permettano di gestire i segnali in maniera più completa. - - - +Questi esempi ci mostrano che per una gestione effettiva dei segnali occorrono +funzioni più sofisticate della semplice interfaccia dei primi sistemi Unix, +che permettano di gestire tutti i possibili aspetti con cui un processo deve +reagire alla ricezione di un segnale. @@ -1873,14 +1905,20 @@ permettono si bloccare temporaneamente (o di eliminare completamente, settando \macro{SIG\_IGN} come azione) la consegna dei segnali ad un processo. Questo è fatto specificando la cosiddetta \textit{signal mask} del processo\footnote{nel caso di Linux essa è mantenuta dal campo \var{blocked} - della relativa \var{task\_struct}} che viene espressa come il signal set dei -segnali la cui consegna è bloccata. Abbiamo accennato in + della \var{task\_struct} del processo.} che viene espressa come il signal +set dei segnali la cui consegna è bloccata. Abbiamo accennato in \secref{sec:proc_fork} che la \textit{signal mask} viene ereditata dal padre alla creazione di un processo figlio, e abbiamo visto al paragrafo precedente che essa può essere specificata, durante l'esecuzione di un manipolatore, attraverso l'uso dal campo \var{sa\_mask} di \var{sigaction}. -Uno dei problemi evidenziatisi con l'esempio di +Uno dei problemi evidenziatisi con l'esempio di \secref{fig:sig_event_wrong} è +che in molti casi è necessario proteggere delle sezioni di codice (nel caso la +sezione fra il test e la eventuale cancellazione del flag che testimoniava +l'avvenuta occorrenza del segnale) in modo da essere sicuri che essi siano +eseguiti senza interruzioni. Le operazioni più semplici, come l'assegnazione o +il controllo di una variabile di norma (per essere sicuri si può usare il tipo +\type{sig\_atomic\_t}).