\begin{table}[!htb]
\footnotesize
\centering
- \begin{tabular}[c]{|l|p{10cm}|}
+ \begin{tabular}[c]{|l|p{8cm}|}
\hline
\textbf{Valore} & \textbf{Significato} \\
\hline
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_si_code_special} che sono state ordinate nella
-sequenza in cui si sono appena citati i rispettivi segnali, 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{10cm}|}
+ \begin{tabular}[c]{|l|p{8cm}|}
\hline
\textbf{Valore} & \textbf{Significato} \\
\hline
\label{tab:sig_si_code_special}
\end{table}
+L'elenco dettagliato dei nomi di queste costanti è riportato nelle diverse
+sezioni di tab.~\ref{tab:sig_si_code_special} che sono state ordinate nella
+sequenza in cui si sono appena citati i rispettivi segnali, il prefisso del
+nome indica comunque in maniera diretta il segnale a cui le costanti fanno
+riferimento.
+
Il resto della struttura \struct{siginfo\_t} è definito come una \dirct{union}
ed i valori eventualmente presenti dipendono dal segnale ricevuto, così
\signal{SIGCHLD} ed i segnali \textit{real-time} (vedi
\func{signal} occorre molta attenzione, in quanto le due funzioni possono
interagire in maniera anomala. Infatti l'azione specificata con
\struct{sigaction} contiene un maggior numero di informazioni rispetto al
-semplice indirizzo del gestore restituito da \func{signal}. Per questo motivo
-se si usa quest'ultima per installare un gestore sostituendone uno
+semplice indirizzo del gestore restituito da \func{signal}, e questo comporta
+che se si usa quest'ultima per installare un gestore sostituendone uno
precedentemente installato con \func{sigaction}, non sarà possibile effettuare
un ripristino corretto dello stesso.
-Per questo è sempre opportuno usare \func{sigaction}, che è in grado di
+Per questo motivo è opportuno usare sempre \func{sigaction} che è in grado di
ripristinare correttamente un gestore precedente, anche se questo è stato
installato con \func{signal}. In generale poi non è il caso di usare il valore
di ritorno di \func{signal} come campo \var{sa\_handler}, o viceversa, dato
-che in certi sistemi questi possono essere diversi. In definitiva dunque, a
-meno che non si sia vincolati all'aderenza stretta allo standard ISO C, è
-sempre il caso di evitare l'uso di \func{signal} a favore di \func{sigaction}.
+che in certi sistemi questi valori possono essere diversi. In definitiva
+dunque, a meno che non si sia vincolati all'aderenza stretta allo standard ISO
+C, è sempre il caso di evitare l'uso di \func{signal} a favore di
+\func{sigaction}.
\begin{figure}[!htbp]
\footnotesize \centering
\label{fig:sig_Signal_code}
\end{figure}
-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 \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). Anche in questo caso, per
-semplificare la definizione si è poi definito un apposito tipo
-\texttt{SigFunc} per esprimere in modo più comprensibile la forma di un
-gestore di segnale.
+Come primo esmpio si è allora provveduto, per mantenere un'interfaccia
+semplificata che abbia le stesse caratteristiche di \func{signal}, a definire
+attraverso \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). Anche in questo caso,
+per semplificare la definizione si è poi definito un apposito tipo
+\texttt{SigHandler} per esprimere in modo più semplice la forma di un gestore
+di segnale.
Si noti come, essendo la funzione estremamente semplice, essa è definita come
\dirct{inline}. Questa direttiva viene usata per dire al compilatore di
di problemi di sintassi nel passaggio degli argomenti (si veda ad esempio
\cite{PratC}) che in questo modo possono essere evitati.
+La funzione \func{Signal} appena illustrata continua però ad utilizzare la
+forma tradizionale del gestore di segnali, mentre abbiamo visto come
+\func{sigaction} preveda la possibilità di indicare, attivando il flag
+\const{SA\_SIGINFO}, un gestore nella forma avanzata \param{sa\_sigaction}, in
+grado di ricevere molte più informazioni, che prevede l'utilizzo di tre
+argomenti. Di nuovo facciamo un esempio di come usare \func{sigaction} in
+questo caso, partendo col definire un apposito tipo, \texttt{SigAction}, per
+semplificare l'indicazione del nuovo tipo di gestore:
+\includecodesnip{listati/SigAction.c}
+
+Un gestore di segnali definito nella forma \val{sa\_sigaction} infatti, oltre
+al numero di segnale ricevuto come primo argomento, otterrà dal kernel un
+puntatore ad una struttura \struct{siginfo\_t} con le relative informazioni
+attienti l'origine del segnale nel secondo argomento, ed infine un puntatore a
+delle informazioni di contesto ad uso delle librerie del C nel terzo
+argomento, che non vengono mai utilizzate nel gestore, attenendo al
+funzionamento a basso livello della gestione dei segnali.\footnote{il kernel
+ tutte le volte che c'è un segnale pendente gestisce l'esecuzione del
+ relativo gestore caricando nello stack i dati del contesto di esecuzione del
+ processo e facendo sì che al ritorno in \textit{user-space} sia eseguito il
+ gestore, una volta che questo ritorna il controllo viene passato a dello
+ specifico codice in \textit{user-space}, detto \itindex{signal~trampoline}
+ \textit{signal trampoline}, che con la funzione di sistema \funcm{sigreturn}
+ usa le informazioni di contesto disponibili in questo argomento per far
+ riprendere l'esecuzione del processo al punto in cui si era stata interrotta
+ dal segnale; tutto ciò è gestito dal kernel e dalle librerie del C e non
+ interessa la programmazione ordinaria.}
+
+Si è riportato in fig.~\ref{fig:sig_Action_code} un equivalente della
+precedente \func{Signal} che però installa un gestore di segnali di tipo
+\param{sa\_sigaction}. Si noti come la funzione, una volta definito come sopra
+il tipo \texttt{SigAction} per il gestore di segnali, sia praticamente
+identica all'altra.
+
+\begin{figure}[!htbp]
+ \footnotesize \centering
+ \begin{minipage}[c]{\codesamplewidth}
+ \includecodesample{listati/Action.c}
+ \end{minipage}
+ \normalsize
+ \caption{La funzione \func{Action}, analoga alla precedente \func{Signal}
+ per l'uso dei gestori di segnali avanzati con \func{sigaction}.}
+ \label{fig:sig_Action_code}
+\end{figure}
+
+Quello che cambia in questo caso è occorre indicare (\texttt{\small 4}) nel
+campo \var{sa\_flags} della struttura \struct{sigaction} il valore
+\const{SA\_SIGINFO}, perché poi si passerà (\texttt{\small 5}) l'indirizzo il
+del gestore nel campo \var{sa\_sigaction} invece che in \var{sa\_handler} come
+nel caso precedente.
+
+Inoltre in questo caso, ritornando la funzione l'indirizzo del gestore che è
+nella nuova forma, non si può terminare in caso di errore riportanto il valore
+\const{SIG\_ERR} (che è di tipo \type{sighandler\_t} e fa riferimento ad un
+gestore ordinario) come in precedenza. Per questo motivo si è scelto di
+ritornare come indicazione di errore il valore \val{NULL}, ma in questo caso
+si deve tenere presente che questo valore non è più distinto da quello che si
+utilizza per indicare la eventuale reimpostazione del gestore di default (come
+era \const{SIG\_ERR} rispetto a \const{SIG\_DFL}).
+
+Per questo motivo questa funzione viene illustrata solo a scopo di primo
+esempio, vedremo più avanti, in sez.~\ref{sec:sig_real_time}, nel contesto
+dell'uso dei segnali \textit{real-time} per i quali è nata questa nuova
+interfaccia, un esempio più completo dell'uso di \func{sigaction} con un
+gestore in questa nuova forma, e di come utilizzare le informazioni ottenute
+nella struttura \struct{siginfo\_t}.
\subsection{La gestione della \textsl{maschera dei segnali} o
citato un controllo ed una assegnazione) o comunque eseguire una serie di
istruzioni, l'atomicità non è più possibile.
-In questo caso, se si vuole essere sicuri di non poter essere interrotti da
-uno o più segnali durante l'esecuzione di una sezione di codice, li si possono
-bloccare esplicitamente modificando la maschera dei segnali del processo
-usando la funzione di sistema \funcd{sigprocmask},\footnote{in realtà quello
- che viene usato normalmente è il \textit{wrapper} omonimo delle \acr{glibc}
- dato che con l'introduzione dei segnali \textit{real time} nel kernel 2.2 le
- dimensioni del tipo \type{sigset\_t} sono cambiate e la \textit{system call}
- sottostante è diventata \funcm{rt\_sigprocmask} che richiede un quarto
- argomento di tipo \ctyp{size\_t} per indicare questa dimensione; il
- \textit{wrapper} maschera questi dettagli ed inoltre ignora in maniera
- silente i tentativi di bloccare i segnali \textit{real time} impiegati per
- la gestione dei \textit{thread} dalla \textit{Native Thread Posix Library}
- (vedi sez.~\ref{sec:linux_ntpl}).} il cui prototipo è:
+In questo caso, quando si vuole essere sicuri di non essere interrotti da uno
+o più segnali durante l'esecuzione di una sezione di codice, diventa
+necessario bloccarli esplicitamente. Questo si fa modificando la maschera dei
+segnali del processo e per fare questa operazione con lo standard POSIX-1.2001
+è stata introdotta una apposita funzione di sistema,
+\funcd{sigprocmask},\footnote{in realtà quello che viene usato normalmente è
+ il \textit{wrapper} omonimo delle \acr{glibc} dato che con l'introduzione
+ dei segnali \textit{real time} nel kernel 2.2 le dimensioni del tipo
+ \type{sigset\_t} sono cambiate e la \textit{system call} sottostante è
+ diventata \funcm{rt\_sigprocmask} che richiede un quarto argomento di tipo
+ \ctyp{size\_t} per indicare questa dimensione; la vecchia funzione di
+ sistema continua ad esistere ma è deprecata, il \textit{wrapper} maschera
+ questi dettagli ed inoltre ignora in maniera silente i tentativi di bloccare
+ i segnali \textit{real time} impiegati per la gestione dei \textit{thread}
+ dalla \textit{Native Thread Posix Library} (vedi
+ sez.~\ref{sec:linux_ntpl}).} il cui prototipo è:
\begin{funcproto}{
\fhead{signal.h}
La funzione usa l'insieme di segnali posto all'indirizzo passato
nell'argomento \param{set} per modificare la maschera dei segnali del processo
-corrente. La modifica viene effettuata a seconda del valore
-dell'argomento \param{how}, secondo le modalità specificate in
-tab.~\ref{tab:sig_procmask_how}. Qualora si specifichi un valore non nullo
-per \param{oldset} la maschera dei segnali corrente viene salvata a
-quell'indirizzo. Se è nullo \param{set} non viene eseguito nessun cambiamento
-e si può usare la funzione per leggere la maschera corrente in \param{oldset}.
+corrente. La modifica viene effettuata a seconda del valore dell'argomento
+\param{how}, secondo le modalità specificate in
+tab.~\ref{tab:sig_procmask_how}. Qualora si specifichi un indirizzo non nullo
+per il puntatore \param{oldset} la maschera dei segnali corrente viene salvata
+a quell'indirizzo. Se invece è nullo il puntatore \param{set} non viene
+eseguito nessun cambiamento e si può usare la funzione per leggere la maschera
+corrente in \param{oldset}.
\begin{table}[htb]
\footnotesize
La funzione consente di proteggere delle sezioni di codice bloccando l'insieme
di segnali voluto per poi riabilitarli alla fine della sezione critica e
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
+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.
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 è:
+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}{
\fhead{signal.h}
% 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 jiffies
+% LocalWords: KILLED DUMPED TRAPPED STOPPED CONTINUED PRI HUP SigHandler
% LocalWords: SEC unsafe sockatmark execl execv faccessat fchmodat fchownat
% LocalWords: fexecve fstatat futimens linkat mkdirat mkfifoat mknod mknodat
% LocalWords: openat readlinkat renameat symlinkat unlinkat utimensat utimes
% LocalWords: epoch multiplexing overrun res lpthread sec nsec curr one shot
% LocalWords: delete stopped gdb alpha mips emulation locking ppoll epoll PGID
% LocalWords: pwait msgrcv msgsnd semop semtimedop runnable sigisemptyset HRT
-% LocalWords: sigorset sigandset BOOTTIME Android request remain cap dell'
+% LocalWords: sigorset sigandset BOOTTIME Android request remain cap jiffies
%%% Local Variables:
* Initialize a signal handler.
* To enable the signal handling a process we need to tell it to
* kernel; this is done writing all needed info to a sigaction structure
- * named sigact, and then callind sigaction() system call passing the
+ * named sigact, and then calling sigaction() system call passing the
* information stored in the sigact structure variable.
*
* Input: the signal to handle
* the signal handler function
- * Return: the previous sigaction structure
+ * Return: the previous signal handler
*/
-inline SigFunc * Signal(int signo, SigFunc *func)
+inline SigHandler * Signal(int signo, SigHandler *func)
{
struct sigaction new_handl, old_handl;
+ new_handl.sa_flags=0; /* init to 0 all flags */
new_handl.sa_handler = func; /* set signal handler */
/* clear signal mask: no signal blocked during execution of func */
if (sigemptyset(&new_handl.sa_mask)!=0){ /* initialize signal set */
return SIG_ERR;
}
- new_handl.sa_flags=0; /* init to 0 all flags */
/* change action for signo signal */
if (sigaction(signo, &new_handl, &old_handl)){
return SIG_ERR;
* Initialize a signal handler.
* To enable the signal handling a process we need to tell it to
* kernel; this is done writing all needed info to a sigaction structure
- * named sigact, and then callind sigaction() system call passing the
+ * named sigact, and then calling sigaction() system call passing the
* information stored in the sigact structure variable.
* This version enable BSD semantics with SA_RESTART
*
* Input: the signal to handle
* the signal handler function
- * Return: the previous sigaction structure
+ * Return: the previous signal handler
*/
-inline SigFunc * SignalRestart(int signo, SigFunc *func)
+inline SigHandler * SignalRestart(int signo, SigHandler *func)
{
struct sigaction new_handl, old_handl;
- new_handl.sa_handler = func; /* set signal handler */
new_handl.sa_flags = SA_RESTART; /* restart system call */
+ new_handl.sa_handler = func; /* set signal handler */
/* clear signal mask: no signal blocked during execution of func */
if (sigemptyset(&new_handl.sa_mask)!=0){ /* initialize signal set */
return SIG_ERR;
return (old_handl.sa_handler);
}
+/*
+ * Function Action
+ * Initialize a sa_sigaction signal handler.
+ * To enable the signal handling a process we need to tell it to
+ * kernel; this is done writing all needed info to a sigaction structure
+ * named sigact, and then calling sigaction() system call passing the
+ * information stored in the sigact structure variable.
+ *
+ * Input: the signal to handle
+ * the signal handler function (sa_sigaction type)
+ * Return: the previous signal handler
+ */
+inline SigAction * Action(int signo, SigAction *func)
+{
+ struct sigaction new_handl, old_handl;
+ new_handl.sa_flags=SA_SIGINFO; /* we use sa_sigaction handler */
+ new_handl.sa_sigaction = func; /* set signal handler */
+ /* clear signal mask: no signal blocked during execution of func */
+ if (sigemptyset(&new_handl.sa_mask)!=0){ /* initialize signal set */
+ return NULL;
+ }
+ /* change action for signo signal */
+ if (sigaction(signo, &new_handl, &old_handl)){
+ return NULL;
+ }
+ return (old_handl.sa_sigaction);
+}
+/*
+ * Function Action
+ * Initialize a sa_sigaction signal handler.
+ * To enable the signal handling a process we need to tell it to
+ * kernel; this is done writing all needed info to a sigaction structure
+ * named sigact, and then calling sigaction() system call passing the
+ * information stored in the sigact structure variable.
+ *
+ * Input: the signal to handle
+ * the signal handler function (sa_sigaction type)
+ * Return: the previous signal handler
+ */
+inline SigAction * ActionRestart(int signo, SigAction *func)
+{
+ struct sigaction new_handl, old_handl;
+ new_handl.sa_flags=SA_SIGINFO|SA_RESTART;/* flag setup */
+ new_handl.sa_sigaction = func; /* set signal handler */
+ /* clear signal mask: no signal blocked during execution of func */
+ if (sigemptyset(&new_handl.sa_mask)!=0){ /* initialize signal set */
+ return NULL;
+ }
+ /* change action for signo signal */
+ if (sigaction(signo, &new_handl, &old_handl)){
+ return NULL;
+ }
+ return (old_handl.sa_sigaction);
+}
/*
* Functions: HandSigCHLD
- * Generic handler for SIGCHLD signal
+ * Generic simple handler for SIGCHLD signal
*
* Simone Piccardi Dec. 2002
*/