From: Simone Piccardi Date: Sun, 13 May 2012 18:01:46 +0000 (+0000) Subject: Indicizzazione e ulterirore revisione dei segnali X-Git-Url: https://gapil.gnulinux.it/gitweb/?a=commitdiff_plain;h=99b4cf6829122cd46c4b387b977e95766853ae3b;p=gapil.git Indicizzazione e ulterirore revisione dei segnali --- diff --git a/fileadv.tex b/fileadv.tex index 9d2626a..e72a7f3 100644 --- a/fileadv.tex +++ b/fileadv.tex @@ -1166,10 +1166,10 @@ caso di interruzione.\footnote{in realtà la system call di Linux aggiorna il questo comportamento passando alla system call una variabile locale, in modo da mantenere l'aderenza allo standard POSIX che richiede che il valore di \param{timeout} non sia modificato.} Inoltre prende un argomento aggiuntivo -\param{sigmask} che è il puntatore ad una maschera di segnali (si veda -sez.~\ref{sec:sig_sigmask}). La maschera corrente viene sostituita da questa -immediatamente prima di eseguire l'attesa, e ripristinata al ritorno della -funzione. +\param{sigmask} che è il puntatore ad una \index{maschera~dei~segnali} +maschera di segnali (si veda sez.~\ref{sec:sig_sigmask}). La maschera +corrente viene sostituita da questa immediatamente prima di eseguire l'attesa, +e ripristinata al ritorno della funzione. L'uso di \param{sigmask} è stato introdotto allo scopo di prevenire possibili \textit{race condition} \itindex{race~condition} quando ci si deve porre in @@ -1402,11 +1402,12 @@ prototipo è: \end{prototype} La funzione ha lo stesso comportamento di \func{poll}, solo che si può -specificare, con l'argomento \param{sigmask}, il puntatore ad una maschera di -segnali; questa sarà la maschera utilizzata per tutto il tempo che la funzione -resterà in attesa, all'uscita viene ripristinata la maschera originale. L'uso -di questa funzione è cioè equivalente, come illustrato nella pagina di -manuale, all'esecuzione atomica del seguente codice: +specificare, con l'argomento \param{sigmask}, il puntatore ad una +\index{maschera~dei~segnali} maschera di segnali; questa sarà la maschera +utilizzata per tutto il tempo che la funzione resterà in attesa, all'uscita +viene ripristinata la maschera originale. L'uso di questa funzione è cioè +equivalente, come illustrato nella pagina di manuale, all'esecuzione atomica +del seguente codice: \includecodesnip{listati/ppoll_means.c} Eccetto per \param{timeout}, che come per \func{pselect} deve essere un @@ -1828,12 +1829,12 @@ Come già per \func{select} e \func{poll} anche per l'interfaccia di \textit{epoll} si pone il problema di gestire l'attesa di segnali e di dati contemporaneamente per le osservazioni fatte in sez.~\ref{sec:file_select}, per fare questo di nuovo è necessaria una variante della funzione di attesa -che consenta di reimpostare all'uscita una maschera di segnali, analoga alle -estensioni \func{pselect} e \func{ppoll} che abbiamo visto in precedenza per -\func{select} e \func{poll}; in questo caso la funzione si chiama -\funcd{epoll\_pwait}\footnote{la funziona è stata introdotta a partire dal - kernel 2.6.19, ed è come tutta l'interfaccia di \textit{epoll}, specifica di - Linux.} ed il suo prototipo è: +che consenta di reimpostare all'uscita una \index{maschera~dei~segnali} +maschera di segnali, analoga alle estensioni \func{pselect} e \func{ppoll} che +abbiamo visto in precedenza per \func{select} e \func{poll}; in questo caso la +funzione si chiama \funcd{epoll\_pwait}\footnote{la funziona è stata + introdotta a partire dal kernel 2.6.19, ed è come tutta l'interfaccia di + \textit{epoll}, specifica di Linux.} ed il suo prototipo è: \begin{prototype}{sys/epoll.h} {int epoll\_pwait(int epfd, struct epoll\_event * events, int maxevents, int timeout, const sigset\_t *sigmask)} @@ -1848,10 +1849,10 @@ estensioni \func{pselect} e \func{ppoll} che abbiamo visto in precedenza per \end{prototype} La funzione è del tutto analoga \funcd{epoll\_wait}, soltanto che alla sua -uscita viene ripristinata la maschera di segnali originale, sostituita durante -l'esecuzione da quella impostata con l'argomento \param{sigmask}; in sostanza -la chiamata a questa funzione è equivalente al seguente codice, eseguito però -in maniera atomica: +uscita viene ripristinata la \index{maschera~dei~segnali} maschera di segnali +originale, sostituita durante l'esecuzione da quella impostata con +l'argomento \param{sigmask}; in sostanza la chiamata a questa funzione è +equivalente al seguente codice, eseguito però in maniera atomica: \includecodesnip{listati/epoll_pwait_means.c} Si tenga presente che come le precedenti funzioni di \textit{I/O multiplexing} @@ -1939,8 +1940,8 @@ descriptor è \funcd{signalfd},\footnote{in realtà quella riportata è versione, \funcm{signalfd4}, introdotta con il kernel 2.6.27 e che è quella che viene sempre usata a partire dalle \acr{glibc} 2.9, che prende un argomento aggiuntivo \code{size\_t sizemask} che indica la dimensione della - maschera dei segnali, il cui valore viene impostato automaticamente dalle - \acr{glibc}.} il cui prototipo è: + \index{maschera~dei~segnali} maschera dei segnali, il cui valore viene + impostato automaticamente dalle \acr{glibc}.} il cui prototipo è: \begin{prototype}{sys/signalfd.h} {int signalfd(int fd, const sigset\_t *mask, int flags)} @@ -1975,13 +1976,13 @@ con \param{fd}, in caso di errore invece verrà restituito $-1$. L'elenco dei segnali che si vogliono gestire con \func{signalfd} deve essere specificato tramite l'argomento \param{mask}. Questo deve essere passato come -puntatore ad una maschera di segnali creata con l'uso delle apposite macro già -illustrate in sez.~\ref{sec:sig_sigset}. La maschera deve indicare su quali -segnali si intende operare con \func{signalfd}; l'elenco può essere modificato -con una successiva chiamata a \func{signalfd}. Dato che \signal{SIGKILL} e -\signal{SIGSTOP} non possono essere intercettati (e non prevedono neanche la -possibilità di un gestore) un loro inserimento nella maschera verrà ignorato -senza generare errori. +puntatore ad una \index{maschera~dei~segnali} maschera di segnali creata con +l'uso delle apposite macro già illustrate in sez.~\ref{sec:sig_sigset}. La +maschera deve indicare su quali segnali si intende operare con +\func{signalfd}; l'elenco può essere modificato con una successiva chiamata a +\func{signalfd}. Dato che \signal{SIGKILL} e \signal{SIGSTOP} non possono +essere intercettati (e non prevedono neanche la possibilità di un gestore) un +loro inserimento nella maschera verrà ignorato senza generare errori. L'argomento \param{flags} consente di impostare direttamente in fase di creazione due flag per il file descriptor analoghi a quelli che si possono @@ -2139,13 +2140,13 @@ Il primo passo (\texttt{\small 19--20}) è la crezione di un file descriptor quello che useremo per il controllo degli altri. É poi necessario disabilitare la ricezione dei segnali (nel caso \signal{SIGINT}, \signal{SIGQUIT} e \signal{SIGTERM}) per i quali si vuole la notifica tramite -file descriptor. Per questo prima li si inseriscono (\texttt{\small 22--25}) in -una maschera di segnali \texttt{sigmask} che useremo con (\texttt{\small 26}) -\func{sigprocmask} per disabilitarli. Con la stessa maschera si potrà per -passare all'uso (\texttt{\small 28--29}) di \func{signalfd} per abilitare la -notifica sul file descriptor \var{sigfd}. Questo poi (\texttt{\small 30--33}) -dovrà essere aggiunto con \func{epoll\_ctl} all'elenco di file descriptor -controllati con \texttt{epfd}. +file descriptor. Per questo prima li si inseriscono (\texttt{\small 22--25}) +in una \index{maschera~dei~segnali} maschera di segnali \texttt{sigmask} che +useremo con (\texttt{\small 26}) \func{sigprocmask} per disabilitarli. Con la +stessa maschera si potrà per passare all'uso (\texttt{\small 28--29}) di +\func{signalfd} per abilitare la notifica sul file descriptor +\var{sigfd}. Questo poi (\texttt{\small 30--33}) dovrà essere aggiunto con +\func{epoll\_ctl} all'elenco di file descriptor controllati con \texttt{epfd}. Occorrerà infine (\texttt{\small 35--38}) creare la \textit{named fifo} se questa non esiste ed aprirla per la lettura (\texttt{\small 39--40}); una diff --git a/prochand.tex b/prochand.tex index f9a48c0..987a1d7 100644 --- a/prochand.tex +++ b/prochand.tex @@ -614,8 +614,9 @@ comune dopo l'esecuzione di una \func{fork} è la seguente: (vedi sez.~\ref{sec:file_work_dir} e sez.~\ref{sec:file_chroot}); \item la maschera dei permessi di creazione dei file (vedi sez.~\ref{sec:file_perm_management}); -\item la maschera dei segnali bloccati (vedi sez.~\ref{sec:sig_sigmask}) e le - azioni installate (vedi sez.~\ref{sec:sig_gen_beha}); +\item la \index{maschera~dei~segnali} maschera dei segnali bloccati (vedi + sez.~\ref{sec:sig_sigmask}) e le azioni installate (vedi + sez.~\ref{sec:sig_gen_beha}); \item i segmenti di memoria condivisa agganciati al processo (vedi sez.~\ref{sec:ipc_sysv_shm}); \item i limiti sulle risorse (vedi sez.~\ref{sec:sys_resource_limit}); @@ -1556,7 +1557,8 @@ seguente: % TODO ===========Importante============= % TODO questo sotto è incerto, verificare % TODO ===========Importante============= -\item la maschera dei segnali (si veda sez.~\ref{sec:sig_sigmask}). +\item la \index{maschera~dei~segnali} maschera dei segnali (si veda + sez.~\ref{sec:sig_sigmask}). \end{itemize*} Una serie di proprietà del processo originale, che non avrebbe senso mantenere diff --git a/signal.tex b/signal.tex index 915e168..94fb886 100644 --- a/signal.tex +++ b/signal.tex @@ -1802,7 +1802,7 @@ non verrebbe mai più interrotta (se non in caso di un altro segnale). Questo problema può essere risolto (ed è la modalità con cui veniva fatto in SVr2) usando la funzione \func{longjmp} (vedi sez.~\ref{sec:proc_longjmp}) per -uscire dal gestore; in questo modo, con una condizione sullo stato di +uscire dal gestore. In questo modo, con una condizione sullo stato di uscita di quest'ultima, si può evitare la chiamata a \func{pause}, usando un codice del tipo di quello riportato in fig.~\ref{fig:sig_sleep_incomplete}. @@ -1817,29 +1817,32 @@ codice del tipo di quello riportato in fig.~\ref{fig:sig_sleep_incomplete}. \end{figure} In questo caso il gestore (\texttt{\small 18-27}) non ritorna come in -fig.~\ref{fig:sig_sleep_wrong}, ma usa \func{longjmp} (\texttt{\small 25}) per -rientrare nel corpo principale del programma; dato che in questo caso il -valore di uscita di \func{setjmp} è 1, grazie alla condizione in -(\texttt{\small 9-12}) si evita comunque che \func{pause} sia chiamata a -vuoto. - -Ma anche questa implementazione comporta dei problemi; in questo caso infatti -non viene gestita correttamente l'interazione con gli altri segnali; se +fig.~\ref{fig:sig_sleep_wrong}, ma usa la funzione \func{longjmp} +(\texttt{\small 25}) per rientrare direttamente nel corpo principale del +programma. Dato che in questo caso il valore di uscita che verrà restituito da +\func{setjmp} è 1, grazie alla condizione impostata in (\texttt{\small 9-12}) +si potrà evitare comunque che \func{pause} sia chiamata a vuoto. + +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, 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 -\textit{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}). La logica è quella di far impostare al -gestore (\texttt{\small 14-19}) una \index{variabili!globali} 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}). +se si volesse usare questa implementazione di \func{alarm} per stabilire un +timeout su una qualunque \textit{system call} bloccante. + +Un secondo esempio dei problemi a cui si può andare incontro è quello in cui +si usa un segnale per notificare una qualche forma di evento. In genere quello +che si fa in questo caso è impostare all'interno del 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}. + +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. \begin{figure}[!htbp] \footnotesize\centering @@ -1854,16 +1857,19 @@ 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 arriva immediatamente -dopo l'esecuzione del controllo (\texttt{\small 6}) ma prima della -cancellazione del flag (\texttt{\small 7}), la sua occorrenza sarà perduta. +\textit{race condition}. Infatti, in una situazione in cui un segnale è già +arrivato (e quindi \var{flag} è già stata impostata ad 1 nel gestre) se un +altro segnale arriva immediatamente dopo l'esecuzione del controllo +(\texttt{\small 6}) ma prima della cancellazione di \var{flag} fatta subito +dopo (\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 -loro origine nella semplice interfaccia dei primi sistemi Unix, ma con esse -non è possibile gestire in maniera adeguata di tutti i possibili aspetti con -cui un processo deve reagire alla ricezione di un segnale. +Questi esempi ci mostrano come per poter eseguire una gestione effettiva dei +segnali occorrono delle funzioni più sofisticate di quelle finora +illustrate. La fuzione \func{signal} infatti ha la sua origine nella +interfaccia alquanto primitiva che venne adottata nei primi sistemi Unix, ma +con questa funzione è sostanzilmente impossibile gestire in maniera adeguata +di tutti i possibili aspetti con cui un processo deve reagire alla ricezione +di un segnale. @@ -1876,6 +1882,7 @@ Come evidenziato nel paragrafo precedente, le funzioni di gestione dei segnali originarie, nate con la semantica inaffidabile, hanno dei limiti non superabili; in particolare non è prevista nessuna funzione che permetta di gestire il blocco dei segnali o di verificare lo stato dei segnali pendenti. + Per questo motivo lo standard POSIX.1, insieme alla nuova semantica dei segnali ha introdotto una interfaccia di gestione completamente nuova, che permette di ottenere un controllo molto più dettagliato. In particolare lo @@ -1884,55 +1891,108 @@ rappresentare un \textsl{insieme di segnali} (un \textit{signal set}, come viene usualmente chiamato), tale tipo di dato viene usato per gestire il blocco dei segnali. -In genere un \textsl{insieme di segnali} è rappresentato da un intero di -dimensione opportuna, di solito pari al numero di bit dell'architettura della -macchina,\footnote{nel caso dei PC questo comporta un massimo di 32 segnali - distinti: dato che in Linux questi sono sufficienti non c'è necessità di - nessuna struttura più complicata.} ciascun bit del quale è associato ad uno -specifico segnale; in questo modo è di solito possibile implementare le -operazioni direttamente con istruzioni elementari del processore. Lo standard -POSIX.1 definisce cinque funzioni per la manipolazione degli insiemi di -segnali: \funcd{sigemptyset}, \funcd{sigfillset}, \funcd{sigaddset}, -\funcd{sigdelset} e \funcd{sigismember}, i cui prototipi sono: -\begin{functions} - \headdecl{signal.h} - - \funcdecl{int sigemptyset(sigset\_t *set)} Inizializza un insieme di segnali - vuoto (in cui non c'è nessun segnale). - - \funcdecl{int sigfillset(sigset\_t *set)} Inizializza un insieme di segnali - pieno (in cui ci sono tutti i segnali). - - \funcdecl{int sigaddset(sigset\_t *set, int signum)} Aggiunge il segnale - \param{signum} all'insieme di segnali \param{set}. +Inizialmente un \textsl{insieme di segnali} veniva rappresentato da un intero +di dimensione opportuna, di solito pari al numero di bit dell'architettura +della macchina, ciascun bit del quale era associato ad uno specifico +segnale. Nel caso di architetture a 32 bit questo comporta un massimo di 32 +segnali distinti e dato che a lungo questi sono stati sufficienti non c'era +necessità di nessuna struttura più complicata, in questo modo era possibile +implementare le operazioni direttamente con istruzioni elementari del +processore. + +Oggi questo non è più vero, in particolare con l'introduzione dei segnali +\textit{real-rime} (che vedremo in sez.~\ref{sec:sig_real_time}). Dato che in +generale non si può fare conto sulle caratteristiche di una implementazione, +perché non è detto che si disponga di un numero di bit sufficienti per mettere +tutti i segnali in un intero, o perché in \type{sigset\_t} possono essere +immagazzinate ulteriori informazioni, tutte le operazioni devono essere +effettuate tramite le opportune funzioni di libreria che si curano di +mascherare i dettagli di basso livello. + +Lo standard POSIX.1 definisce cinque funzioni per la manipolazione degli +insiemi di segnali. Le prime quattro, che consentono di manipolare i contenuti +di un \textit{signal set}, sono \funcd{sigemptyset}, \funcd{sigfillset}, +\funcd{sigaddset} e \funcd{sigdelset}; i rispettivi prototipi sono: - \funcdecl{int sigdelset(sigset\_t *set, int signum)} Toglie il segnale - \param{signum} dall'insieme di segnali \param{set}. - - \funcdecl{int sigismember(const sigset\_t *set, int signum)} Controlla se il - segnale \param{signum} è nell'insieme di segnali \param{set}. - - \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} - impostata a \errval{EINVAL} (il solo errore possibile è che \param{signum} - non sia un segnale valido).} -\end{functions} +\begin{funcproto}{ +\fhead{signal.h} +\fdecl{int sigemptyset(sigset\_t *set)} +\fdesc{Inizializza un insieme di segnali vuoto.} +\fdecl{int sigfillset(sigset\_t *set)} +\fdesc{Inizializza un insieme di segnali pieno.} +\fdecl{int sigaddset(sigset\_t *set, int signum)} +\fdesc{Aggiunge un segnale ad un insieme di segnali.} +\fdecl{int sigdelset(sigset\_t *set, int signum)} +\fdesc{Rimuove un segnale da un insieme di segnali.} +} + +{Le funzioni ritornano $0$ in caso di successo, e $-1$ per un errore, nel qual + caso \var{errno} assumerà il valore: + \begin{errlist} + \item[\errcode{EINVAL}] \param{signum} non è un segnale valido. + \end{errlist} +} +\end{funcproto} + +Le prime due funzioni inizializzano l'insieme di segnali indicato +dall'argomento \param{set} rispettivamente ad un contenuto vuoto (in cui cioè +non c'è nessun segnale) e pieno (in cui cioè ci sono tutti i segnali). Le +altre due funzioni consentono di inserire o rimuovere uno specifico segnale +indicato con l'argomento \param{signum} in un insieme. + +A queste funzioni si aggiunge l'ulteriore \funcd{sigismember}, che consente di +verificare la presenza di un segnale in un insieme, il suo prototipo è: + +\begin{funcproto}{ +\fhead{signal.h} +\fdecl{int sigismember(const sigset\_t *set, int signum)} +\fdesc{Controlla se un segnale è in un insieme di segnali.} +} + +{La funzione ritorna $1$ il segnale è nell'insieme e $0$ altrimenti, e $-1$ + per un errore, nel qual caso \var{errno} assumerà il valore \errval{EINVAL} + se si è specificato un puntatore \var{NULL}.} +\end{funcproto} + +La \acr{glibc} prevede inoltre altre funzioni non standardizzate, accessibili +definendo la macro \macro{\_GNU\_SOURCE}. La prima di queste è +\funcd{sigisemptyset}, che consente di verificare un insieme è vuoto, il suo +prototipo è: + +\begin{funcproto}{ +\fhead{signal.h} +\fdecl{int sigisemptyset(sigset\_t *set)} +\fdesc{Controlla se un insieme di segnali è vuoto.} +} + +{La funzione ritorna $1$ l'insieme è vuoto e $0$ altrimenti, non sono previste + condizioni di errore.} +\end{funcproto} + +Alla precedente si aggiungono altre due funzioni consentono di effettuare +delle operazioni logiche con gli insiemi di segnali, esse sono +\funcd{sigorset} e \funcd{sigandset}, ed i rispettivi prototipi sono: + +\begin{funcproto}{ +\fhead{signal.h} +\fdecl{sigorset(sigset\_t *dest, sigset\_t *left, sigset\_t *right)} +\fdesc{Crea l'unione di due insieme di segnali.} +\fdecl{sigandset(sigset\_t *dest, sigset\_t *left, sigset\_t *right)} +\fdesc{Crea l'intersezione di due insieme di segnali.} +} + +{Le funzioni ritornano $0$ in caso di successo e $-1$ per un errore, nel qual + caso \var{errno} assumerà il valore \errcode{EINVAL}.} +\end{funcproto} -Dato che in generale non si può fare conto sulle caratteristiche di una -implementazione (non è detto che si disponga di un numero di bit sufficienti -per mettere tutti i segnali in un intero, o in \type{sigset\_t} possono essere -immagazzinate ulteriori informazioni) tutte le operazioni devono essere -comunque eseguite attraverso queste funzioni. In genere si usa un insieme di segnali per specificare quali segnali si vuole bloccare, o per riottenere dalle varie funzioni di gestione la maschera dei -segnali attivi (vedi sez.~\ref{sec:sig_sigmask}). Essi possono essere definiti -in due diverse maniere, aggiungendo i segnali voluti ad un insieme vuoto -ottenuto con \func{sigemptyset} o togliendo quelli che non servono da un -insieme completo ottenuto con \func{sigfillset}. Infine \func{sigismember} -permette di verificare la presenza di uno specifico segnale in un -insieme. +segnali attivi (vedi sez.~\ref{sec:sig_sigmask}). La modalità più comune, che +è anche quella più portabile, prevede che possano essere definiti aggiungendo +i segnali voluti ad un insieme vuoto ottenuto con \func{sigemptyset} o +togliendo quelli che non servono da un insieme completo ottenuto con +\func{sigfillset}. \itindend{signal~set} @@ -1945,40 +2005,49 @@ relativi all'uso di \func{signal}. Per ovviare a tutto questo lo standard POSIX.1 ha ridefinito completamente l'interfaccia per la gestione dei segnali, rendendola molto più flessibile e robusta, anche se leggermente più complessa. -La funzione principale dell'interfaccia POSIX.1 per i segnali è -\funcd{sigaction}. Essa ha sostanzialmente lo stesso uso di \func{signal}, -permette cioè di specificare le modalità con cui un segnale può essere gestito -da un processo. Il suo prototipo è: -\begin{prototype}{signal.h}{int sigaction(int signum, const struct sigaction - *act, struct sigaction *oldact)} - - Installa una nuova azione per il segnale \param{signum}. - - \bodydesc{La funzione restituisce zero in caso di successo e $-1$ per un - errore, nel qual caso \var{errno} assumerà i valori: +La funzione di sistema principale prevista dall'interfaccia POSIX.1 per i +segnali è \funcd{sigaction}. Essa ha sostanzialmente lo stesso uso di +\func{signal}, permette cioè di specificare le modalità con cui un segnale può +essere gestito da un processo. Il suo prototipo è: + +\begin{funcproto}{ +\fhead{signal.h} +\fdecl{int sigaction(int signum, const struct sigaction *act, struct sigaction + *oldact)} +\fdesc{Installa una nuova azione pr un segnale.} +} + +{La funzione ritorna $0$ in caso di successo e $-1$ per un errore, nel qual + caso \var{errno} assumerà uno dei valori: \begin{errlist} \item[\errcode{EINVAL}] si è specificato un numero di segnale invalido o si è cercato di installare il gestore per \signal{SIGKILL} o \signal{SIGSTOP}. \item[\errcode{EFAULT}] si sono specificati indirizzi non validi. - \end{errlist}} -\end{prototype} + \end{errlist} +} +\end{funcproto} La funzione serve ad installare una nuova \textsl{azione} per il segnale -\param{signum}; si parla di \textsl{azione} e non di \textsl{gestore} -come nel caso di \func{signal}, in quanto la funzione consente di specificare -le varie caratteristiche della risposta al segnale, non solo la funzione che -verrà eseguita alla sua occorrenza. Per questo lo standard raccomanda di -usare sempre questa funzione al posto di \func{signal} (che in genere viene -definita tramite essa), in quanto permette un controllo completo su tutti gli -aspetti della gestione di un segnale, sia pure al prezzo di una maggiore -complessità d'uso. +indicato dall'argomento \param{signum}. Si parla di \textsl{azione} e non di +\textsl{gestore} come nel caso di \func{signal}, in quanto la funzione +consente di specificare le varie caratteristiche della risposta al segnale, +non solo la funzione che verrà eseguita alla sua occorrenza. + +Per questo motivo lo standard POSIX.1 raccomanda di usare sempre questa +funzione al posto della precedente \func{signal}, che in genere viene +ridefinita in termini di \func{sigaction}, in quanto la nuova interfaccia +permette un controllo completo su tutti gli aspetti della gestione di un +segnale, sia pure al prezzo di una maggiore complessità d'uso. Se il puntatore \param{act} non è nullo, la funzione installa la nuova azione da esso specificata, se \param{oldact} non è nullo il valore dell'azione corrente viene restituito indietro. Questo permette (specificando \param{act} nullo e \param{oldact} non nullo) di superare uno dei limiti di \func{signal}, -che non consente di ottenere l'azione corrente senza installarne una nuova. +che non consente di ottenere l'azione corrente senza installarne una nuova. Se +sia \param{act} che \param{oldact} la funzione può essere utilizzata per +verificare, se da luogo ad un errore, se il segnale indicato è valido per la +piattaforma che si sta usando. Entrambi i puntatori fanno riferimento alla struttura \struct{sigaction}, tramite la quale si specificano tutte le caratteristiche dell'azione associata @@ -1989,7 +2058,7 @@ più usato. \begin{figure}[!htb] \footnotesize \centering - \begin{minipage}[c]{\textwidth} + \begin{minipage}[c]{0.8\textwidth} \includestruct{listati/sigaction.h} \end{minipage} \normalsize @@ -2009,14 +2078,14 @@ 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 \signal{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 +correttamente, la cosa poteva essere prevenuta installando gli altri gestori +usando \var{sa\_mask} per bloccare \signal{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] +\begin{table}[!htb] \footnotesize \centering \begin{tabular}[c]{|l|p{8cm}|} @@ -2028,41 +2097,47 @@ tab.~\ref{tab:sig_sa_flag}. essere notificato quando il processo figlio viene fermato da uno dei segnali \signal{SIGSTOP}, \signal{SIGTSTP}, \signal{SIGTTIN} o - \signal{SIGTTOU}.\\ - \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\_ONESHOT} & Nome obsoleto, sinonimo non standard di - \const{SA\_RESETHAND}; da evitare.\\ + \signal{SIGTTOU}, questo flag ha significato solo + quando si imposta un gestore per \signal{SIGCHLD}.\\ + \const{SA\_NOCLDWAIT}& Se il segnale è \signal{SIGCHLD} e si richiede di + ignorare il segnale con \const{SIG\_IGN} allora i + processi figli non diventano \itindex{zombie} + \textit{zombie} quando terminano; questa + funzionalità è stata introdotta nel kernel 2.6 e va + a modificare il comportamento di \func{waitpid} + come illustrato in sez.~\ref{sec:proc_wait}, se si + installa un gestore con questo flag attivo il + segnale \signal{SIGCHLD} viene comunque generato.\\ + \const{SA\_NODEFER} & Evita che il segnale corrente sia bloccato durante + l'esecuzione del gestore.\\ + \const{SA\_NOMASK} & Nome obsoleto e sinonimo non standard di + \const{SA\_NODEFER}, non deve essere più + utilizzato.\\ + \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 sez.~\ref{sec:sig_specific_features}).\\ + \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\_RESTART} & Riavvia automaticamente le \textit{slow system call} quando vengono interrotte dal suddetto - segnale; riproduce cioè il comportamento standard + segnale, riproduce cioè il comportamento standard di BSD.\index{system~call~lente}\\ - \const{SA\_NODEFER} & Evita che il segnale corrente sia bloccato durante - l'esecuzione del gestore.\\ - \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\_NOCLDWAIT}& Se il segnale è \signal{SIGCHLD} allora i processi - figli non diventano \itindex{zombie} - \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} -\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 dallo standard POSIX.1b, ed è stata aggiunta nei kernel della serie 2.1.x @@ -2071,13 +2146,13 @@ di utilizzare due forme diverse di gestore,\footnote{la possibilità è prevista informazioni addizionali usando \var{sa\_handler} con un secondo parametro 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 campi devono essere usati in maniera - alternativa, in certe implementazioni questi campi vengono addirittura - definiti come \direct{union}.} Quest'ultima è quella classica usata anche con -\func{signal}, mentre la prima permette di usare un gestore più complesso, in -grado di ricevere informazioni più dettagliate dal sistema, attraverso la -struttura \struct{siginfo\_t}, riportata in fig.~\ref{fig:sig_siginfo_t}. +rispettivamente attraverso i campi \var{sa\_sigaction} o \var{sa\_handler}. +Quest'ultima è quella classica usata anche con \func{signal}, mentre la prima +permette di usare un gestore più complesso, in grado di ricevere informazioni +più dettagliate dal sistema, attraverso la struttura \struct{siginfo\_t}, +riportata in fig.~\ref{fig:sig_siginfo_t}. I due campi devono essere usati in +maniera alternativa, in certe implementazioni questi campi vengono addirittura +definiti come una \direct{union}. Installando un gestore di tipo \var{sa\_sigaction} diventa allora possibile accedere alle informazioni restituite attraverso il puntatore a questa @@ -2089,7 +2164,7 @@ causato l'emissione del segnale. \begin{figure}[!htb] \footnotesize \centering - \begin{minipage}[c]{\textwidth} + \begin{minipage}[c]{0.9\textwidth} \includestruct{listati/siginfo_t.h} \end{minipage} \normalsize @@ -2122,22 +2197,23 @@ altre informazioni specifiche. \textbf{Valore} & \textbf{Significato} \\ \hline \hline - \const{SI\_USER} & Generato da \func{kill} o \func{raise}.\\ - \const{SI\_KERNEL} & Inviato dal kernel.\\ + \const{SI\_USER} & Generato da \func{kill} o \func{raise} o affini.\\ + \const{SI\_KERNEL} & Inviato direttamente dal kernel.\\ \const{SI\_QUEUE} & Inviato con \func{sigqueue} (vedi sez.~\ref{sec:sig_real_time}).\\ \const{SI\_TIMER} & Scadenza di un\itindex{POSIX~Timer~API} \textit{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\\ + messaggi POSIX (vedi sez.~\ref{sec:ipc_posix_mq}), + introdotto con il kernel 2.6.6.\\ \const{SI\_ASYNCIO}& Una operazione di I/O asincrono (vedi sez.~\ref{sec:file_asyncronous_io}) è stata completata.\\ \const{SI\_SIGIO} & Segnale di \signal{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\\ + sez.~\ref{cha:threads_xxx}), introdotto con il kernel + 2.4.19.\\ \hline \end{tabular} \caption{Valori del campo \var{si\_code} della struttura \struct{sigaction} @@ -2145,19 +2221,18 @@ altre informazioni specifiche. \label{tab:sig_si_code_generic} \end{table} -\footnotetext[24]{introdotto con il kernel 2.6.6.} -\footnotetext{introdotto con il kernel 2.4.19.} 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_si_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.} +confronti delle diverse costanti previste per ciascuno di detti segnali; dato +che si tratta di costanti, 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_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 @@ -2217,20 +2292,21 @@ cui si sono appena citati i rispettivi segnali.\footnote{il prefisso del nome \label{tab:sig_si_code_special} \end{table} -Il resto della struttura \struct{siginfo\_t} è definito come \direct{union} ed -i valori eventualmente presenti dipendono dal segnale, così \signal{SIGCHLD} -ed i segnali \textit{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, \signal{SIGCHLD} avvalora -anche i campi \var{si\_status}, \var{si\_utime} e \var{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; -\signal{SIGILL}, \signal{SIGFPE}, \signal{SIGSEGV} e \signal{SIGBUS} -avvalorano \var{si\_addr} con l'indirizzo in cui è avvenuto l'errore, -\signal{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, il segnale -inviato alla scadenza di un \itindex{POSIX~Timer~API} POSIX timer (vedi +Il resto della struttura \struct{siginfo\_t} è definito come una +\direct{union} ed i valori eventualmente presenti dipendono dal segnale +ricevuto, così \signal{SIGCHLD} ed i segnali \textit{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, \signal{SIGCHLD} avvalora anche i campi \var{si\_status}, +\var{si\_utime} e \var{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; \signal{SIGILL}, +\signal{SIGFPE}, \signal{SIGSEGV} e \signal{SIGBUS} avvalorano \var{si\_addr} +con l'indirizzo in cui è avvenuto l'errore, \signal{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, il segnale inviato alla +scadenza di un \itindex{POSIX~Timer~API} POSIX timer (vedi sez.~\ref{sec:sig_timer_adv}) avvalora i campi \var{si\_timerid} e \var{si\_overrun}. @@ -2266,24 +2342,28 @@ 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). 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}. +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 forma più comprensibile la forma di un +gestore di segnale. + +Si noti come, essendo la funzione estremamente semplice, essa è definita come +\direct{inline}. Questa direttiva 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. @@ -2291,48 +2371,61 @@ definito un apposito tipo \texttt{SigFunc}. \textit{signal mask}} \label{sec:sig_sigmask} -\itindbeg{signal~mask} +\index{maschera dei segnali|(} Come spiegato in sez.~\ref{sec:sig_semantics} tutti i moderni sistemi unix-like permettono di bloccare temporaneamente (o di eliminare completamente, impostando \const{SIG\_IGN} come azione) la consegna dei segnali ad un processo. Questo è fatto specificando la cosiddetta \textsl{maschera dei segnali} (o \textit{signal mask}) del processo\footnote{nel caso di Linux essa è mantenuta dal campo \var{blocked} della \struct{task\_struct} del - processo.} cioè l'insieme dei segnali la cui consegna è bloccata. Abbiamo -accennato in sez.~\ref{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 modificata, durante l'esecuzione di -un gestore, attraverso l'uso dal campo \var{sa\_mask} di \struct{sigaction}. + processo.} cioè l'insieme dei segnali la cui consegna è bloccata. + +Abbiamo accennato in sez.~\ref{sec:proc_fork} che la maschera dei segnali +viene ereditata dal padre alla creazione di un processo figlio, e abbiamo +visto al paragrafo precedente che essa può essere modificata durante +l'esecuzione di un gestore ed automaticamente ripristinata quando questo +ritorna, attraverso l'uso dal campo \var{sa\_mask} di \struct{sigaction}. Uno dei problemi evidenziatisi con l'esempio di fig.~\ref{fig:sig_event_wrong} -è che in molti casi è necessario proteggere delle sezioni di codice (nel caso -in questione la sezione fra il controllo e la eventuale cancellazione del flag -che testimoniava l'avvenuta occorrenza del segnale) in modo da essere sicuri -che essi siano eseguite senza interruzioni. - -Le operazioni più semplici, come l'assegnazione o il controllo di una -variabile (per essere sicuri si può usare il tipo \type{sig\_atomic\_t}) di -norma sono atomiche; quando si devono eseguire operazioni più complesse si può -invece usare la funzione \funcd{sigprocmask} che permette di bloccare uno o -più segnali; il suo prototipo è: -\begin{prototype}{signal.h} -{int sigprocmask(int how, const sigset\_t *set, sigset\_t *oldset)} - - Cambia la \textsl{maschera dei segnali} del processo corrente. - - \bodydesc{La funzione restituisce zero in caso di successo e $-1$ per un - errore, nel qual caso \var{errno} assumerà i valori: +è che in molti casi è necessario proteggere delle sezioni di codice, in modo +da essere sicuri che essi siano eseguite senza interruzioni da parte di un +segnale. Nel caso in questione si trattava della sezione di codice fra il +controllo e la eventuale cancellazione del flag impostato dal gestore di un +segnale che testimoniava l'avvenuta occorrenza dello stesso. + +Come illustrato in sez.~\ref{sec:proc_atom_oper} le operazioni più semplici, +come l'assegnazione o il controllo di una variabile, di norma sono atomiche, e +qualora si voglia essere sicuri si può usare il tipo \type{sig\_atomic\_t}. Ma +quando si devono eseguire più operazioni su delle variabili (nell'esempio +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 un +segnale durante l'esecuzione di una sezione di codice, lo si può bloccare +esplicitamente modificando la maschera dei segnali del processo con la +funzione di sistema \funcd{sigprocmask}, il cui prototipo è: + +\begin{funcproto}{ +\fhead{signal.h} +\fdecl{int sigprocmask(int how, const sigset\_t *set, sigset\_t *oldset)} +\fdesc{Imposta la maschera dei segnali del processo corrente.} +} + +{La funzione ritorna $0$ in caso di successo e $-1$ per un errore, nel qual + caso \var{errno} assumerà uno dei valori: \begin{errlist} \item[\errcode{EINVAL}] si è specificato un numero di segnale invalido. \item[\errcode{EFAULT}] si sono specificati indirizzi non validi. - \end{errlist}} -\end{prototype} + \end{errlist} +} +\end{funcproto} -La funzione usa l'insieme di segnali dato all'indirizzo \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 +La funzione usa l'insieme di segnali posto all'indirizzo passanto +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. \begin{table}[htb] @@ -2361,35 +2454,37 @@ 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 alla conclusione del terminatore. +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 +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 +sospensione del processo lo standard POSIX ha previsto la funzione di sistema \funcd{sigsuspend}, il cui prototipo è: -\begin{prototype}{signal.h} -{int sigsuspend(const sigset\_t *mask)} - - Imposta la \textit{signal mask} specificata, mettendo in attesa il processo. - - \bodydesc{La funzione restituisce zero in caso di successo e $-1$ per un - errore, nel qual caso \var{errno} assumerà i valori: + +\begin{funcproto}{ +\fhead{signal.h} +\fdecl{int sigsuspend(const sigset\_t *mask)} +\fdesc{Imposta la maschera dei segnali mettendo in attesa il processo.} +} + +{La funzione ritorna $0$ in caso di successo e $-1$ per un errore, nel qual + caso \var{errno} assumerà uno dei valori: \begin{errlist} \item[\errcode{EINVAL}] si è specificato un numero di segnale invalido. \item[\errcode{EFAULT}] si sono specificati indirizzi non validi. - \end{errlist}} -\end{prototype} + \end{errlist} +} +\end{funcproto} Come esempio dell'uso di queste funzioni proviamo a riscrivere un'altra volta l'esempio di implementazione di \code{sleep}. Abbiamo accennato in @@ -2445,7 +2540,7 @@ riabilitarla immediatamente dopo, in questo modo si evita il \itindex{deadlock} deadlock dovuto all'arrivo del segnale prima dell'esecuzione di \func{sigsuspend}. -\itindend{signal~mask} +\index{maschera dei segnali|)} \subsection{Criteri di programmazione per i gestori dei segnali} @@ -2558,7 +2653,6 @@ 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