Il segnale può essere ignorato (perso)?


9

Ho un'applicazione che comunica con i lavoratori tramite segnali (in particolare SIGUSR1 / SIGUSR2 / SIGSTOP).

Posso fidarmi che qualunque cosa accada ogni segnale verrà consegnato ed elaborato dal gestore?

Cosa succede se i segnali vengono inviati più rapidamente di quanto non sia possibile per l'applicazione per gestirli (ad es. A causa dell'elevato carico dell'host al momento)?

Risposte:


8

A parte il problema "troppi segnali", i segnali possono essere esplicitamente ignorati. Da man 2 signal:

If the signal signum is delivered to the process, then one of the
following happens:    
  *  If the disposition is set to SIG_IGN, then the signal is ignored.

I segnali possono anche essere bloccati. Da man 7 signal;

A signal may be blocked, which means that it will not be delivered
until it is later unblocked.  Between the time when it is generated
and when it is delivered a signal is said to be pending.

Gli insiemi di segnali bloccati e ignorati vengono ereditati da processi figlio, pertanto può accadere che il processo padre dell'applicazione ignori o blocchi uno di questi segnali.

Cosa succede quando vengono emessi più segnali prima che il processo abbia finito di gestire quelli precedenti? Dipende dal sistema operativo. La signal(2)manpage collegata sopra ne discute:

  • Il sistema V ripristinava la disposizione del segnale al valore predefinito. Peggio ancora, la consegna rapida di più segnali comporterebbe chiamate ricorsive (?).
  • BSD bloccherebbe automaticamente il segnale fino al termine del gestore.
  • Su Linux, questo dipende dai flag di compilazione impostati per GNU libc, ma mi aspetto il comportamento di BSD.

4
La pagina man di Linux signal(2)suggerisce enfaticamente che si evita questa confusione usando sigaction(2)invece.
Nate Eldredge,

7

Non puoi fidarti che ogni segnale inviato verrà consegnato. Ad esempio, il kernel Linux "coalizza" SIGCHLD se un processo impiega molto tempo a gestire SIGCHLD da un processo figlio uscito.

Per rispondere a un'altra parte della tua domanda, i segnali vengono "messi in coda" all'interno del kernel se un numero di segnali diversi arriva in un intervallo troppo breve.

Dovresti usare sigaction()per impostare il gestore del segnale con il sa_sigactionmembro di siginfo_t, impostando attentamente il sa_maskmembro siginfo_tdell'argomento. Penso che questo significhi mascherare tutti i segnali "asincroni" almeno. Secondo la pagina man di Linux sigaction(), nasconderai anche il segnale che viene gestito. Penso che dovresti impostare il sa_flagsmembro su SA_SIGINFO, ma non ricordo perché ho questa superstizione. Credo che questo renderà il tuo processo un gestore di segnali che rimane impostato senza condizioni di gara e uno che non viene interrotto dalla maggior parte degli altri segnali.

Scrivi la tua funzione di gestione del segnale molto, molto attentamente. Fondamentalmente basta impostare una variabile globale per indicare che un segnale è stato catturato e fare in modo che il resto del processo gestisca l'azione desiderata per quel segnale. I segnali verranno mascherati per il minor tempo in quel modo.

Inoltre, ti consigliamo di testare il tuo codice di gestione del segnale molto attentamente. Mettilo in un piccolo processo di test e invia il maggior numero possibile di segnali SIGUSR1 e SIGUSR2, magari da 2 o 3 programmi di invio di segnali per scopi speciali. Mescola anche alcuni altri segnali, dopo aver confidato che il tuo codice può gestire SIGUSR1 e SIGUSR2 in modo rapido e corretto. Preparati per il debug difficile.

Se stai usando Linux e solo Linux, potresti pensare di usare signalfd()per creare un descrittore di file che puoi select()o sondare per ricevere quei segnali. L'uso signalfd()potrebbe semplificare il debug.


2
Non è solo SIGCLD che viene coalizzato: tutti i segnali sono potenzialmente coalizzati se vengono inviati prima che possano essere elaborati.
Gilles 'SO- smetti di essere malvagio' il

C'è qualche misura di quanto è "troppo lungo" per i segnali SIGCHLD? Sto sperimentando questo comportamento nel mio programma in questo momento, e il mio gestore del segnale non impiega più di ~ 100ms, direi.
xrisk,

@Rishav - per quanto ne sappia, non c'è modo di scoprire che cosa sia "troppo lungo". Mi aspetto che il carico complessivo del sistema sia importante. Cioè, ciò che altri processi e il kernel stanno facendo influenzerebbe il "quanto tempo" tra i segnali affinché possano coalizzarsi. Non è una risposta utile, penso.
Bruce Ediger,

6

Un segnale è garantito per essere inviato, nel senso che se un processo chiama con successo kill, quindi il bersaglio riceverà il segnale. Questo è asincrono: il mittente non ha modo di sapere quando il segnale viene ricevuto o elaborato. Tuttavia, ciò non garantisce che il segnale verrà inviato. Il bersaglio potrebbe morire prima di poter elaborare il segnale. Se il bersaglio ignora il segnale al momento della consegna, il segnale non avrà alcun effetto. Se il target riceve più istanze dello stesso numero di segnale prima di poterle elaborare, i segnali possono (e di solito sono) uniti: se si invia lo stesso segnale due volte a un processo, non è possibile sapere se il processo riceverà il segnale una volta o due. I segnali sono principalmente progettati per uccidere un processo o come un modo per fare attenzione a un processo, non sono progettati per la comunicazione in quanto tale.

Se hai bisogno di una consegna affidabile, hai bisogno di un diverso meccanismo di comunicazione. Esistono due principali meccanismi di comunicazione tra i processi: una pipe consente la comunicazione unidirezionale; un socket consente la comunicazione bidirezionale e connessioni multiple allo stesso server. Se è necessario che la destinazione elabori tutte le notifiche che si inviano, inviare byte su una pipe.


4
Intendevi scrivere "Un segnale è garantito per essere inviato" poiché hai continuato a descrivere alcuni dei modi in cui il segnale non sarebbe stato inviato (cioè il processo è morto prima che fosse ricevuto o i segnali fossero coalizzati)?
Johnny,

2

Il kernel è libero di fondere segnali standard se più di uno viene consegnato mentre è bloccato. I segnali in tempo reale invece non sono portatori di handicap simili.

Dalla pagina di manuale del segnale (7) :

I segnali in tempo reale si distinguono per quanto segue:

  1. È possibile mettere in coda più istanze di segnali in tempo reale. Al contrario, se più istanze di un segnale standard vengono inviate mentre quel segnale è attualmente bloccato, viene messa in coda solo un'istanza.

Prova a utilizzare un segnale con un numero compreso nell'intervallo da SIGRTMIN a SIGRTMAX.


C'è un limite per i segnali in tempo reale, ma è piuttosto alto. Un segnale verrà eliminato se il numero di segnali in sospeso in sospeso inviati dall'utente supera RLIMIT_SIGPENDING. ulimit -imostra questo valore come 63432 su Ubuntu 18.04.
Guadagna il
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.